GeezerVison is showing github.com — repl: fix overzealous top-level await · nodejs/node@aba9c8e
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: lib/internal/repl/await.js +10-2Lines changed: 10 additions & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -237,8 +237,16 @@ function processTopLevelAwait(src) { | 237 | 237 | // semicolon. Since there can only be more right parentheses between | 238 | 238 | // node.expression.end and the semicolon, appending one more to | 239 | 239 | // 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, ') }'); | 242 | 250 | } | 243 | 251 | break; | 244 | 252 | } | |
Collapse file Copy file name to clipboardExpand all lines: lib/repl.js +1-1Lines changed: 1 addition & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -616,7 +616,7 @@ function REPLServer(prompt, | 616 | 616 |
| 617 | 617 | (async () => { | 618 | 618 | try { | 619 | | - const result = await promise; | | 619 | + const result = (await promise)?.value; | 620 | 620 | finishExecution(null, result); | 621 | 621 | } catch (err) { | 622 | 622 | if (err && process.domain) { | |
Collapse file 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 number | Diff line number | Diff line change |
|---|
@@ -17,25 +17,25 @@ const testCases = [ | 17 | 17 | [ '0', | 18 | 18 | null ], | 19 | 19 | [ 'await 0', | 20 | | - '(async () => { return (await 0) })()' ], | | 20 | + '(async () => { return { value: (await 0) } })()' ], | 21 | 21 | [ `await ${surrogate}`, | 22 | | - `(async () => { return (await ${surrogate}) })()` ], | | 22 | + `(async () => { return { value: (await ${surrogate}) } })()` ], | 23 | 23 | [ 'await 0;', | 24 | | - '(async () => { return (await 0); })()' ], | | 24 | + '(async () => { return { value: (await 0) }; })()' ], | 25 | 25 | [ 'await 0;;;', | 26 | | - '(async () => { return (await 0);;; })()' ], | | 26 | + '(async () => { return { value: (await 0) };;; })()' ], | 27 | 27 | [ `await ${surrogate};`, | 28 | | - `(async () => { return (await ${surrogate}); })()` ], | | 28 | + `(async () => { return { value: (await ${surrogate}) }; })()` ], | 29 | 29 | [ `await ${surrogate};`, | 30 | | - `(async () => { return (await ${surrogate}); })()` ], | | 30 | + `(async () => { return { value: (await ${surrogate}) }; })()` ], | 31 | 31 | [ '(await 0)', | 32 | | - '(async () => { return ((await 0)) })()' ], | | 32 | + '(async () => { return ({ value: (await 0) }) })()' ], | 33 | 33 | [ `(await ${surrogate})`, | 34 | | - `(async () => { return ((await ${surrogate})) })()` ], | | 34 | + `(async () => { return ({ value: (await ${surrogate}) }) })()` ], | 35 | 35 | [ '(await 0);', | 36 | | - '(async () => { return ((await 0)); })()' ], | | 36 | + '(async () => { return ({ value: (await 0) }); })()' ], | 37 | 37 | [ `(await ${surrogate});`, | 38 | | - `(async () => { return ((await ${surrogate})); })()` ], | | 38 | + `(async () => { return ({ value: (await ${surrogate}) }); })()` ], | 39 | 39 | [ 'async function foo() { await 0; }', | 40 | 40 | null ], | 41 | 41 | [ 'async () => await 0', | @@ -45,7 +45,7 @@ const testCases = [ | 45 | 45 | [ 'await 0; return 0;', | 46 | 46 | null ], | 47 | 47 | [ `await ${surrogate}; await ${surrogate};`, | 48 | | - `(async () => { await ${surrogate}; return (await ${surrogate}); })()` ], | | 48 | + `(async () => { await ${surrogate}; return { value: (await ${surrogate}) }; })()` ], | 49 | 49 | [ 'var a = await 1', | 50 | 50 | 'var a; (async () => { void (a = await 1) })()' ], | 51 | 51 | [ `var a = await ${surrogate}`, | @@ -71,7 +71,7 @@ const testCases = [ | 71 | 71 | ' ([{d}] = [{d: 3}])) })()'], | 72 | 72 | /* eslint-disable no-template-curly-in-string */ | 73 | 73 | [ '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}`)) } })()' ], | 75 | 75 | /* eslint-enable no-template-curly-in-string */ | 76 | 76 | [ 'await 0; function foo() {}', | 77 | 77 | 'var foo; (async () => { await 0; this.foo = foo; function foo() {} })()' ], | @@ -92,15 +92,15 @@ const testCases = [ | 92 | 92 | [ 'let o = await 1, p', | 93 | 93 | 'let o, p; (async () => { void ( (o = await 1), (p=undefined)) })()' ], | 94 | 94 | [ '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; })()) } })()' ], | 97 | 97 | [ '{ let p = await 1; }', | 98 | 98 | '(async () => { { let p = await 1; } })()' ], | 99 | 99 | [ 'var p = await 1', | 100 | 100 | 'var p; (async () => { void (p = await 1) })()' ], | 101 | 101 | [ '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; })()) } })()' ], | 104 | 104 | [ '{ var p = await 1; }', | 105 | 105 | 'var p; (async () => { { void (p = await 1); } })()' ], | 106 | 106 | [ 'for await (var i of asyncIterable) { i; }', | @@ -140,6 +140,10 @@ const testCases = [ | 140 | 140 | [ 'var x = await foo(); async function foo() { return Promise.resolve(1);}', | 141 | 141 | 'var x; var foo; (async () => { void (x = await foo()); this.foo = foo; ' + | 142 | 142 | '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) } })()'], | 143 | 147 | ]; | 144 | 148 |
| 145 | 149 | for (const [input, expected] of testCases) { | |
Collapse file Copy file name to clipboardExpand all lines: test/parallel/test-repl-top-level-await.js +4Lines changed: 4 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -182,6 +182,10 @@ async function ordinaryTests() { | 182 | 182 | '3', | 183 | 183 | 'undefined', | 184 | 184 | ]], | | 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'], | 185 | 189 | ]; | 186 | 190 |
| 187 | 191 | for (const [input, expected = [`${input}\r`], options = {}] of testCases) { | |
|