Skip to content

Commit 0b314ef

Browse files
lib: enhance error formatting in util.inspect
1 parent f38e4e8 commit 0b314ef

File tree

2 files changed

+24
-103
lines changed

2 files changed

+24
-103
lines changed

lib/internal/util/inspect.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1902,6 +1902,13 @@ function formatError(err, constructor, tag, ctx, keys) {
19021902
const name = err.name != null ? err.name : 'Error';
19031903
let stack = getStackString(ctx, err);
19041904

1905+
if (tag !== '' && constructor !== null &&
1906+
StringPrototypeIncludes(constructor, 'Error') &&
1907+
!StringPrototypeIncludes(tag, 'Error') &&
1908+
StringPrototypeStartsWith(constructor, tag)) {
1909+
return `[${tag}: ${err.message}]`;
1910+
}
1911+
19051912
removeDuplicateErrorKeys(ctx, keys, err, stack);
19061913

19071914
if ('cause' in err &&

test/parallel/test-util-inspect.js

Lines changed: 17 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -85,88 +85,6 @@ assert.strictEqual(util.inspect(async () => {}), '[AsyncFunction (anonymous)]');
8585
);
8686
}
8787

88-
// Null constructor scenarios
89-
{
90-
function fnNull() {}
91-
Object.setPrototypeOf(fnNull, null);
92-
assert.strictEqual(
93-
util.inspect(fnNull),
94-
'[Function (null prototype): fnNull]'
95-
);
96-
97-
function fnNullAndStringTag() {}
98-
Object.defineProperty(fnNullAndStringTag, Symbol.toStringTag, {
99-
value: 'CustomTag',
100-
configurable: true
101-
});
102-
Object.setPrototypeOf(fnNullAndStringTag, null);
103-
assert.strictEqual(
104-
util.inspect(fnNullAndStringTag),
105-
'[Function (null prototype): fnNullAndStringTag] [CustomTag]'
106-
);
107-
108-
function fnAnonymous() {}
109-
Object.defineProperty(fnAnonymous, Symbol.toStringTag, {
110-
value: 'AnonymousCustom',
111-
configurable: true
112-
});
113-
Object.setPrototypeOf(fnAnonymous, null);
114-
assert.strictEqual(
115-
util.inspect(fnAnonymous),
116-
'[Function (null prototype): fnAnonymous] [AnonymousCustom]'
117-
);
118-
119-
const fnArrow = () => {};
120-
Object.setPrototypeOf(fnArrow, null);
121-
assert.strictEqual(
122-
util.inspect(fnArrow),
123-
'[Function (null prototype): fnArrow]'
124-
);
125-
126-
async function fnAsync() {}
127-
Object.defineProperty(fnAsync, Symbol.toStringTag, {
128-
value: 'AsyncCustom',
129-
configurable: true
130-
});
131-
Object.setPrototypeOf(fnAsync, null);
132-
assert.strictEqual(
133-
util.inspect(fnAsync),
134-
'[AsyncFunction (null prototype): fnAsync] [AsyncCustom]'
135-
);
136-
137-
class TestClass {}
138-
Object.defineProperty(TestClass, Symbol.toStringTag, {
139-
value: 'ClassTag',
140-
configurable: true
141-
});
142-
Object.setPrototypeOf(TestClass, null);
143-
assert.strictEqual(
144-
util.inspect(TestClass),
145-
'[class TestClass [ClassTag] extends [null prototype]]'
146-
);
147-
148-
function fnMatchConstructor() {}
149-
Object.defineProperty(fnMatchConstructor, Symbol.toStringTag, {
150-
value: 'Function',
151-
configurable: true
152-
});
153-
assert.strictEqual(
154-
util.inspect(fnMatchConstructor),
155-
'[Function: fnMatchConstructor]'
156-
);
157-
158-
function fnNullMatchConstructor() {}
159-
Object.defineProperty(fnNullMatchConstructor, Symbol.toStringTag, {
160-
value: 'Function',
161-
configurable: true
162-
});
163-
Object.setPrototypeOf(fnNullMatchConstructor, null);
164-
assert.strictEqual(
165-
util.inspect(fnNullMatchConstructor),
166-
'[Function (null prototype): fnNullMatchConstructor] [Function]'
167-
);
168-
}
169-
17088
assert.strictEqual(util.inspect(undefined), 'undefined');
17189
assert.strictEqual(util.inspect(null), 'null');
17290
assert.strictEqual(util.inspect(/foo(bar\n)?/gi), '/foo(bar\\n)?/gi');
@@ -1497,11 +1415,11 @@ if (typeof Symbol !== 'undefined') {
14971415
assert.strictEqual(util.inspect(new ArraySubclass(1, 2, 3)),
14981416
'ArraySubclass(3) [ 1, 2, 3 ]');
14991417
assert.strictEqual(util.inspect(new SetSubclass([1, 2, 3])),
1500-
'SetSubclass(3) [Set] { 1, 2, 3 }');
1418+
'SetSubclass(3) { 1, 2, 3 }');
15011419
assert.strictEqual(util.inspect(new MapSubclass([['foo', 42]])),
1502-
"MapSubclass(1) [Map] { 'foo' => 42 }");
1420+
"MapSubclass(1) { 'foo' => 42 }");
15031421
assert.strictEqual(util.inspect(new PromiseSubclass(() => {})),
1504-
'PromiseSubclass [Promise] { <pending> }');
1422+
'PromiseSubclass { <pending> }');
15051423
assert.strictEqual(util.inspect(new SymbolNameClass()),
15061424
'Symbol(name) {}');
15071425
assert.strictEqual(
@@ -1513,35 +1431,31 @@ if (typeof Symbol !== 'undefined') {
15131431
'[ObjectSubclass: null prototype] { foo: 42 }'
15141432
);
15151433

1516-
class CustomClass {}
1517-
Object.defineProperty(CustomClass.prototype, Symbol.toStringTag, {
1518-
value: 'Custom',
1434+
class MiddleErrorPart extends Error {}
1435+
Object.defineProperty(MiddleErrorPart.prototype, Symbol.toStringTag, {
1436+
value: 'Middle',
15191437
configurable: true
15201438
});
1521-
assert.strictEqual(util.inspect(new CustomClass()),
1522-
'CustomClass [Custom] {}');
1439+
assert.strictEqual(util.inspect(new MiddleErrorPart('foo')),
1440+
'[Middle: foo]');
15231441

15241442
class MapClass extends Map {}
1525-
Object.defineProperty(MapClass.prototype, Symbol.toStringTag, {
1526-
value: 'Map',
1527-
configurable: true
1528-
});
15291443
assert.strictEqual(util.inspect(new MapClass([['key', 'value']])),
1530-
"MapClass(1) [Map] { 'key' => 'value' }");
1444+
"MapClass(1) { 'key' => 'value' }");
1445+
1446+
class AbcMap extends Map {}
1447+
assert.strictEqual(util.inspect(new AbcMap([['key', 'value']])),
1448+
"AbcMap(1) { 'key' => 'value' }");
1449+
1450+
class SetAbc extends Set {}
1451+
assert.strictEqual(util.inspect(new SetAbc([1, 2, 3])),
1452+
'SetAbc(3) { 1, 2, 3 }');
15311453

15321454
class FooSet extends Set {}
1533-
Object.defineProperty(FooSet.prototype, Symbol.toStringTag, {
1534-
value: 'Set',
1535-
configurable: true
1536-
});
15371455
assert.strictEqual(util.inspect(new FooSet([1, 2, 3])),
15381456
'FooSet(3) { 1, 2, 3 }');
15391457

15401458
class Settings extends Set {}
1541-
Object.defineProperty(Settings.prototype, Symbol.toStringTag, {
1542-
value: 'Set',
1543-
configurable: true
1544-
});
15451459
assert.strictEqual(util.inspect(new Settings([1, 2, 3])),
15461460
'Settings(3) [Set] { 1, 2, 3 }');
15471461
}

0 commit comments

Comments
 (0)