Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit b26ec48

Browse filesBrowse files
authored
Fixed out of spec behavior of array.reduce (#731)
* Fixed out of spec behavior of array.reduce * Moved select declarations from ArrayReduce to lualib declaration files * Fixed issue in reduce with undefined returning callback * Changed reduce loop from while to for for performance reasons * Cleaned up code a little from PR feedback * testcase formatting
1 parent c1e77c9 commit b26ec48
Copy full SHA for b26ec48

4 files changed

+38-12Lines changed: 38 additions & 12 deletions

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎src/lualib/ArrayReduce.ts‎

Copy file name to clipboardExpand all lines: src/lualib/ArrayReduce.ts
+13-12Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,26 @@ function __TS__ArrayReduce<T>(
33
this: void,
44
arr: T[],
55
callbackFn: (accumulator: T, currentValue: T, index: number, array: T[]) => T,
6-
initial?: T
6+
...initial: Vararg<T>
77
): T {
88
const len = arr.length;
99

10-
if (len === 0 && initial === undefined) {
11-
// tslint:disable-next-line: no-string-throw
12-
throw "Reduce of empty array with no initial value";
13-
}
14-
1510
let k = 0;
16-
let accumulator = initial;
17-
if (initial === undefined) {
11+
let accumulator = undefined;
12+
13+
// Check if initial value is present in function call
14+
if (select("#", ...initial) !== 0) {
15+
accumulator = select(1, ...initial);
16+
} else if (len > 0) {
1817
accumulator = arr[0];
19-
k++;
18+
k = 1;
19+
} else {
20+
// tslint:disable-next-line: no-string-throw
21+
throw "Reduce of empty array with no initial value";
2022
}
2123

22-
while (k < len) {
23-
accumulator = callbackFn(accumulator, arr[k], k, arr);
24-
k = k + 1;
24+
for (const i of forRange(k, len - 1)) {
25+
accumulator = callbackFn(accumulator, arr[i], i, arr);
2526
}
2627

2728
return accumulator;
Collapse file

‎src/lualib/declarations/global.d.ts‎

Copy file name to clipboardExpand all lines: src/lualib/declarations/global.d.ts
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,6 @@ declare function rawset<T, K extends keyof T>(table: T, key: K, val: T[K]): void
1616
declare function next<K, V>(table: Record<any, V>, index?: K): [K, V];
1717
declare function pcall(func: () => any): any;
1818
declare function unpack<T>(list: T[], i?: number, j?: number): T[];
19+
20+
declare function select<T>(index: number, ...args: T[]): T;
21+
declare function select<T>(index: "#", ...args: T[]): number;
Collapse file

‎src/lualib/declarations/tstl.d.ts‎

Copy file name to clipboardExpand all lines: src/lualib/declarations/tstl.d.ts
+6Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
/** @noSelfInFile */
22

3+
/** @vararg */
4+
interface Vararg<T> extends Array<T> {}
5+
6+
/** @forRange */
7+
declare function forRange(start: number, limit: number, step?: number): number[];
8+
39
interface LuaClass {
410
prototype: LuaObject;
511
____super?: LuaClass;
Collapse file

‎test/unit/builtins/array.spec.ts‎

Copy file name to clipboardExpand all lines: test/unit/builtins/array.spec.ts
+16Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,22 @@ test.each<[[(total: number, currentItem: number, index: number, array: number[])
486486
util.testExpression`[1, 3, 5, 7].reduce(${util.valuesToString(args)})`.expectToMatchJsResult();
487487
});
488488

489+
test("array.reduce empty undefined initial", () => {
490+
util.testExpression`[].reduce(() => {}, undefined)`.expectToMatchJsResult();
491+
});
492+
493+
test("array.reduce empty no initial", () => {
494+
util.testExpression`[].reduce(() => {})`.expectToMatchJsResult(true);
495+
});
496+
497+
test("array.reduce undefined returning callback", () => {
498+
util.testFunction`
499+
const calls: Array<{ a: void, b: string }> = [];
500+
["a", "b"].reduce<void>((a, b) => { calls.push({ a, b }) }, undefined);
501+
return calls;
502+
`.expectToMatchJsResult();
503+
});
504+
489505
const genericChecks = [
490506
"function generic<T extends number[]>(array: T)",
491507
"function generic<T extends [...number[]]>(array: T)",

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.