Skip to content

Commit aba9c8e

Browse files
tniessendanielleadams
authored andcommitted
repl: fix overzealous top-level await
Fixes: #43777 PR-URL: #43827 Reviewed-By: Guy Bedford <guybedford@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
1 parent ec7e45e commit aba9c8e

File tree

4 files changed

+35
-19
lines changed

4 files changed

+35
-19
lines changed

lib/internal/repl/await.js

+10-2
Original file line numberDiff line numberDiff line change
@@ -237,8 +237,16 @@ function processTopLevelAwait(src) {
237237
// semicolon. Since there can only be more right parentheses between
238238
// node.expression.end and the semicolon, appending one more to
239239
// node.expression should be fine.
240-
state.prepend(node, 'return (');
241-
state.append(node.expression, ')');
240+
//
241+
// We also create a wrapper object around the result of the expression.
242+
// Consider an expression of the form `(await x).y`. If we just return
243+
// this expression from an async function, the caller will await `y`, too,
244+
// if it evaluates to a Promise. Instead, we return
245+
// `{ value: ((await x).y) }`, which allows the caller to retrieve the
246+
// awaited value correctly.
247+
state.prepend(node.expression, '{ value: (');
248+
state.prepend(node, 'return ');
249+
state.append(node.expression, ') }');
242250
}
243251
break;
244252
}

lib/repl.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -616,7 +616,7 @@ function REPLServer(prompt,
616616

617617
(async () => {
618618
try {
619-
const result = await promise;
619+
const result = (await promise)?.value;
620620
finishExecution(null, result);
621621
} catch (err) {
622622
if (err && process.domain) {

test/parallel/test-repl-preprocess-top-level-await.js

+20-16
Original file line numberDiff line numberDiff line change
@@ -17,25 +17,25 @@ const testCases = [
1717
[ '0',
1818
null ],
1919
[ 'await 0',
20-
'(async () => { return (await 0) })()' ],
20+
'(async () => { return { value: (await 0) } })()' ],
2121
[ `await ${surrogate}`,
22-
`(async () => { return (await ${surrogate}) })()` ],
22+
`(async () => { return { value: (await ${surrogate}) } })()` ],
2323
[ 'await 0;',
24-
'(async () => { return (await 0); })()' ],
24+
'(async () => { return { value: (await 0) }; })()' ],
2525
[ 'await 0;;;',
26-
'(async () => { return (await 0);;; })()' ],
26+
'(async () => { return { value: (await 0) };;; })()' ],
2727
[ `await ${surrogate};`,
28-
`(async () => { return (await ${surrogate}); })()` ],
28+
`(async () => { return { value: (await ${surrogate}) }; })()` ],
2929
[ `await ${surrogate};`,
30-
`(async () => { return (await ${surrogate}); })()` ],
30+
`(async () => { return { value: (await ${surrogate}) }; })()` ],
3131
[ '(await 0)',
32-
'(async () => { return ((await 0)) })()' ],
32+
'(async () => { return ({ value: (await 0) }) })()' ],
3333
[ `(await ${surrogate})`,
34-
`(async () => { return ((await ${surrogate})) })()` ],
34+
`(async () => { return ({ value: (await ${surrogate}) }) })()` ],
3535
[ '(await 0);',
36-
'(async () => { return ((await 0)); })()' ],
36+
'(async () => { return ({ value: (await 0) }); })()' ],
3737
[ `(await ${surrogate});`,
38-
`(async () => { return ((await ${surrogate})); })()` ],
38+
`(async () => { return ({ value: (await ${surrogate}) }); })()` ],
3939
[ 'async function foo() { await 0; }',
4040
null ],
4141
[ 'async () => await 0',
@@ -45,7 +45,7 @@ const testCases = [
4545
[ 'await 0; return 0;',
4646
null ],
4747
[ `await ${surrogate}; await ${surrogate};`,
48-
`(async () => { await ${surrogate}; return (await ${surrogate}); })()` ],
48+
`(async () => { await ${surrogate}; return { value: (await ${surrogate}) }; })()` ],
4949
[ 'var a = await 1',
5050
'var a; (async () => { void (a = await 1) })()' ],
5151
[ `var a = await ${surrogate}`,
@@ -71,7 +71,7 @@ const testCases = [
7171
' ([{d}] = [{d: 3}])) })()'],
7272
/* eslint-disable no-template-curly-in-string */
7373
[ 'console.log(`${(await { a: 1 }).a}`)',
74-
'(async () => { return (console.log(`${(await { a: 1 }).a}`)) })()' ],
74+
'(async () => { return { value: (console.log(`${(await { a: 1 }).a}`)) } })()' ],
7575
/* eslint-enable no-template-curly-in-string */
7676
[ 'await 0; function foo() {}',
7777
'var foo; (async () => { await 0; this.foo = foo; function foo() {} })()' ],
@@ -92,15 +92,15 @@ const testCases = [
9292
[ 'let o = await 1, p',
9393
'let o, p; (async () => { void ( (o = await 1), (p=undefined)) })()' ],
9494
[ 'await (async () => { let p = await 1; return p; })()',
95-
'(async () => { return (await (async () => ' +
96-
'{ let p = await 1; return p; })()) })()' ],
95+
'(async () => { return { value: (await (async () => ' +
96+
'{ let p = await 1; return p; })()) } })()' ],
9797
[ '{ let p = await 1; }',
9898
'(async () => { { let p = await 1; } })()' ],
9999
[ 'var p = await 1',
100100
'var p; (async () => { void (p = await 1) })()' ],
101101
[ 'await (async () => { var p = await 1; return p; })()',
102-
'(async () => { return (await (async () => ' +
103-
'{ var p = await 1; return p; })()) })()' ],
102+
'(async () => { return { value: (await (async () => ' +
103+
'{ var p = await 1; return p; })()) } })()' ],
104104
[ '{ var p = await 1; }',
105105
'var p; (async () => { { void (p = await 1); } })()' ],
106106
[ 'for await (var i of asyncIterable) { i; }',
@@ -140,6 +140,10 @@ const testCases = [
140140
[ 'var x = await foo(); async function foo() { return Promise.resolve(1);}',
141141
'var x; var foo; (async () => { void (x = await foo()); this.foo = foo; ' +
142142
'async function foo() { return Promise.resolve(1);} })()'],
143+
[ '(await x).y',
144+
'(async () => { return { value: ((await x).y) } })()'],
145+
[ 'await (await x).y',
146+
'(async () => { return { value: (await (await x).y) } })()'],
143147
];
144148

145149
for (const [input, expected] of testCases) {

test/parallel/test-repl-top-level-await.js

+4
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,10 @@ async function ordinaryTests() {
182182
'3',
183183
'undefined',
184184
]],
185+
// Regression test for https://github.com/nodejs/node/issues/43777.
186+
['await Promise.resolve(123), Promise.resolve(456)', 'Promise {', { line: 0 }],
187+
['await Promise.resolve(123), await Promise.resolve(456)', '456'],
188+
['await (Promise.resolve(123), Promise.resolve(456))', '456'],
185189
];
186190

187191
for (const [input, expected = [`${input}\r`], options = {}] of testCases) {

0 commit comments

Comments
 (0)