diff --git a/src/LuaLib.ts b/src/LuaLib.ts index 1e5332caa..8826abf95 100644 --- a/src/LuaLib.ts +++ b/src/LuaLib.ts @@ -9,6 +9,7 @@ export enum LuaLibFeature { ArrayConcat = "ArrayConcat", ArrayEntries = "ArrayEntries", ArrayEvery = "ArrayEvery", + ArrayFill = "ArrayFill", ArrayFilter = "ArrayFilter", ArrayForEach = "ArrayForEach", ArrayFind = "ArrayFind", diff --git a/src/lualib/ArrayFill.ts b/src/lualib/ArrayFill.ts new file mode 100644 index 000000000..a1654114a --- /dev/null +++ b/src/lualib/ArrayFill.ts @@ -0,0 +1,19 @@ +// https://tc39.es/ecma262/multipage/indexed-collections.html#sec-array.prototype.fill +export function __TS__ArrayFill(this: T[], value: T, start?: number, end?: number): T[] { + let relativeStart = start ?? 0; + let relativeEnd = end ?? this.length; + + if (relativeStart < 0) { + relativeStart += this.length; + } + + if (relativeEnd < 0) { + relativeEnd += this.length; + } + + for (let i = relativeStart; i < relativeEnd; i++) { + this[i] = value; + } + + return this; +} diff --git a/src/transformation/builtins/array.ts b/src/transformation/builtins/array.ts index 53dbc653d..b22bff01d 100644 --- a/src/transformation/builtins/array.ts +++ b/src/transformation/builtins/array.ts @@ -94,6 +94,8 @@ export function transformArrayPrototypeCall( return transformLuaLibFunction(context, LuaLibFeature.ArrayConcat, node, caller, ...params); case "entries": return transformLuaLibFunction(context, LuaLibFeature.ArrayEntries, node, caller); + case "fill": + return transformLuaLibFunction(context, LuaLibFeature.ArrayFill, node, caller, ...params); case "push": if (node.arguments.length === 1) { const param = params[0] ?? lua.createNilLiteral(); diff --git a/test/unit/builtins/array.spec.ts b/test/unit/builtins/array.spec.ts index 05d499395..a59d1ee04 100644 --- a/test/unit/builtins/array.spec.ts +++ b/test/unit/builtins/array.spec.ts @@ -788,6 +788,33 @@ test.each([ util.testExpression(literal).expectToHaveNoDiagnostics(); }); +describe("array.fill", () => { + test.each(["[]", "[1]", "[1,2,3,4]"])("Fills full length of array without other parameters (%p)", arr => { + util.testExpression`${arr}.fill(5)`.expectToMatchJsResult(); + }); + + test.each(["[1,2,3]", "[1,2,3,4,5,6]"])("Fills starting from start parameter (%p)", arr => { + util.testExpression`${arr}.fill(5, 3)`.expectToMatchJsResult(); + }); + + test("handles negative start parameter", () => { + util.testExpression`[1,2,3,4,5,6,7].fill(8, -3)`.expectToMatchJsResult(); + }); + + test("handles negative end parameter", () => { + util.testExpression`[1,2,3,4,5,6,7].fill(8, -5, -2)`.expectToMatchJsResult(); + }); + + test("Fills starting from start parameter, up to ending parameter", () => { + util.testExpression`[1,2,3,4,5,6,7,8].fill(5, 2, 6)`.expectToMatchJsResult(); + }); + + // NOTE: This is different from the default ECMAScript specification for the behavior, but for Lua this is much more useful + test("Extends size of the array if ending size is larger than array", () => { + util.testExpression`[1,2,3].fill(5, 0, 6)`.expectToEqual([5, 5, 5, 5, 5, 5]); + }); +}); + // Issue #1218: https://github.com/TypeScriptToLua/TypeScriptToLua/issues/1218 test.each(["[1, 2, 3]", "undefined"])("prototype call on nullable array (%p)", value => { util.testFunction`