summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuben Bridgewater <ruben@bridgewater.de>2019-09-23 19:38:12 +0200
committerRuben Bridgewater <ruben@bridgewater.de>2019-12-06 02:10:58 +0100
commit6c40cb2aca89df4c7c0e3923d93024734dd49f2d (patch)
treeceb06cf66682bc843e8e0953cd8092a1179c46b5
parent51ccf1b5e90540a11c33866da15d4a7f52d7fddb (diff)
downloadandroid-node-v8-6c40cb2aca89df4c7c0e3923d93024734dd49f2d.tar.gz
android-node-v8-6c40cb2aca89df4c7c0e3923d93024734dd49f2d.tar.bz2
android-node-v8-6c40cb2aca89df4c7c0e3923d93024734dd49f2d.zip
repl: use better uncaught exceptions indicator
This switches "Thrown:" with "Uncaught" to outline clearer that the thrown error is not caught. PR-URL: https://github.com/nodejs/node/pull/29676 Reviewed-By: Gus Caplan <me@gus.host> Reviewed-By: James M Snell <jasnell@gmail.com>
-rw-r--r--lib/repl.js25
-rw-r--r--test/parallel/test-repl-harmony.js2
-rw-r--r--test/parallel/test-repl-null-thrown.js2
-rw-r--r--test/parallel/test-repl-pretty-custom-stack.js12
-rw-r--r--test/parallel/test-repl-pretty-stack.js19
-rw-r--r--test/parallel/test-repl-top-level-await.js10
-rw-r--r--test/parallel/test-repl-uncaught-exception-standalone.js3
-rw-r--r--test/parallel/test-repl-uncaught-exception.js25
-rw-r--r--test/parallel/test-repl-underscore.js12
-rw-r--r--test/parallel/test-repl.js67
10 files changed, 90 insertions, 87 deletions
diff --git a/lib/repl.js b/lib/repl.js
index c1473588d3..55daf2f47f 100644
--- a/lib/repl.js
+++ b/lib/repl.js
@@ -552,11 +552,28 @@ function REPLServer(prompt,
});
} else {
if (errStack === '') {
- errStack = `Thrown: ${self.writer(e)}\n`;
- } else {
- const ln = errStack.endsWith('\n') ? '' : '\n';
- errStack = `Thrown:\n${errStack}${ln}`;
+ errStack = self.writer(e);
+ }
+ const lines = errStack.split(/(?<=\n)/);
+ let matched = false;
+
+ errStack = '';
+ for (const line of lines) {
+ if (!matched && /^\[?([A-Z][a-z0-9_]*)*Error/.test(line)) {
+ errStack += writer.options.breakLength >= line.length ?
+ `Uncaught ${line}` :
+ `Uncaught:\n${line}`;
+ matched = true;
+ } else {
+ errStack += line;
+ }
+ }
+ if (!matched) {
+ const ln = lines.length === 1 ? ' ' : ':\n';
+ errStack = `Uncaught${ln}${errStack}`;
}
+ // Normalize line endings.
+ errStack += errStack.endsWith('\n') ? '' : '\n';
top.outputStream.write(errStack);
top.clearBufferedCommand();
top.lines.level = [];
diff --git a/test/parallel/test-repl-harmony.js b/test/parallel/test-repl-harmony.js
index 0aa8e56bdd..88b2c9deca 100644
--- a/test/parallel/test-repl-harmony.js
+++ b/test/parallel/test-repl-harmony.js
@@ -30,7 +30,7 @@ const child = spawn(process.execPath, args);
const input = '(function(){"use strict"; const y=1;y=2})()\n';
// This message will vary based on JavaScript engine, so don't check the message
// contents beyond confirming that the `Error` is a `TypeError`.
-const expectOut = /> Thrown:\nTypeError: /;
+const expectOut = /> Uncaught TypeError: /;
child.stderr.setEncoding('utf8');
child.stderr.on('data', (d) => {
diff --git a/test/parallel/test-repl-null-thrown.js b/test/parallel/test-repl-null-thrown.js
index 1fe5d30396..0ed4a05fd5 100644
--- a/test/parallel/test-repl-null-thrown.js
+++ b/test/parallel/test-repl-null-thrown.js
@@ -20,5 +20,5 @@ replserver.emit('line', '.exit');
setTimeout(() => {
console.log(text);
- assert(text.includes('Thrown: null'));
+ assert(text.includes('Uncaught null'));
}, 0);
diff --git a/test/parallel/test-repl-pretty-custom-stack.js b/test/parallel/test-repl-pretty-custom-stack.js
index 0d2ada134f..8f633a4d48 100644
--- a/test/parallel/test-repl-pretty-custom-stack.js
+++ b/test/parallel/test-repl-pretty-custom-stack.js
@@ -48,26 +48,26 @@ const tests = [
{
// test .load for a file that throws
command: `.load ${fixtures.path('repl-pretty-stack.js')}`,
- expected: 'Thrown:\nError: Whoops!--->\nrepl:*:*--->\nd (repl:*:*)' +
+ expected: 'Uncaught Error: Whoops!--->\nrepl:*:*--->\nd (repl:*:*)' +
'--->\nc (repl:*:*)--->\nb (repl:*:*)--->\na (repl:*:*)\n'
},
{
command: 'let x y;',
- expected: 'Thrown:\n' +
- 'let x y;\n ^\n\nSyntaxError: Unexpected identifier\n'
+ expected: 'let x y;\n ^\n\n' +
+ 'Uncaught SyntaxError: Unexpected identifier\n'
},
{
command: 'throw new Error(\'Whoops!\')',
- expected: 'Thrown:\nError: Whoops!\n'
+ expected: 'Uncaught Error: Whoops!\n'
},
{
command: 'foo = bar;',
- expected: 'Thrown:\nReferenceError: bar is not defined\n'
+ expected: 'Uncaught ReferenceError: bar is not defined\n'
},
// test anonymous IIFE
{
command: '(function() { throw new Error(\'Whoops!\'); })()',
- expected: 'Thrown:\nError: Whoops!--->\nrepl:*:*\n'
+ expected: 'Uncaught Error: Whoops!--->\nrepl:*:*\n'
}
];
diff --git a/test/parallel/test-repl-pretty-stack.js b/test/parallel/test-repl-pretty-stack.js
index 9f307c4f43..456e866b7b 100644
--- a/test/parallel/test-repl-pretty-stack.js
+++ b/test/parallel/test-repl-pretty-stack.js
@@ -7,7 +7,7 @@ const repl = require('repl');
const stackRegExp = /(at .*repl:)[0-9]+:[0-9]+/g;
-function run({ command, expected, ...extraREPLOptions }) {
+function run({ command, expected, ...extraREPLOptions }, i) {
let accum = '';
const inputStream = new ArrayStream();
@@ -25,6 +25,7 @@ function run({ command, expected, ...extraREPLOptions }) {
});
r.write(`${command}\n`);
+ console.log(i);
assert.strictEqual(
accum.replace(stackRegExp, '$1*:*'),
expected.replace(stackRegExp, '$1*:*')
@@ -36,39 +37,39 @@ const tests = [
{
// Test .load for a file that throws.
command: `.load ${fixtures.path('repl-pretty-stack.js')}`,
- expected: 'Thrown:\nError: Whoops!\n at repl:*:*\n' +
+ expected: 'Uncaught Error: Whoops!\n at repl:*:*\n' +
' at d (repl:*:*)\n at c (repl:*:*)\n' +
' at b (repl:*:*)\n at a (repl:*:*)\n'
},
{
command: 'let x y;',
- expected: 'Thrown:\n' +
- 'let x y;\n ^\n\nSyntaxError: Unexpected identifier\n'
+ expected: 'let x y;\n ^\n\n' +
+ 'Uncaught SyntaxError: Unexpected identifier\n'
},
{
command: 'throw new Error(\'Whoops!\')',
- expected: 'Thrown:\nError: Whoops!\n'
+ expected: 'Uncaught Error: Whoops!\n'
},
{
command: '(() => { const err = Error(\'Whoops!\'); ' +
'err.foo = \'bar\'; throw err; })()',
- expected: "Thrown:\nError: Whoops!\n at repl:*:* {\n foo: 'bar'\n}\n",
+ expected: "Uncaught Error: Whoops!\n at repl:*:* {\n foo: 'bar'\n}\n",
},
{
command: '(() => { const err = Error(\'Whoops!\'); ' +
'err.foo = \'bar\'; throw err; })()',
- expected: 'Thrown:\nError: Whoops!\n at repl:*:* {\n foo: ' +
+ expected: 'Uncaught Error: Whoops!\n at repl:*:* {\n foo: ' +
"\u001b[32m'bar'\u001b[39m\n}\n",
useColors: true
},
{
command: 'foo = bar;',
- expected: 'Thrown:\nReferenceError: bar is not defined\n'
+ expected: 'Uncaught ReferenceError: bar is not defined\n'
},
// Test anonymous IIFE.
{
command: '(function() { throw new Error(\'Whoops!\'); })()',
- expected: 'Thrown:\nError: Whoops!\n at repl:*:*\n'
+ expected: 'Uncaught Error: Whoops!\n at repl:*:*\n'
}
];
diff --git a/test/parallel/test-repl-top-level-await.js b/test/parallel/test-repl-top-level-await.js
index f629d3f1d0..5c8aa95d40 100644
--- a/test/parallel/test-repl-top-level-await.js
+++ b/test/parallel/test-repl-top-level-await.js
@@ -118,15 +118,15 @@ async function ordinaryTests() {
[ 'if (await true) { function bar() {}; }', 'undefined' ],
[ 'bar', '[Function: bar]' ],
[ 'if (await true) { class Bar {}; }', 'undefined' ],
- [ 'Bar', 'ReferenceError: Bar is not defined', { line: 1 } ],
+ [ 'Bar', 'Uncaught ReferenceError: Bar is not defined' ],
[ 'await 0; function* gen(){}', 'undefined' ],
[ 'for (var i = 0; i < 10; ++i) { await i; }', 'undefined' ],
[ 'i', '10' ],
[ 'for (let j = 0; j < 5; ++j) { await j; }', 'undefined' ],
- [ 'j', 'ReferenceError: j is not defined', { line: 1 } ],
+ [ 'j', 'Uncaught ReferenceError: j is not defined' ],
[ 'gen', '[GeneratorFunction: gen]' ],
- [ 'return 42; await 5;', 'SyntaxError: Illegal return statement',
- { line: 4 } ],
+ [ 'return 42; await 5;', 'Uncaught SyntaxError: Illegal return statement',
+ { line: 3 } ],
[ 'let o = await 1, p', 'undefined' ],
[ 'p', 'undefined' ],
[ 'let q = 1, s = await 2', 'undefined' ],
@@ -160,7 +160,7 @@ async function ctrlCTest() {
{ ctrl: true, name: 'c' }
]), [
'await timeout(100000)\r',
- 'Thrown:',
+ 'Uncaught:',
'[Error [ERR_SCRIPT_EXECUTION_INTERRUPTED]: ' +
'Script execution was interrupted by `SIGINT`] {',
" code: 'ERR_SCRIPT_EXECUTION_INTERRUPTED'",
diff --git a/test/parallel/test-repl-uncaught-exception-standalone.js b/test/parallel/test-repl-uncaught-exception-standalone.js
index ae7b214fef..e7371f9f7c 100644
--- a/test/parallel/test-repl-uncaught-exception-standalone.js
+++ b/test/parallel/test-repl-uncaught-exception-standalone.js
@@ -18,8 +18,7 @@ child.on('exit', common.mustCall(() => {
[
'Type ".help" for more information.',
// x\n
- '> Thrown:',
- 'ReferenceError: x is not defined',
+ '> Uncaught ReferenceError: x is not defined',
// Added `uncaughtException` listener.
'> short',
'undefined',
diff --git a/test/parallel/test-repl-uncaught-exception.js b/test/parallel/test-repl-uncaught-exception.js
index 447b69b1d4..28e62dff22 100644
--- a/test/parallel/test-repl-uncaught-exception.js
+++ b/test/parallel/test-repl-uncaught-exception.js
@@ -6,7 +6,7 @@ const repl = require('repl');
let count = 0;
-function run({ command, expected }) {
+function run({ command, expected, useColors = false }) {
let accum = '';
const output = new ArrayStream();
@@ -17,7 +17,7 @@ function run({ command, expected }) {
input: new ArrayStream(),
output,
terminal: false,
- useColors: false
+ useColors
});
r.write(`${command}\n`);
@@ -30,35 +30,40 @@ function run({ command, expected }) {
// Verify that the repl is still working as expected.
accum = '';
r.write('1 + 1\n');
- assert.strictEqual(accum, '2\n');
+ // eslint-disable-next-line no-control-regex
+ assert.strictEqual(accum.replace(/\u001b\[[0-9]+m/g, ''), '2\n');
r.close();
count++;
}
const tests = [
{
+ useColors: true,
command: 'x',
- expected: 'Thrown:\n' +
- 'ReferenceError: x is not defined\n'
+ expected: 'Uncaught ReferenceError: x is not defined\n'
+ },
+ {
+ useColors: true,
+ command: 'throw { foo: "test" }',
+ expected: "Uncaught { foo: \x1B[32m'test'\x1B[39m }\n"
},
{
command: 'process.on("uncaughtException", () => console.log("Foobar"));\n',
- expected: /^Thrown:\nTypeError \[ERR_INVALID_REPL_INPUT]: Listeners for `/
+ expected: /^Uncaught:\nTypeError \[ERR_INVALID_REPL_INPUT]: Listeners for `/
},
{
command: 'x;\n',
- expected: 'Thrown:\n' +
- 'ReferenceError: x is not defined\n'
+ expected: 'Uncaught ReferenceError: x is not defined\n'
},
{
command: 'process.on("uncaughtException", () => console.log("Foobar"));' +
'console.log("Baz");\n',
- expected: /^Thrown:\nTypeError \[ERR_INVALID_REPL_INPUT]: Listeners for `/
+ expected: /^Uncaught:\nTypeError \[ERR_INVALID_REPL_INPUT]: Listeners for `/
},
{
command: 'console.log("Baz");' +
'process.on("uncaughtException", () => console.log("Foobar"));\n',
- expected: /^Baz\nThrown:\nTypeError \[ERR_INVALID_REPL_INPUT]:.*uncaughtException/
+ expected: /^Baz\nUncaught:\nTypeError \[ERR_INVALID_REPL_INPUT]:.*uncaughtException/
}
];
diff --git a/test/parallel/test-repl-underscore.js b/test/parallel/test-repl-underscore.js
index 2e0865f5a7..c05c387471 100644
--- a/test/parallel/test-repl-underscore.js
+++ b/test/parallel/test-repl-underscore.js
@@ -173,13 +173,11 @@ function testError() {
'undefined',
// The error, both from the original throw and the `_error` echo.
- 'Thrown:',
- 'Error: foo',
+ 'Uncaught Error: foo',
'[Error: foo]',
// The sync error, with individual property echoes
- 'Thrown:',
- /^Error: ENOENT: no such file or directory, scandir '.*nonexistent\?'/,
+ /^Uncaught Error: ENOENT: no such file or directory, scandir '.*nonexistent\?'/,
/Object\.readdirSync/,
/^ errno: -(2|4058),$/,
" syscall: 'scandir',",
@@ -194,8 +192,7 @@ function testError() {
'undefined',
// The message from the original throw
- 'Thrown:',
- 'Error: baz',
+ 'Uncaught Error: baz',
];
for (const line of lines) {
const expected = expectedLines.shift();
@@ -218,8 +215,7 @@ function testError() {
"'baz'",
'Expression assignment to _error now disabled.',
'0',
- 'Thrown:',
- 'Error: quux',
+ 'Uncaught Error: quux',
'0'
]);
});
diff --git a/test/parallel/test-repl.js b/test/parallel/test-repl.js
index 05608bd5ee..b0dad397cc 100644
--- a/test/parallel/test-repl.js
+++ b/test/parallel/test-repl.js
@@ -126,7 +126,7 @@ const unixTests = [
const strictModeTests = [
{
send: 'ref = 1',
- expect: ['Thrown:', /^ReferenceError:\s/]
+ expect: [/^Uncaught ReferenceError:\s/]
}
];
@@ -134,11 +134,11 @@ const errorTests = [
// Uncaught error throws and prints out
{
send: 'throw new Error(\'test error\');',
- expect: ['Thrown:', 'Error: test error']
+ expect: ['Uncaught Error: test error']
},
{
send: "throw { foo: 'bar' };",
- expect: "Thrown: { foo: 'bar' }"
+ expect: "Uncaught { foo: 'bar' }"
},
// Common syntax error is treated as multiline command
{
@@ -153,7 +153,7 @@ const errorTests = [
// But passing the same string to eval() should throw
{
send: 'eval("function test_func() {")',
- expect: ['Thrown:', /^SyntaxError: /]
+ expect: [/^Uncaught SyntaxError: /]
},
// Can handle multiline template literals
{
@@ -210,89 +210,84 @@ const errorTests = [
// should throw
{
send: 'JSON.parse(\'{invalid: \\\'json\\\'}\');',
- expect: ['Thrown:', /^SyntaxError: /]
+ expect: [/^Uncaught SyntaxError: /]
},
// End of input to JSON.parse error is special case of syntax error,
// should throw
{
send: 'JSON.parse(\'066\');',
- expect: ['Thrown:', /^SyntaxError: /]
+ expect: [/^Uncaught SyntaxError: /]
},
// should throw
{
send: 'JSON.parse(\'{\');',
- expect: ['Thrown:', /^SyntaxError: /]
+ expect: [/^Uncaught SyntaxError: /]
},
// invalid RegExps are a special case of syntax error,
// should throw
{
send: '/(/;',
- expect: ['Thrown:', /^SyntaxError: /]
+ expect: [/^Uncaught SyntaxError: /]
},
// invalid RegExp modifiers are a special case of syntax error,
// should throw (GH-4012)
{
send: 'new RegExp("foo", "wrong modifier");',
- expect: ['Thrown:', /^SyntaxError: /]
+ expect: [/^Uncaught SyntaxError: /]
},
// Strict mode syntax errors should be caught (GH-5178)
{
send: '(function() { "use strict"; return 0755; })()',
expect: [
- 'Thrown:',
kSource,
kArrow,
'',
- /^SyntaxError: /
+ /^Uncaught SyntaxError: /
]
},
{
send: '(function(a, a, b) { "use strict"; return a + b + c; })()',
expect: [
- 'Thrown:',
kSource,
kArrow,
'',
- /^SyntaxError: /
+ /^Uncaught SyntaxError: /
]
},
{
send: '(function() { "use strict"; with (this) {} })()',
expect: [
- 'Thrown:',
kSource,
kArrow,
'',
- /^SyntaxError: /
+ /^Uncaught SyntaxError: /
]
},
{
send: '(function() { "use strict"; var x; delete x; })()',
expect: [
- 'Thrown:',
kSource,
kArrow,
'',
- /^SyntaxError: /
+ /^Uncaught SyntaxError: /
]
},
{
send: '(function() { "use strict"; eval = 17; })()',
expect: [
- 'Thrown:',
kSource,
kArrow,
'',
- /^SyntaxError: /
+ /^Uncaught SyntaxError: /
]
},
{
send: '(function() { "use strict"; if (true) function f() { } })()',
expect: [
- 'Thrown:',
kSource,
kArrow,
'',
+ 'Uncaught:',
/^SyntaxError: /
]
},
@@ -413,11 +408,10 @@ const errorTests = [
{
send: '[] \\',
expect: [
- 'Thrown:',
kSource,
kArrow,
'',
- /^SyntaxError: /
+ /^Uncaught SyntaxError: /
]
},
// Do not fail when a String is created with line continuation
@@ -548,8 +542,7 @@ const errorTests = [
{
send: 'require("internal/repl")',
expect: [
- 'Thrown:',
- /^Error: Cannot find module 'internal\/repl'/,
+ /^Uncaught Error: Cannot find module 'internal\/repl'/,
/^Require stack:/,
/^- <repl>/,
/^ at .*/,
@@ -587,11 +580,10 @@ const errorTests = [
{
send: 'a = 3.5e',
expect: [
- 'Thrown:',
kSource,
kArrow,
'',
- /^SyntaxError: /
+ /^Uncaught SyntaxError: /
]
},
// Mitigate https://github.com/nodejs/node/issues/548
@@ -607,22 +599,20 @@ const errorTests = [
{
send: 'a = 3.5e',
expect: [
- 'Thrown:',
kSource,
kArrow,
'',
- /^SyntaxError: /
+ /^Uncaught SyntaxError: /
]
},
// Avoid emitting stack trace
{
send: 'a = 3.5e',
expect: [
- 'Thrown:',
kSource,
kArrow,
'',
- /^SyntaxError: /
+ /^Uncaught SyntaxError: /
]
},
@@ -687,11 +677,10 @@ const errorTests = [
{
send: '...[]',
expect: [
- 'Thrown:',
kSource,
kArrow,
'',
- /^SyntaxError: /
+ /^Uncaught SyntaxError: /
]
},
// Bring back the repl to prompt
@@ -702,31 +691,28 @@ const errorTests = [
{
send: 'console.log("Missing comma in arg list" process.version)',
expect: [
- 'Thrown:',
kSource,
kArrow,
'',
- /^SyntaxError: /
+ /^Uncaught SyntaxError: /
]
},
{
send: 'x = {\nfield\n{',
expect: [
- '... ... Thrown:',
- '{',
+ '... ... {',
kArrow,
'',
- /^SyntaxError: /
+ /^Uncaught SyntaxError: /
]
},
{
send: '(2 + 3))',
expect: [
- 'Thrown:',
kSource,
kArrow,
'',
- /^SyntaxError: /
+ /^Uncaught SyntaxError: /
]
},
{
@@ -740,11 +726,10 @@ const errorTests = [
{
send: '} else {',
expect: [
- 'Thrown:',
kSource,
kArrow,
'',
- /^SyntaxError: /
+ /^Uncaught SyntaxError: /
]
},
];