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 aba9c8e

Browse filesBrowse 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
Copy full SHA for aba9c8e

File tree

Expand file treeCollapse file tree

4 files changed

+35
-19
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

4 files changed

+35
-19
lines changed
Open diff view settings
Collapse file

‎lib/internal/repl/await.js‎

Copy file name to clipboardExpand all lines: lib/internal/repl/await.js
+10-2Lines changed: 10 additions & 2 deletions
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
}
Collapse file

‎lib/repl.js‎

Copy file name to clipboardExpand all lines: lib/repl.js
+1-1Lines changed: 1 addition & 1 deletion
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) {
Collapse file

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

Copy file name to clipboardExpand all lines: test/parallel/test-repl-preprocess-top-level-await.js
+20-16Lines changed: 20 additions & 16 deletions
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) {
Collapse file

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

Copy file name to clipboardExpand all lines: test/parallel/test-repl-top-level-await.js
+4Lines changed: 4 additions & 0 deletions
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 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.