11cb0ef41Sopenharmony_ci'use strict'; 21cb0ef41Sopenharmony_ci 31cb0ef41Sopenharmony_ciconst common = require('../common'); 41cb0ef41Sopenharmony_ciconst ArrayStream = require('../common/arraystream'); 51cb0ef41Sopenharmony_ciconst assert = require('assert'); 61cb0ef41Sopenharmony_ciconst events = require('events'); 71cb0ef41Sopenharmony_ciconst { stripVTControlCharacters } = require('internal/util/inspect'); 81cb0ef41Sopenharmony_ciconst repl = require('repl'); 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_cicommon.skipIfInspectorDisabled(); 111cb0ef41Sopenharmony_ci 121cb0ef41Sopenharmony_ci// Flags: --expose-internals 131cb0ef41Sopenharmony_ci 141cb0ef41Sopenharmony_ciconst PROMPT = 'await repl > '; 151cb0ef41Sopenharmony_ci 161cb0ef41Sopenharmony_ciclass REPLStream extends ArrayStream { 171cb0ef41Sopenharmony_ci constructor() { 181cb0ef41Sopenharmony_ci super(); 191cb0ef41Sopenharmony_ci this.waitingForResponse = false; 201cb0ef41Sopenharmony_ci this.lines = ['']; 211cb0ef41Sopenharmony_ci } 221cb0ef41Sopenharmony_ci write(chunk, encoding, callback) { 231cb0ef41Sopenharmony_ci if (Buffer.isBuffer(chunk)) { 241cb0ef41Sopenharmony_ci chunk = chunk.toString(encoding); 251cb0ef41Sopenharmony_ci } 261cb0ef41Sopenharmony_ci const chunkLines = stripVTControlCharacters(chunk).split('\n'); 271cb0ef41Sopenharmony_ci this.lines[this.lines.length - 1] += chunkLines[0]; 281cb0ef41Sopenharmony_ci if (chunkLines.length > 1) { 291cb0ef41Sopenharmony_ci this.lines.push(...chunkLines.slice(1)); 301cb0ef41Sopenharmony_ci } 311cb0ef41Sopenharmony_ci this.emit('line', this.lines[this.lines.length - 1]); 321cb0ef41Sopenharmony_ci if (callback) callback(); 331cb0ef41Sopenharmony_ci return true; 341cb0ef41Sopenharmony_ci } 351cb0ef41Sopenharmony_ci 361cb0ef41Sopenharmony_ci async wait() { 371cb0ef41Sopenharmony_ci if (this.waitingForResponse) { 381cb0ef41Sopenharmony_ci throw new Error('Currently waiting for response to another command'); 391cb0ef41Sopenharmony_ci } 401cb0ef41Sopenharmony_ci this.lines = ['']; 411cb0ef41Sopenharmony_ci for await (const [line] of events.on(this, 'line')) { 421cb0ef41Sopenharmony_ci if (line.includes(PROMPT)) { 431cb0ef41Sopenharmony_ci return this.lines; 441cb0ef41Sopenharmony_ci } 451cb0ef41Sopenharmony_ci } 461cb0ef41Sopenharmony_ci } 471cb0ef41Sopenharmony_ci} 481cb0ef41Sopenharmony_ci 491cb0ef41Sopenharmony_ciconst putIn = new REPLStream(); 501cb0ef41Sopenharmony_ciconst testMe = repl.start({ 511cb0ef41Sopenharmony_ci prompt: PROMPT, 521cb0ef41Sopenharmony_ci stream: putIn, 531cb0ef41Sopenharmony_ci terminal: true, 541cb0ef41Sopenharmony_ci useColors: true, 551cb0ef41Sopenharmony_ci breakEvalOnSigint: true 561cb0ef41Sopenharmony_ci}); 571cb0ef41Sopenharmony_ci 581cb0ef41Sopenharmony_cifunction runAndWait(cmds) { 591cb0ef41Sopenharmony_ci const promise = putIn.wait(); 601cb0ef41Sopenharmony_ci for (const cmd of cmds) { 611cb0ef41Sopenharmony_ci if (typeof cmd === 'string') { 621cb0ef41Sopenharmony_ci putIn.run([cmd]); 631cb0ef41Sopenharmony_ci } else { 641cb0ef41Sopenharmony_ci testMe.write('', cmd); 651cb0ef41Sopenharmony_ci } 661cb0ef41Sopenharmony_ci } 671cb0ef41Sopenharmony_ci return promise; 681cb0ef41Sopenharmony_ci} 691cb0ef41Sopenharmony_ci 701cb0ef41Sopenharmony_ciasync function ordinaryTests() { 711cb0ef41Sopenharmony_ci // These tests were created based on 721cb0ef41Sopenharmony_ci // https://cs.chromium.org/chromium/src/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-top-level-await.js?rcl=5d0ea979f0ba87655b7ef0e03b58fa3c04986ba6 731cb0ef41Sopenharmony_ci putIn.run([ 741cb0ef41Sopenharmony_ci 'function foo(x) { return x; }', 751cb0ef41Sopenharmony_ci 'function koo() { return Promise.resolve(4); }', 761cb0ef41Sopenharmony_ci ]); 771cb0ef41Sopenharmony_ci const testCases = [ 781cb0ef41Sopenharmony_ci ['await Promise.resolve(0)', '0'], 791cb0ef41Sopenharmony_ci ['{ a: await Promise.resolve(1) }', '{ a: 1 }'], 801cb0ef41Sopenharmony_ci ['_', '{ a: 1 }'], 811cb0ef41Sopenharmony_ci ['let { aa, bb } = await Promise.resolve({ aa: 1, bb: 2 }), f = 5;'], 821cb0ef41Sopenharmony_ci ['aa', '1'], 831cb0ef41Sopenharmony_ci ['bb', '2'], 841cb0ef41Sopenharmony_ci ['f', '5'], 851cb0ef41Sopenharmony_ci ['let cc = await Promise.resolve(2)'], 861cb0ef41Sopenharmony_ci ['cc', '2'], 871cb0ef41Sopenharmony_ci ['let dd;'], 881cb0ef41Sopenharmony_ci ['dd'], 891cb0ef41Sopenharmony_ci ['let [ii, { abc: { kk } }] = [0, { abc: { kk: 1 } }];'], 901cb0ef41Sopenharmony_ci ['ii', '0'], 911cb0ef41Sopenharmony_ci ['kk', '1'], 921cb0ef41Sopenharmony_ci ['var ll = await Promise.resolve(2);'], 931cb0ef41Sopenharmony_ci ['ll', '2'], 941cb0ef41Sopenharmony_ci ['foo(await koo())', '4'], 951cb0ef41Sopenharmony_ci ['_', '4'], 961cb0ef41Sopenharmony_ci ['const m = foo(await koo());'], 971cb0ef41Sopenharmony_ci ['m', '4'], 981cb0ef41Sopenharmony_ci ['const n = foo(await\nkoo());', 991cb0ef41Sopenharmony_ci ['const n = foo(await\r', '... koo());\r', 'undefined']], 1001cb0ef41Sopenharmony_ci ['n', '4'], 1011cb0ef41Sopenharmony_ci // eslint-disable-next-line no-template-curly-in-string 1021cb0ef41Sopenharmony_ci ['`status: ${(await Promise.resolve({ status: 200 })).status}`', 1031cb0ef41Sopenharmony_ci "'status: 200'"], 1041cb0ef41Sopenharmony_ci ['for (let i = 0; i < 2; ++i) await i'], 1051cb0ef41Sopenharmony_ci ['for (let i = 0; i < 2; ++i) { await i }'], 1061cb0ef41Sopenharmony_ci ['await 0', '0'], 1071cb0ef41Sopenharmony_ci ['await 0; function foo() {}'], 1081cb0ef41Sopenharmony_ci ['foo', '[Function: foo]'], 1091cb0ef41Sopenharmony_ci ['class Foo {}; await 1;', '1'], 1101cb0ef41Sopenharmony_ci ['Foo', '[class Foo]'], 1111cb0ef41Sopenharmony_ci ['if (await true) { function bar() {}; }'], 1121cb0ef41Sopenharmony_ci ['bar', '[Function: bar]'], 1131cb0ef41Sopenharmony_ci ['if (await true) { class Bar {}; }'], 1141cb0ef41Sopenharmony_ci ['Bar', 'Uncaught ReferenceError: Bar is not defined'], 1151cb0ef41Sopenharmony_ci ['await 0; function* gen(){}'], 1161cb0ef41Sopenharmony_ci ['for (var i = 0; i < 10; ++i) { await i; }'], 1171cb0ef41Sopenharmony_ci ['i', '10'], 1181cb0ef41Sopenharmony_ci ['for (let j = 0; j < 5; ++j) { await j; }'], 1191cb0ef41Sopenharmony_ci ['j', 'Uncaught ReferenceError: j is not defined', { line: 0 }], 1201cb0ef41Sopenharmony_ci ['gen', '[GeneratorFunction: gen]'], 1211cb0ef41Sopenharmony_ci ['return 42; await 5;', 'Uncaught SyntaxError: Illegal return statement', 1221cb0ef41Sopenharmony_ci { line: 3 }], 1231cb0ef41Sopenharmony_ci ['let o = await 1, p'], 1241cb0ef41Sopenharmony_ci ['p'], 1251cb0ef41Sopenharmony_ci ['let q = 1, s = await 2'], 1261cb0ef41Sopenharmony_ci ['s', '2'], 1271cb0ef41Sopenharmony_ci ['for await (let i of [1,2,3]) console.log(i)', 1281cb0ef41Sopenharmony_ci [ 1291cb0ef41Sopenharmony_ci 'for await (let i of [1,2,3]) console.log(i)\r', 1301cb0ef41Sopenharmony_ci '1', 1311cb0ef41Sopenharmony_ci '2', 1321cb0ef41Sopenharmony_ci '3', 1331cb0ef41Sopenharmony_ci 'undefined', 1341cb0ef41Sopenharmony_ci ], 1351cb0ef41Sopenharmony_ci ], 1361cb0ef41Sopenharmony_ci ['await Promise..resolve()', 1371cb0ef41Sopenharmony_ci [ 1381cb0ef41Sopenharmony_ci 'await Promise..resolve()\r', 1391cb0ef41Sopenharmony_ci 'Uncaught SyntaxError: ', 1401cb0ef41Sopenharmony_ci 'await Promise..resolve()', 1411cb0ef41Sopenharmony_ci ' ^', 1421cb0ef41Sopenharmony_ci '', 1431cb0ef41Sopenharmony_ci 'Unexpected token \'.\'', 1441cb0ef41Sopenharmony_ci ], 1451cb0ef41Sopenharmony_ci ], 1461cb0ef41Sopenharmony_ci ['for (const x of [1,2,3]) {\nawait x\n}', [ 1471cb0ef41Sopenharmony_ci 'for (const x of [1,2,3]) {\r', 1481cb0ef41Sopenharmony_ci '... await x\r', 1491cb0ef41Sopenharmony_ci '... }\r', 1501cb0ef41Sopenharmony_ci 'undefined', 1511cb0ef41Sopenharmony_ci ]], 1521cb0ef41Sopenharmony_ci ['for (const x of [1,2,3]) {\nawait x;\n}', [ 1531cb0ef41Sopenharmony_ci 'for (const x of [1,2,3]) {\r', 1541cb0ef41Sopenharmony_ci '... await x;\r', 1551cb0ef41Sopenharmony_ci '... }\r', 1561cb0ef41Sopenharmony_ci 'undefined', 1571cb0ef41Sopenharmony_ci ]], 1581cb0ef41Sopenharmony_ci ['for await (const x of [1,2,3]) {\nconsole.log(x)\n}', [ 1591cb0ef41Sopenharmony_ci 'for await (const x of [1,2,3]) {\r', 1601cb0ef41Sopenharmony_ci '... console.log(x)\r', 1611cb0ef41Sopenharmony_ci '... }\r', 1621cb0ef41Sopenharmony_ci '1', 1631cb0ef41Sopenharmony_ci '2', 1641cb0ef41Sopenharmony_ci '3', 1651cb0ef41Sopenharmony_ci 'undefined', 1661cb0ef41Sopenharmony_ci ]], 1671cb0ef41Sopenharmony_ci ['for await (const x of [1,2,3]) {\nconsole.log(x);\n}', [ 1681cb0ef41Sopenharmony_ci 'for await (const x of [1,2,3]) {\r', 1691cb0ef41Sopenharmony_ci '... console.log(x);\r', 1701cb0ef41Sopenharmony_ci '... }\r', 1711cb0ef41Sopenharmony_ci '1', 1721cb0ef41Sopenharmony_ci '2', 1731cb0ef41Sopenharmony_ci '3', 1741cb0ef41Sopenharmony_ci 'undefined', 1751cb0ef41Sopenharmony_ci ]], 1761cb0ef41Sopenharmony_ci // Regression test for https://github.com/nodejs/node/issues/43777. 1771cb0ef41Sopenharmony_ci ['await Promise.resolve(123), Promise.resolve(456)', 'Promise {', { line: 0 }], 1781cb0ef41Sopenharmony_ci ['await Promise.resolve(123), await Promise.resolve(456)', '456'], 1791cb0ef41Sopenharmony_ci ['await (Promise.resolve(123), Promise.resolve(456))', '456'], 1801cb0ef41Sopenharmony_ci ]; 1811cb0ef41Sopenharmony_ci 1821cb0ef41Sopenharmony_ci for (const [input, expected = [`${input}\r`], options = {}] of testCases) { 1831cb0ef41Sopenharmony_ci console.log(`Testing ${input}`); 1841cb0ef41Sopenharmony_ci const toBeRun = input.split('\n'); 1851cb0ef41Sopenharmony_ci const lines = await runAndWait(toBeRun); 1861cb0ef41Sopenharmony_ci if (Array.isArray(expected)) { 1871cb0ef41Sopenharmony_ci if (expected.length === 1) 1881cb0ef41Sopenharmony_ci expected.push('undefined'); 1891cb0ef41Sopenharmony_ci if (lines[0] === input) 1901cb0ef41Sopenharmony_ci lines.shift(); 1911cb0ef41Sopenharmony_ci assert.deepStrictEqual(lines, [...expected, PROMPT]); 1921cb0ef41Sopenharmony_ci } else if ('line' in options) { 1931cb0ef41Sopenharmony_ci assert.strictEqual(lines[toBeRun.length + options.line], expected); 1941cb0ef41Sopenharmony_ci } else { 1951cb0ef41Sopenharmony_ci const echoed = toBeRun.map((a, i) => `${i > 0 ? '... ' : ''}${a}\r`); 1961cb0ef41Sopenharmony_ci assert.deepStrictEqual(lines, [...echoed, expected, PROMPT]); 1971cb0ef41Sopenharmony_ci } 1981cb0ef41Sopenharmony_ci } 1991cb0ef41Sopenharmony_ci} 2001cb0ef41Sopenharmony_ci 2011cb0ef41Sopenharmony_ciasync function ctrlCTest() { 2021cb0ef41Sopenharmony_ci console.log('Testing Ctrl+C'); 2031cb0ef41Sopenharmony_ci const output = await runAndWait([ 2041cb0ef41Sopenharmony_ci 'await new Promise(() => {})', 2051cb0ef41Sopenharmony_ci { ctrl: true, name: 'c' }, 2061cb0ef41Sopenharmony_ci ]); 2071cb0ef41Sopenharmony_ci assert.deepStrictEqual(output.slice(0, 3), [ 2081cb0ef41Sopenharmony_ci 'await new Promise(() => {})\r', 2091cb0ef41Sopenharmony_ci 'Uncaught:', 2101cb0ef41Sopenharmony_ci 'Error [ERR_SCRIPT_EXECUTION_INTERRUPTED]: ' + 2111cb0ef41Sopenharmony_ci 'Script execution was interrupted by `SIGINT`', 2121cb0ef41Sopenharmony_ci ]); 2131cb0ef41Sopenharmony_ci assert.deepStrictEqual(output.slice(-2), [ 2141cb0ef41Sopenharmony_ci '}', 2151cb0ef41Sopenharmony_ci PROMPT, 2161cb0ef41Sopenharmony_ci ]); 2171cb0ef41Sopenharmony_ci} 2181cb0ef41Sopenharmony_ci 2191cb0ef41Sopenharmony_ciasync function main() { 2201cb0ef41Sopenharmony_ci await ordinaryTests(); 2211cb0ef41Sopenharmony_ci await ctrlCTest(); 2221cb0ef41Sopenharmony_ci} 2231cb0ef41Sopenharmony_ci 2241cb0ef41Sopenharmony_cimain().then(common.mustCall()); 225