Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

repl: always show all error properties #20801

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions lib/repl.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,7 @@ function hasOwnProperty(obj, prop) {
// Can overridden with custom print functions, such as `probe` or `eyes.js`.
// This is the default "writer" value if none is passed in the REPL options.
const writer = exports.writer = (obj) => util.inspect(obj, writer.options);
writer.options =
Object.assign({}, util.inspect.defaultOptions, { showProxy: true });
writer.options = { ...util.inspect.defaultOptions, showProxy: true };

exports._builtinLibs = builtinLibs;

Expand Down Expand Up @@ -417,9 +416,15 @@ function REPLServer(prompt,
(_, pre, line) => pre + (line - 1));
}
if (isError && e.stack) {
top.outputStream.write(`${e.stack}\n`);
// Since this error is not exposed to the user otherwise, just remove this
// part to prevent it from being logged.
if (e.domainThrown === true) {
delete e.domain;
delete e.domainThrown;
}
top.outputStream.write(`${top.writer(e)}\n`);
} else {
top.outputStream.write(`Thrown: ${String(e)}\n`);
top.outputStream.write(`Thrown: ${top.writer(e)}\n`);
}
top.clearBufferedCommand();
top.lines.level = [];
Expand Down Expand Up @@ -485,7 +490,7 @@ function REPLServer(prompt,
if (self.useColors && self.writer === writer) {
// Turn on ANSI coloring.
self.writer = (obj) => util.inspect(obj, self.writer.options);
self.writer.options = Object.assign({}, writer.options, { colors: true });
self.writer.options = { ...writer.options, colors: true };
}

function filterInternalStackFrames(error, structuredStack) {
Expand Down
4 changes: 2 additions & 2 deletions test/parallel/test-repl-top-level-await.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,8 @@ async function ctrlCTest() {
{ ctrl: true, name: 'c' }
]), [
'await timeout(100000)\r',
'Thrown: Error [ERR_SCRIPT_EXECUTION_INTERRUPTED]: ' +
'Script execution was interrupted by `SIGINT`',
'Thrown: [Error [ERR_SCRIPT_EXECUTION_INTERRUPTED]: ' +
'Script execution was interrupted by `SIGINT`]',
PROMPT
]);
}
Expand Down
4 changes: 4 additions & 0 deletions test/parallel/test-repl-underscore.js
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,10 @@ function testError() {
// The sync error, with individual property echoes
/Error: ENOENT: no such file or directory, scandir '.*nonexistent.*'/,
/fs\.readdirSync/,
' errno: -2,',
" syscall: 'scandir',",
" code: 'ENOENT',",
" path: '/nonexistent?' }",
"'ENOENT'",
"'scandir'",

Expand Down
21 changes: 15 additions & 6 deletions test/parallel/test-repl.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const fixtures = require('../common/fixtures');
const assert = require('assert');
const net = require('net');
const repl = require('repl');
const { inspect } = require('util');

common.globalCheck = false;
common.crashOnUnhandledRejection();
Expand Down Expand Up @@ -62,7 +63,7 @@ async function runReplTests(socket, prompt, tests) {
expectedLine = send;

while (!lineBuffer.includes('\n')) {
lineBuffer += await event(socket, 'data');
lineBuffer += await event(socket, expect);

// Cut away the initial prompt
while (lineBuffer.startsWith(prompt))
Expand Down Expand Up @@ -523,11 +524,11 @@ const errorTests = [
{
send: 'require("internal/repl")',
expect: [
/^Error: Cannot find module 'internal\/repl'/,
/^{ Error: Cannot find module 'internal\/repl'/,
/^ at .*/,
/^ at .*/,
/^ at .*/,
/^ at .*/
/^ at .* code: 'MODULE_NOT_FOUND' }/
]
},
// REPL should handle quotes within regexp literal in multiline mode
Expand Down Expand Up @@ -836,8 +837,16 @@ function startUnixRepl() {
]);
}

function event(ee, eventName) {
return new Promise((resolve) => {
ee.once(eventName, common.mustCall(resolve));
function event(ee, expected) {
return new Promise((resolve, reject) => {
const timeout = setTimeout(() => {
reject(
new Error(`Repl did not reply as expected for:\n\n${inspect(expected)}`)
);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is expected always an event name (a string?).
If it is I think padding with two newlines is a bit much. It could just go right after the : .

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, expected is the expected output, so either a string or an array with many strings.

}, 500);
ee.once('data', common.mustCall((...args) => {
clearTimeout(timeout);
resolve(...args);
Copy link
Member

@jdalton jdalton May 18, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With promises I believe once resolve is called a reject will have no effect so it could go without clearing since the timeout has no other side effects.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But it would keep the test alive after being done if I am not mistaken.

}));
});
}