diff --git a/lib/repl.js b/lib/repl.js index 9530d57a347468..71fb84897880f4 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -339,11 +339,6 @@ function REPLServer(prompt, } catch (e) { err = e; - if (err && err.code === 'ERR_SCRIPT_EXECUTION_INTERRUPTED') { - // The stack trace for this case is not very useful anyway. - Object.defineProperty(err, 'stack', { value: '' }); - } - if (process.domain) { debug('not recoverable, send to domain'); process.domain.emit('error', err); @@ -359,7 +354,11 @@ function REPLServer(prompt, if (self.breakEvalOnSigint) { const interrupt = new Promise((resolve, reject) => { sigintListener = () => { - reject(new ERR_SCRIPT_EXECUTION_INTERRUPTED()); + const tmp = Error.stackTraceLimit; + Error.stackTraceLimit = 0; + const err = new ERR_SCRIPT_EXECUTION_INTERRUPTED(); + Error.stackTraceLimit = tmp; + reject(err); }; prioritizedSigintQueue.add(sigintListener); }); @@ -378,11 +377,6 @@ function REPLServer(prompt, // Remove prioritized SIGINT listener if it was not called. prioritizedSigintQueue.delete(sigintListener); - if (err.code === 'ERR_SCRIPT_EXECUTION_INTERRUPTED') { - // The stack trace for this case is not very useful anyway. - Object.defineProperty(err, 'stack', { value: '' }); - } - unpause(); if (err && process.domain) { debug('not recoverable, send to domain'); @@ -404,29 +398,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(); diff --git a/test/parallel/test-repl-top-level-await.js b/test/parallel/test-repl-top-level-await.js index f1e2303938b7a6..c8413646f38f4c 100644 --- a/test/parallel/test-repl-top-level-await.js +++ b/test/parallel/test-repl-top-level-await.js @@ -158,7 +158,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 ]); diff --git a/test/parallel/test-repl-underscore.js b/test/parallel/test-repl-underscore.js index f7fe0bcea80ca0..dea2ed43704dfd 100644 --- a/test/parallel/test-repl-underscore.js +++ b/test/parallel/test-repl-underscore.js @@ -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'", diff --git a/test/parallel/test-repl.js b/test/parallel/test-repl.js index 8cb4b686b85e40..49e718da0f0683 100644 --- a/test/parallel/test-repl.js +++ b/test/parallel/test-repl.js @@ -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 { @@ -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 .*/,