Skip to content

Commit 4b3162b

Browse files
committed
(lualib): update Promise.prototype.finally to correctly handle onFinally errors and rejected
1 parent 4855d04 commit 4b3162b

2 files changed

Lines changed: 49 additions & 12 deletions

File tree

src/lualib/Promise.ts

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -125,20 +125,17 @@ export class __TS__Promise<T> implements Promise<T> {
125125
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/finally
126126
// Delegates to .then() so that a new Promise is returned (per ES spec §27.2.5.3)
127127
// and the original fulfillment value / rejection reason is preserved.
128+
// reference: https://github.com/tc39/proposal-promise-finally/blob/fd934c0b42d59bf8d9446e737ba14d50a9067216/polyfill.js#L34-L41
128129
public finally(onFinally?: () => void): Promise<T> {
130+
if (typeof onFinally !== "function") {
131+
return this.then(onFinally, onFinally);
132+
}
129133
return this.then(
130-
onFinally
131-
? (value: T): T => {
132-
onFinally();
133-
return value;
134-
}
135-
: undefined,
136-
onFinally
137-
? (reason: any): never => {
138-
onFinally();
139-
throw reason;
140-
}
141-
: undefined
134+
x => new __TS__Promise(resolve => resolve(onFinally())).then(() => x),
135+
e =>
136+
new __TS__Promise(resolve => resolve(onFinally())).then(() => {
137+
throw e;
138+
})
142139
);
143140
}
144141

test/unit/builtins/promise.spec.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1370,4 +1370,44 @@ describe("Promise.finally", () => {
13701370
return result.value;
13711371
`.expectToEqual(99);
13721372
});
1373+
1374+
test("finally throw overrides fulfillment value", () => {
1375+
util.testModule`
1376+
let result: any;
1377+
Promise.resolve("ok")
1378+
.finally(() => { throw "finally-error"; })
1379+
.then(v => { result = v; }, e => { result = e; });
1380+
export const output = result;
1381+
`.expectToEqual({ output: "finally-error" });
1382+
});
1383+
1384+
test("finally throw overrides rejection reason", () => {
1385+
util.testModule`
1386+
let result: any;
1387+
Promise.reject("original")
1388+
.finally(() => { throw "finally-error"; })
1389+
.then(v => { result = v; }, e => { result = e; });
1390+
export const output = result;
1391+
`.expectToEqual({ output: "finally-error" });
1392+
});
1393+
1394+
test("finally returning rejected promise overrides fulfillment", () => {
1395+
util.testModule`
1396+
let result: any;
1397+
Promise.resolve("ok")
1398+
.finally(() => Promise.reject("finally-rejected") as any)
1399+
.then(v => { result = v; }, e => { result = e; });
1400+
export const output = result;
1401+
`.expectToEqual({ output: "finally-rejected" });
1402+
});
1403+
1404+
test("finally returning rejected promise overrides rejection", () => {
1405+
util.testModule`
1406+
let result: any;
1407+
Promise.reject("original")
1408+
.finally(() => Promise.reject("finally-rejected") as any)
1409+
.then(v => { result = v; }, e => { result = e; });
1410+
export const output = result;
1411+
`.expectToEqual({ output: "finally-rejected" });
1412+
});
13731413
});

0 commit comments

Comments
 (0)