Skip to content

Commit 94a702e

Browse files
committed
fixup! util: implement consistent inspect(err)
1 parent f85647b commit 94a702e

File tree

2 files changed

+100
-53
lines changed

2 files changed

+100
-53
lines changed

lib/internal/util/inspect.js

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ const {
156156
} = require('internal/util');
157157

158158
const {
159+
isErrorStackTraceLimitWritable,
159160
isStackOverflowError,
160161
} = require('internal/errors');
161162

@@ -2557,14 +2558,17 @@ function formatProperty(ctx, value, recurseTimes, key, type, desc,
25572558
}
25582559
ctx.indentationLvl -= 2;
25592560
} catch (err) {
2560-
// Error message itself may be a getter
2561-
let errMessage;
2562-
try {
2563-
errMessage = err.message;
2564-
} catch {
2565-
errMessage = undefined;
2561+
// Error message itself may be a getter that throws
2562+
let messageSuffix = '';
2563+
if (isErrorStackTraceLimitWritable()) {
2564+
const stackTraceLimit = Error.stackTraceLimit;
2565+
Error.stackTraceLimit = 0;
2566+
try {
2567+
messageSuffix = ` (${inspect(err)})`;
2568+
// eslint-disable-next-line no-empty
2569+
} catch { } finally { Error.stackTraceLimit = stackTraceLimit; }
25662570
}
2567-
const messageSuffix = typeof errMessage === 'string' ? ` (${errMessage})` : '';
2571+
25682572
const message = `<Inspection threw${messageSuffix}>`;
25692573
str = `${s(`[${label}:`, sp)} ${message}${s(']', sp)}`;
25702574
}

test/parallel/test-util-inspect.js

Lines changed: 89 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2527,14 +2527,10 @@ assert.strictEqual(
25272527
set foo(val) { foo = val; },
25282528
get inc() { return ++foo; }
25292529
};
2530-
const thrower = { get foo() { throw new Error('Oops'); } };
25312530
assert.strictEqual(
25322531
inspect(get, { getters: true, colors: true }),
25332532
'{ foo: \u001b[36m[Getter:\u001b[39m ' +
25342533
'\u001b[33m1\u001b[39m\u001b[36m]\u001b[39m }');
2535-
assert.strictEqual(
2536-
inspect(thrower, { getters: true }),
2537-
'{ foo: [Getter: <Inspection threw (Oops)>] }');
25382534
assert.strictEqual(
25392535
inspect(getset, { getters: true }),
25402536
'{ foo: [Getter/Setter: 1], inc: [Getter: 2] }');
@@ -2551,80 +2547,116 @@ assert.strictEqual(
25512547
"'foobar', { x: 1 } },\n inc: [Getter: NaN]\n}");
25522548
}
25532549

2554-
// Property getter throwing throwing uncommon values.
2550+
// Property getter throwing an error.
25552551
{
2552+
const error = new Error('Oops');
2553+
error.stack = [
2554+
'Error: Oops',
2555+
' at get foo (/foo/node_modules/foo.js:2:7)',
2556+
' at get bar (/foo/node_modules/bar.js:827:30)',
2557+
].join('\n');
2558+
2559+
const thrower = {
2560+
get foo() { throw error; }
2561+
};
2562+
25562563
assert.strictEqual(
2557-
inspect({
2558-
// eslint-disable-next-line no-throw-literal
2559-
get foo() { throw null; }
2560-
}, { getters: true }),
2561-
'{ foo: [Getter: <Inspection threw>] }'
2564+
inspect(thrower, { getters: true }),
2565+
'{\n' +
2566+
' foo: [Getter: <Inspection threw (Error: Oops\n' +
2567+
' at get foo (/foo/node_modules/foo.js:2:7)\n' +
2568+
' at get bar (/foo/node_modules/bar.js:827:30))>]\n' +
2569+
'}',
25622570
);
2571+
};
2572+
2573+
// Property getter throwing an error with getters that throws.
2574+
// https://github.com/nodejs/node/issues/60683
2575+
{
2576+
const error = new Error();
2577+
2578+
const throwingGetter = {
2579+
__proto__: null,
2580+
get() {
2581+
throw error;
2582+
},
2583+
configurable: true,
2584+
enumerable: true,
2585+
};
2586+
2587+
Object.defineProperties(error, {
2588+
name: throwingGetter,
2589+
stack: throwingGetter,
2590+
cause: throwingGetter,
2591+
});
2592+
2593+
const thrower = {
2594+
get foo() { throw error; }
2595+
};
2596+
2597+
assert.strictEqual(
2598+
inspect(thrower, { getters: true }),
2599+
'{\n' +
2600+
' foo: [Getter: <Inspection threw ([object Error] {\n' +
2601+
' stack: [Getter/Setter],\n' +
2602+
' name: [Getter],\n' +
2603+
' cause: [Getter]\n' +
2604+
'})>]\n' +
2605+
'}',
2606+
);
2607+
}
2608+
2609+
// Property getter throwing throwing uncommon values.
2610+
{
25632611
assert.strictEqual(
25642612
inspect({
25652613
// eslint-disable-next-line no-throw-literal
25662614
get foo() { throw undefined; }
25672615
}, { getters: true }),
2568-
'{ foo: [Getter: <Inspection threw>] }'
2616+
'{ foo: [Getter: <Inspection threw (undefined)>] }'
25692617
);
25702618
assert.strictEqual(
25712619
inspect({
25722620
// eslint-disable-next-line no-throw-literal
2573-
get foo() { throw true; }
2621+
get foo() { throw null; }
25742622
}, { getters: true }),
2575-
'{ foo: [Getter: <Inspection threw>] }'
2623+
'{ foo: [Getter: <Inspection threw (null)>] }'
25762624
);
25772625
assert.strictEqual(
25782626
inspect({
25792627
// eslint-disable-next-line no-throw-literal
2580-
get foo() { throw {}; }
2628+
get foo() { throw 'string'; }
25812629
}, { getters: true }),
2582-
'{ foo: [Getter: <Inspection threw>] }'
2630+
"{ foo: [Getter: <Inspection threw ('string')>] }"
25832631
);
25842632
assert.strictEqual(
25852633
inspect({
2586-
get foo() { throw Error; }
2634+
// eslint-disable-next-line no-throw-literal
2635+
get foo() { throw true; }
25872636
}, { getters: true }),
2588-
'{ foo: [Getter: <Inspection threw>] }'
2589-
);
2590-
}
2591-
2592-
// Property getter throwing an error with message getter that throws.
2593-
{
2594-
const error = {
2595-
// The message itself is a getter that throws
2596-
get message() { throw new Error('Oops'); }
2597-
};
2598-
2599-
const thrower = {
2600-
get foo() { throw error; }
2601-
};
2602-
2603-
assert.strictEqual(
2604-
inspect(thrower, { getters: true }),
2605-
'{ foo: [Getter: <Inspection threw>] }'
2637+
'{ foo: [Getter: <Inspection threw (true)>] }'
26062638
);
2607-
}
2608-
2609-
// Property getter throwing an error with a bad message.
2610-
{
26112639
assert.strictEqual(
26122640
inspect({
2613-
get foo() { throw new Error(undefined); }
2641+
// eslint-disable-next-line no-throw-literal
2642+
get foo() { throw {}; }
26142643
}, { getters: true }),
2615-
'{ foo: [Getter: <Inspection threw ()>] }'
2644+
'{ foo: [Getter: <Inspection threw ({})>] }'
26162645
);
26172646
assert.strictEqual(
26182647
inspect({
2619-
get foo() { throw new Error(''); }
2648+
// eslint-disable-next-line no-throw-literal
2649+
get foo() { throw { get message() { return 'Oops'; } }; }
26202650
}, { getters: true }),
2621-
'{ foo: [Getter: <Inspection threw ()>] }'
2651+
'{ foo: [Getter: <Inspection threw ({ message: [Getter] })>] }'
26222652
);
26232653
assert.strictEqual(
26242654
inspect({
2625-
get foo() { throw new Error(null); }
2655+
get foo() { throw Error; }
26262656
}, { getters: true }),
2627-
'{ foo: [Getter: <Inspection threw (null)>] }'
2657+
'{\n' +
2658+
' foo: [Getter: <Inspection threw ([Function: Error] { stackTraceLimit: 0 })>]\n' +
2659+
'}'
26282660
);
26292661
}
26302662

@@ -3316,8 +3348,19 @@ assert.strictEqual(
33163348
' [length]: 0,\n' +
33173349
" [name]: 'Bar',\n" +
33183350
' [prototype]: [Circular *1],\n' +
3319-
' [Symbol(Symbol.species)]: [Getter: <Inspection threw ' +
3320-
"(Symbol.prototype.toString requires that 'this' be a Symbol)>]\n" +
3351+
// Heh? I don't know how to override the error stakc to make it predictable
3352+
' [Symbol(Symbol.species)]: ' +
3353+
"[Getter: <Inspection threw (TypeError: Symbol.prototype.toString requires that 'this' be a Symbol\n" +
3354+
' at Bar.toString (<anonymous>)\n' +
3355+
' at formatPrimitive (node:internal/util/inspect:2246:13)\n' +
3356+
' at formatProperty (node:internal/util/inspect:2556:29)\n' +
3357+
' at addPrototypeProperties (node:internal/util/inspect:1010:21)\n' +
3358+
' at getConstructorName (node:internal/util/inspect:918:11)\n' +
3359+
' at formatRaw (node:internal/util/inspect:1194:23)\n' +
3360+
' at formatValue (node:internal/util/inspect:1184:10)\n' +
3361+
' at formatProperty (node:internal/util/inspect:2536:11)\n' +
3362+
' at formatRaw (node:internal/util/inspect:1429:9)\n' +
3363+
' at formatValue (node:internal/util/inspect:1184:10))>]\n' +
33213364
' },\n' +
33223365
" [xyz]: [Getter: 'YES!'],\n" +
33233366
' [Symbol(nodejs.util.inspect.custom)]: ' +

0 commit comments

Comments
 (0)