mirror of
https://github.com/nodejs/node.git
synced 2024-11-21 21:19:50 +01:00
cc725a653a
PR-URL: https://github.com/nodejs/node/pull/49654 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Stephen Belanger <admin@stephenbelanger.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Raz Luvaton <rluvaton@gmail.com>
225 lines
6.3 KiB
JavaScript
225 lines
6.3 KiB
JavaScript
'use strict';
|
|
|
|
const common = require('../common');
|
|
const ArrayStream = require('../common/arraystream');
|
|
const assert = require('assert');
|
|
const events = require('events');
|
|
const { stripVTControlCharacters } = require('internal/util/inspect');
|
|
const repl = require('repl');
|
|
|
|
common.skipIfInspectorDisabled();
|
|
|
|
// Flags: --expose-internals
|
|
|
|
const PROMPT = 'await repl > ';
|
|
|
|
class REPLStream extends ArrayStream {
|
|
constructor() {
|
|
super();
|
|
this.waitingForResponse = false;
|
|
this.lines = [''];
|
|
}
|
|
write(chunk, encoding, callback) {
|
|
if (Buffer.isBuffer(chunk)) {
|
|
chunk = chunk.toString(encoding);
|
|
}
|
|
const chunkLines = stripVTControlCharacters(chunk).split('\n');
|
|
this.lines[this.lines.length - 1] += chunkLines[0];
|
|
if (chunkLines.length > 1) {
|
|
this.lines.push(...chunkLines.slice(1));
|
|
}
|
|
this.emit('line', this.lines[this.lines.length - 1]);
|
|
if (callback) callback();
|
|
return true;
|
|
}
|
|
|
|
async wait() {
|
|
if (this.waitingForResponse) {
|
|
throw new Error('Currently waiting for response to another command');
|
|
}
|
|
this.lines = [''];
|
|
for await (const [line] of events.on(this, 'line')) {
|
|
if (line.includes(PROMPT)) {
|
|
return this.lines;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
const putIn = new REPLStream();
|
|
const testMe = repl.start({
|
|
prompt: PROMPT,
|
|
stream: putIn,
|
|
terminal: true,
|
|
useColors: true,
|
|
breakEvalOnSigint: true
|
|
});
|
|
|
|
function runAndWait(cmds) {
|
|
const promise = putIn.wait();
|
|
for (const cmd of cmds) {
|
|
if (typeof cmd === 'string') {
|
|
putIn.run([cmd]);
|
|
} else {
|
|
testMe.write('', cmd);
|
|
}
|
|
}
|
|
return promise;
|
|
}
|
|
|
|
async function ordinaryTests() {
|
|
// These tests were created based on
|
|
// https://cs.chromium.org/chromium/src/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-top-level-await.js?rcl=5d0ea979f0ba87655b7ef0e03b58fa3c04986ba6
|
|
putIn.run([
|
|
'function foo(x) { return x; }',
|
|
'function koo() { return Promise.resolve(4); }',
|
|
]);
|
|
const testCases = [
|
|
['await Promise.resolve(0)', '0'],
|
|
['{ a: await Promise.resolve(1) }', '{ a: 1 }'],
|
|
['_', '{ a: 1 }'],
|
|
['let { aa, bb } = await Promise.resolve({ aa: 1, bb: 2 }), f = 5;'],
|
|
['aa', '1'],
|
|
['bb', '2'],
|
|
['f', '5'],
|
|
['let cc = await Promise.resolve(2)'],
|
|
['cc', '2'],
|
|
['let dd;'],
|
|
['dd'],
|
|
['let [ii, { abc: { kk } }] = [0, { abc: { kk: 1 } }];'],
|
|
['ii', '0'],
|
|
['kk', '1'],
|
|
['var ll = await Promise.resolve(2);'],
|
|
['ll', '2'],
|
|
['foo(await koo())', '4'],
|
|
['_', '4'],
|
|
['const m = foo(await koo());'],
|
|
['m', '4'],
|
|
['const n = foo(await\nkoo());',
|
|
['const n = foo(await\r', '... koo());\r', 'undefined']],
|
|
['n', '4'],
|
|
// eslint-disable-next-line no-template-curly-in-string
|
|
['`status: ${(await Promise.resolve({ status: 200 })).status}`',
|
|
"'status: 200'"],
|
|
['for (let i = 0; i < 2; ++i) await i'],
|
|
['for (let i = 0; i < 2; ++i) { await i }'],
|
|
['await 0', '0'],
|
|
['await 0; function foo() {}'],
|
|
['foo', '[Function: foo]'],
|
|
['class Foo {}; await 1;', '1'],
|
|
['Foo', '[class Foo]'],
|
|
['if (await true) { function bar() {}; }'],
|
|
['bar', '[Function: bar]'],
|
|
['if (await true) { class Bar {}; }'],
|
|
['Bar', 'Uncaught ReferenceError: Bar is not defined'],
|
|
['await 0; function* gen(){}'],
|
|
['for (var i = 0; i < 10; ++i) { await i; }'],
|
|
['i', '10'],
|
|
['for (let j = 0; j < 5; ++j) { await j; }'],
|
|
['j', 'Uncaught ReferenceError: j is not defined', { line: 0 }],
|
|
['gen', '[GeneratorFunction: gen]'],
|
|
['return 42; await 5;', 'Uncaught SyntaxError: Illegal return statement',
|
|
{ line: 3 }],
|
|
['let o = await 1, p'],
|
|
['p'],
|
|
['let q = 1, s = await 2'],
|
|
['s', '2'],
|
|
['for await (let i of [1,2,3]) console.log(i)',
|
|
[
|
|
'for await (let i of [1,2,3]) console.log(i)\r',
|
|
'1',
|
|
'2',
|
|
'3',
|
|
'undefined',
|
|
],
|
|
],
|
|
['await Promise..resolve()',
|
|
[
|
|
'await Promise..resolve()\r',
|
|
'Uncaught SyntaxError: ',
|
|
'await Promise..resolve()',
|
|
' ^',
|
|
'',
|
|
'Unexpected token \'.\'',
|
|
],
|
|
],
|
|
['for (const x of [1,2,3]) {\nawait x\n}', [
|
|
'for (const x of [1,2,3]) {\r',
|
|
'... await x\r',
|
|
'... }\r',
|
|
'undefined',
|
|
]],
|
|
['for (const x of [1,2,3]) {\nawait x;\n}', [
|
|
'for (const x of [1,2,3]) {\r',
|
|
'... await x;\r',
|
|
'... }\r',
|
|
'undefined',
|
|
]],
|
|
['for await (const x of [1,2,3]) {\nconsole.log(x)\n}', [
|
|
'for await (const x of [1,2,3]) {\r',
|
|
'... console.log(x)\r',
|
|
'... }\r',
|
|
'1',
|
|
'2',
|
|
'3',
|
|
'undefined',
|
|
]],
|
|
['for await (const x of [1,2,3]) {\nconsole.log(x);\n}', [
|
|
'for await (const x of [1,2,3]) {\r',
|
|
'... console.log(x);\r',
|
|
'... }\r',
|
|
'1',
|
|
'2',
|
|
'3',
|
|
'undefined',
|
|
]],
|
|
// Regression test for https://github.com/nodejs/node/issues/43777.
|
|
['await Promise.resolve(123), Promise.resolve(456)', 'Promise {', { line: 0 }],
|
|
['await Promise.resolve(123), await Promise.resolve(456)', '456'],
|
|
['await (Promise.resolve(123), Promise.resolve(456))', '456'],
|
|
];
|
|
|
|
for (const [input, expected = [`${input}\r`], options = {}] of testCases) {
|
|
console.log(`Testing ${input}`);
|
|
const toBeRun = input.split('\n');
|
|
const lines = await runAndWait(toBeRun);
|
|
if (Array.isArray(expected)) {
|
|
if (expected.length === 1)
|
|
expected.push('undefined');
|
|
if (lines[0] === input)
|
|
lines.shift();
|
|
assert.deepStrictEqual(lines, [...expected, PROMPT]);
|
|
} else if ('line' in options) {
|
|
assert.strictEqual(lines[toBeRun.length + options.line], expected);
|
|
} else {
|
|
const echoed = toBeRun.map((a, i) => `${i > 0 ? '... ' : ''}${a}\r`);
|
|
assert.deepStrictEqual(lines, [...echoed, expected, PROMPT]);
|
|
}
|
|
}
|
|
}
|
|
|
|
async function ctrlCTest() {
|
|
console.log('Testing Ctrl+C');
|
|
const output = await runAndWait([
|
|
'await new Promise(() => {})',
|
|
{ ctrl: true, name: 'c' },
|
|
]);
|
|
assert.deepStrictEqual(output.slice(0, 3), [
|
|
'await new Promise(() => {})\r',
|
|
'Uncaught:',
|
|
'[Error [ERR_SCRIPT_EXECUTION_INTERRUPTED]: ' +
|
|
'Script execution was interrupted by `SIGINT`] {',
|
|
]);
|
|
assert.deepStrictEqual(output.slice(-2), [
|
|
'}',
|
|
PROMPT,
|
|
]);
|
|
}
|
|
|
|
async function main() {
|
|
await ordinaryTests();
|
|
await ctrlCTest();
|
|
}
|
|
|
|
main().then(common.mustCall());
|