Skip to content

Commit

Permalink
repl: improve error output
Browse files Browse the repository at this point in the history
1) Currently extra properties on an error will be ignored, if thrown.
   This information will from now on be visible.
2) In case someone threw a non error object it would have resulted in
   `[object Object]`. Instead, the full object will now be visible.
3) Some cases were not detected properly as error before and "Thrown: "
   was visible before. That is now fixed.

PR-URL: nodejs#22436
Refs: nodejs#20253
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: James M Snell <jasnell@gmail.com>
  • Loading branch information
BridgeAR committed Aug 27, 2018
1 parent 50aa85d commit ccb303e
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 24 deletions.
61 changes: 41 additions & 20 deletions lib/repl.js
Original file line number Diff line number Diff line change
Expand Up @@ -410,29 +410,50 @@ function REPLServer(prompt,

self._domain.on('error', function debugDomainError(e) {
debug('domain error');
const top = replMap.get(self);
const pstrace = Error.prepareStackTrace;
Error.prepareStackTrace = prepareStackTrace(pstrace);
if (typeof e === 'object')
let errStack = '';

if (typeof e === 'object' && e !== null) {
const pstrace = Error.prepareStackTrace;
Error.prepareStackTrace = prepareStackTrace(pstrace);
internalUtil.decorateErrorStack(e);
Error.prepareStackTrace = pstrace;
const isError = internalUtil.isError(e);
if (!self.underscoreErrAssigned)
self.lastError = e;
if (e instanceof SyntaxError && e.stack) {
// remove repl:line-number and stack trace
e.stack = e.stack
.replace(/^repl:\d+\r?\n/, '')
.replace(/^\s+at\s.*\n?/gm, '');
} else if (isError && self.replMode === exports.REPL_MODE_STRICT) {
e.stack = e.stack.replace(/(\s+at\s+repl:)(\d+)/,
(_, pre, line) => pre + (line - 1));
Error.prepareStackTrace = pstrace;

if (e.domainThrown) {
delete e.domain;
delete e.domainThrown;
}

if (internalUtil.isError(e)) {
if (e.stack) {
if (e.name === 'SyntaxError') {
// Remove stack trace.
e.stack = e.stack
.replace(/^repl:\d+\r?\n/, '')
.replace(/^\s+at\s.*\n?/gm, '');
} else if (self.replMode === exports.REPL_MODE_STRICT) {
e.stack = e.stack.replace(/(\s+at\s+repl:)(\d+)/,
(_, pre, line) => pre + (line - 1));
}
}
errStack = util.inspect(e);

// Remove one line error braces to keep the old style in place.
if (errStack[errStack.length - 1] === ']') {
errStack = errStack.slice(1, -1);
}
}
}
if (isError && e.stack) {
top.outputStream.write(`${e.stack}\n`);
} else {
top.outputStream.write(`Thrown: ${String(e)}\n`);

if (errStack === '') {
errStack = `Thrown: ${util.inspect(e)}`;
}

if (!self.underscoreErrAssigned) {
self.lastError = e;
}

const top = replMap.get(self);
top.outputStream.write(`${errStack}\n`);
top.clearBufferedCommand();
top.lines.level = [];
top.displayPrompt();
Expand Down
2 changes: 1 addition & 1 deletion test/parallel/test-repl-top-level-await.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ async function ctrlCTest() {
{ ctrl: true, name: 'c' }
]), [
'await timeout(100000)\r',
'Thrown: Error [ERR_SCRIPT_EXECUTION_INTERRUPTED]: ' +
'Error [ERR_SCRIPT_EXECUTION_INTERRUPTED]: ' +
'Script execution was interrupted by `SIGINT`',
PROMPT
]);
Expand Down
6 changes: 5 additions & 1 deletion test/parallel/test-repl-underscore.js
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,12 @@ function testError() {
'[Error: foo]',

// The sync error, with individual property echoes
/Error: ENOENT: no such file or directory, scandir '.*nonexistent.*'/,
/^{ Error: ENOENT: no such file or directory, scandir '.*nonexistent.*'/,
/Object\.readdirSync/,
/^ errno: -(2|4058),$/,
" syscall: 'scandir',",
" code: 'ENOENT',",
" path: '/nonexistent?' }",
"'ENOENT'",
"'scandir'",

Expand Down
8 changes: 6 additions & 2 deletions test/parallel/test-repl.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,11 @@ const errorTests = [
// Uncaught error throws and prints out
{
send: 'throw new Error(\'test error\');',
expect: /^Error: test error/
expect: 'Error: test error'
},
{
send: "throw { foo: 'bar' };",
expect: "Thrown: { foo: 'bar' }"
},
// Common syntax error is treated as multiline command
{
Expand Down Expand Up @@ -526,7 +530,7 @@ const errorTests = [
{
send: 'require("internal/repl")',
expect: [
/^Error: Cannot find module 'internal\/repl'/,
/^{ Error: Cannot find module 'internal\/repl'/,
/^ at .*/,
/^ at .*/,
/^ at .*/,
Expand Down

0 comments on commit ccb303e

Please sign in to comment.