mirror of
https://github.com/nodejs/node.git
synced 2024-12-01 16:10:02 +01:00
8fb5fe28a4
The array grouping function relies on the width of the characters. It was not calculated correct so far, since it used the string length instead. This improves the unicode output by calculating the mono-spaced font width (other fonts might differ). PR-URL: https://github.com/nodejs/node/pull/31319 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Steven R Loomis <srloomis@us.ibm.com> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Minwoo Jung <nodecorelab@gmail.com>
194 lines
5.4 KiB
JavaScript
194 lines
5.4 KiB
JavaScript
'use strict';
|
|
|
|
const common = require('../common');
|
|
const ArrayStream = require('../common/arraystream');
|
|
const assert = require('assert');
|
|
const { stripVTControlCharacters } = require('internal/util/inspect');
|
|
const repl = require('repl');
|
|
|
|
common.skipIfInspectorDisabled();
|
|
|
|
// Flags: --expose-internals --experimental-repl-await
|
|
|
|
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');
|
|
if (callback) callback();
|
|
return true;
|
|
}
|
|
|
|
wait() {
|
|
if (this.waitingForResponse) {
|
|
throw new Error('Currently waiting for response to another command');
|
|
}
|
|
this.lines = [''];
|
|
return new Promise((resolve, reject) => {
|
|
const onError = (err) => {
|
|
this.removeListener('line', onLine);
|
|
reject(err);
|
|
};
|
|
const onLine = () => {
|
|
if (this.lines[this.lines.length - 1].includes(PROMPT)) {
|
|
this.removeListener('error', onError);
|
|
this.removeListener('line', onLine);
|
|
resolve(this.lines);
|
|
}
|
|
};
|
|
this.once('error', onError);
|
|
this.on('line', onLine);
|
|
});
|
|
}
|
|
}
|
|
|
|
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', '[Function: 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'
|
|
]
|
|
]
|
|
];
|
|
|
|
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() {
|
|
putIn.run([
|
|
`const timeout = (msecs) => new Promise((resolve) => {
|
|
setTimeout(resolve, msecs).unref();
|
|
});`
|
|
]);
|
|
|
|
console.log('Testing Ctrl+C');
|
|
assert.deepStrictEqual(await runAndWait([
|
|
'await timeout(100000)',
|
|
{ ctrl: true, name: 'c' }
|
|
]), [
|
|
'await timeout(100000)\r',
|
|
'Uncaught:',
|
|
'[Error [ERR_SCRIPT_EXECUTION_INTERRUPTED]: ' +
|
|
'Script execution was interrupted by `SIGINT`] {',
|
|
" code: 'ERR_SCRIPT_EXECUTION_INTERRUPTED'",
|
|
'}',
|
|
PROMPT
|
|
]);
|
|
}
|
|
|
|
async function main() {
|
|
await ordinaryTests();
|
|
await ctrlCTest();
|
|
}
|
|
|
|
main();
|