util: only inspect error properties that are not visible otherwise

Inspecting errors results in duplicated information in case an error
is created with enumerable `name`, `message` or `stack` properties.
In that case, check if the output already contains that information
and prevent listing that property.

This reduces the noise as receiver.

PR-URL: https://github.com/nodejs/node/pull/32327
Reviewed-By: Anto Aravinth <anto.aravinth.cse@gmail.com>
pull/32617/head
Ruben Bridgewater 2020-03-17 17:24:25 +01:00 committed by Anna Henningsen
parent e20b4f918a
commit 6baddcfddf
No known key found for this signature in database
GPG Key ID: A94130F0BFC8EBE9
2 changed files with 36 additions and 2 deletions

View File

@ -890,7 +890,7 @@ function formatRaw(ctx, value, recurseTimes, typedArray) {
return ctx.stylize(base, 'date');
}
} else if (isError(value)) {
base = formatError(value, constructor, tag, ctx);
base = formatError(value, constructor, tag, ctx, keys);
if (keys.length === 0 && protoProps === undefined)
return base;
} else if (isAnyArrayBuffer(value)) {
@ -1083,11 +1083,23 @@ function getFunctionBase(value, constructor, tag) {
return base;
}
function formatError(err, constructor, tag, ctx) {
function formatError(err, constructor, tag, ctx, keys) {
const name = err.name != null ? String(err.name) : 'Error';
let len = name.length;
let stack = err.stack ? String(err.stack) : ErrorPrototypeToString(err);
// Do not "duplicate" error properties that are already included in the output
// otherwise.
if (!ctx.showHidden && keys.length !== 0) {
for (const name of ['name', 'message', 'stack']) {
const index = keys.indexOf(name);
// Only hide the property in case it's part of the original stack
if (index !== -1 && stack.includes(err[name])) {
keys.splice(index, 1);
}
}
}
// A stack trace may contain arbitrary data. Only manipulate the output
// for "regular errors" (errors that "look normal") for now.
if (constructor === null ||

View File

@ -697,6 +697,28 @@ assert.strictEqual(util.inspect(-5e-324), '-5e-324');
Error.stackTraceLimit = tmp;
}
// Prevent enumerable error properties from being printed.
{
let err = new Error();
err.message = 'foobar';
let out = util.inspect(err).split('\n');
assert.strictEqual(out[0], 'Error: foobar');
assert(out[out.length - 1].startsWith(' at '));
// Reset the error, the stack is otherwise not recreated.
err = new Error();
err.message = 'foobar';
err.name = 'Unique';
Object.defineProperty(err, 'stack', { value: err.stack, enumerable: true });
out = util.inspect(err).split('\n');
assert.strictEqual(out[0], 'Unique: foobar');
assert(out[out.length - 1].startsWith(' at '));
err.name = 'Baz';
out = util.inspect(err).split('\n');
assert.strictEqual(out[0], 'Unique: foobar');
assert.strictEqual(out[out.length - 2], " name: 'Baz'");
assert.strictEqual(out[out.length - 1], '}');
}
// Doesn't capture stack trace.
{
function BadCustomError(msg) {