Skip to content

Commit f742949

Browse files
authored
Implement Array.from and Array.of (#1240)
1 parent baa826d commit f742949

File tree

5 files changed

+59
-2
lines changed

5 files changed

+59
-2
lines changed

src/LuaLib.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export enum LuaLibFeature {
1010
ArrayForEach = "ArrayForEach",
1111
ArrayFind = "ArrayFind",
1212
ArrayFindIndex = "ArrayFindIndex",
13+
ArrayFrom = "ArrayFrom",
1314
ArrayIncludes = "ArrayIncludes",
1415
ArrayIndexOf = "ArrayIndexOf",
1516
ArrayIsArray = "ArrayIsArray",

src/lualib/ArrayFrom.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/** @noSelfInFile */
2+
3+
import { __TS__Iterator } from "./Iterator";
4+
5+
function arrayLikeStep(this: ArrayLike<unknown>, index: number): LuaMultiReturn<[number, unknown] | []> {
6+
index += 1;
7+
if (index > this.length) return $multi();
8+
return $multi(index, this[index]);
9+
}
10+
11+
const arrayLikeIterator: (
12+
this: void,
13+
arr: ArrayLike<unknown> | Iterable<unknown>
14+
) => LuaIterable<LuaMultiReturn<[number, unknown]>> = (arr => {
15+
if (typeof arr.length === "number") return $multi(arrayLikeStep, arr, 0);
16+
return __TS__Iterator(arr);
17+
}) as any;
18+
19+
export function __TS__ArrayFrom(
20+
this: void,
21+
arrayLike: ArrayLike<unknown> | Iterable<unknown>,
22+
mapFn?: (this: unknown, element: unknown, index: number) => unknown,
23+
thisArg?: unknown
24+
): unknown[] {
25+
const result = [];
26+
if (mapFn === undefined) {
27+
for (const [, v] of arrayLikeIterator(arrayLike)) {
28+
result.push(v);
29+
}
30+
} else {
31+
for (const [i, v] of arrayLikeIterator(arrayLike)) {
32+
result.push(mapFn.call(thisArg, v, i - 1));
33+
}
34+
}
35+
return result;
36+
}

src/lualib/tsconfig.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,6 @@
1313
"luaLibImport": "none",
1414
"noHeader": true,
1515
"luaPlugins": [{ "name": "../../dist/lualib-build/plugin.js" }]
16-
}
16+
},
17+
"include": [".", "../../language-extensions/index.d.ts"]
1718
}

src/transformation/builtins/array.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,24 @@ import { unsupportedProperty } from "../utils/diagnostics";
55
import { LuaLibFeature, transformLuaLibFunction } from "../utils/lualib";
66
import { PropertyCallExpression, transformArguments, transformCallAndArguments } from "../visitors/call";
77
import { isStringType, isNumberType } from "../utils/typescript";
8+
import { wrapInTable } from "../utils/lua-ast";
89

910
export function transformArrayConstructorCall(
1011
context: TransformationContext,
1112
node: PropertyCallExpression
12-
): lua.CallExpression | undefined {
13+
): lua.Expression | undefined {
1314
const expression = node.expression;
1415
const signature = context.checker.getResolvedSignature(node);
1516
const params = transformArguments(context, node.arguments, signature);
1617

1718
const expressionName = expression.name.text;
1819
switch (expressionName) {
20+
case "from":
21+
return transformLuaLibFunction(context, LuaLibFeature.ArrayFrom, node, ...params);
1922
case "isArray":
2023
return transformLuaLibFunction(context, LuaLibFeature.ArrayIsArray, node, ...params);
24+
case "of":
25+
return wrapInTable(...params);
2126
default:
2227
context.diagnostics.push(unsupportedProperty(expression.name, "Array", expressionName));
2328
}

test/unit/builtins/array.spec.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,20 @@ test("Array.isArray returns true for empty objects", () => {
671671
util.testExpression`Array.isArray({})`.expectToEqual(true);
672672
});
673673

674+
test.each([
675+
"[1, 2, 3]",
676+
"(new Set([1, 2, 3])).values()",
677+
"[1, 2, 3], value => value * 2",
678+
"{ length: 3 }, (_, index) => index + 1",
679+
])("Array.from(%p)", valueString => {
680+
util.testExpression`Array.from(${valueString})`.expectToMatchJsResult();
681+
});
682+
683+
// Array.of
684+
test.each(["1, 2, 3", "", "...[1, 2, 3], 4, 5, 6"])("Array.of(%p)", valueString => {
685+
util.testExpression`Array.of(${valueString})`.expectToMatchJsResult();
686+
});
687+
674688
// Test fix for https://github.com/TypeScriptToLua/TypeScriptToLua/issues/738
675689
test("array.prototype.concat issue #738", () => {
676690
util.testExpression`([] as any[]).concat(13, 323, {x: 3}, [2, 3])`.expectToMatchJsResult();

0 commit comments

Comments
 (0)