diff --git a/lib/internal/util/inspect.js b/lib/internal/util/inspect.js index bc25cfdd3899b6..0bbd527feff0be 100644 --- a/lib/internal/util/inspect.js +++ b/lib/internal/util/inspect.js @@ -780,7 +780,7 @@ function getPrefix(constructor, tag, fallback, size = '') { return `[${fallback}${size}: null prototype] `; } - if (tag !== '' && constructor !== tag) { + if (tag !== '' && !constructor.includes(tag)) { return `${constructor}${size} [${tag}] `; } return `${constructor}${size} `; @@ -1248,7 +1248,7 @@ function getClassBase(value, constructor, tag) { if (constructor !== 'Function' && constructor !== null) { base += ` [${constructor}]`; } - if (tag !== '' && constructor !== tag) { + if (tag !== '' && (constructor === null || !constructor.includes(tag))) { base += ` [${tag}]`; } if (constructor !== null) { @@ -1295,7 +1295,7 @@ function getFunctionBase(ctx, value, constructor, tag) { if (constructor !== type && constructor !== null) { base += ` ${constructor}`; } - if (tag !== '' && constructor !== tag) { + if (tag !== '' && (constructor === null || !constructor.includes(tag))) { base += ` [${tag}]`; } return base; diff --git a/test/es-module/test-esm-loader-with-syntax-error.mjs b/test/es-module/test-esm-loader-with-syntax-error.mjs index 835aa284374833..a2461677730a63 100644 --- a/test/es-module/test-esm-loader-with-syntax-error.mjs +++ b/test/es-module/test-esm-loader-with-syntax-error.mjs @@ -13,7 +13,7 @@ describe('ESM: loader with syntax error', { concurrency: !process.env.TEST_PARAL path('print-error-message.js'), ]); - match(stderr, /SyntaxError \[Error\]:/); + match(stderr, /SyntaxError/); ok(!stderr.includes('Bad command or file name')); notStrictEqual(code, 0); }); diff --git a/test/parallel/test-util-inspect.js b/test/parallel/test-util-inspect.js index 5aafb4378c18e1..670c2ee76df35a 100644 --- a/test/parallel/test-util-inspect.js +++ b/test/parallel/test-util-inspect.js @@ -85,6 +85,88 @@ assert.strictEqual(util.inspect(async () => {}), '[AsyncFunction (anonymous)]'); ); } +// Null constructor scenarios +{ + function fnNull() {} + Object.setPrototypeOf(fnNull, null); + assert.strictEqual( + util.inspect(fnNull), + '[Function (null prototype): fnNull]' + ); + + function fnNullAndStringTag() {} + Object.defineProperty(fnNullAndStringTag, Symbol.toStringTag, { + value: 'CustomTag', + configurable: true + }); + Object.setPrototypeOf(fnNullAndStringTag, null); + assert.strictEqual( + util.inspect(fnNullAndStringTag), + '[Function (null prototype): fnNullAndStringTag] [CustomTag]' + ); + + function fnAnonymous() {} + Object.defineProperty(fnAnonymous, Symbol.toStringTag, { + value: 'AnonymousCustom', + configurable: true + }); + Object.setPrototypeOf(fnAnonymous, null); + assert.strictEqual( + util.inspect(fnAnonymous), + '[Function (null prototype): fnAnonymous] [AnonymousCustom]' + ); + + const fnArrow = () => {}; + Object.setPrototypeOf(fnArrow, null); + assert.strictEqual( + util.inspect(fnArrow), + '[Function (null prototype): fnArrow]' + ); + + async function fnAsync() {} + Object.defineProperty(fnAsync, Symbol.toStringTag, { + value: 'AsyncCustom', + configurable: true + }); + Object.setPrototypeOf(fnAsync, null); + assert.strictEqual( + util.inspect(fnAsync), + '[AsyncFunction (null prototype): fnAsync] [AsyncCustom]' + ); + + class TestClass {} + Object.defineProperty(TestClass, Symbol.toStringTag, { + value: 'ClassTag', + configurable: true + }); + Object.setPrototypeOf(TestClass, null); + assert.strictEqual( + util.inspect(TestClass), + '[class TestClass [ClassTag] extends [null prototype]]' + ); + + function fnMatchConstructor() {} + Object.defineProperty(fnMatchConstructor, Symbol.toStringTag, { + value: 'Function', + configurable: true + }); + assert.strictEqual( + util.inspect(fnMatchConstructor), + '[Function: fnMatchConstructor]' + ); + + function fnNullMatchConstructor() {} + Object.defineProperty(fnNullMatchConstructor, Symbol.toStringTag, { + value: 'Function', + configurable: true + }); + Object.setPrototypeOf(fnNullMatchConstructor, null); + assert.strictEqual( + util.inspect(fnNullMatchConstructor), + '[Function (null prototype): fnNullMatchConstructor] [Function]' + ); +} + assert.strictEqual(util.inspect(undefined), 'undefined'); assert.strictEqual(util.inspect(null), 'null'); assert.strictEqual(util.inspect(/foo(bar\n)?/gi), '/foo(bar\\n)?/gi'); @@ -1415,11 +1497,11 @@ if (typeof Symbol !== 'undefined') { assert.strictEqual(util.inspect(new ArraySubclass(1, 2, 3)), 'ArraySubclass(3) [ 1, 2, 3 ]'); assert.strictEqual(util.inspect(new SetSubclass([1, 2, 3])), - 'SetSubclass(3) [Set] { 1, 2, 3 }'); + 'SetSubclass(3) { 1, 2, 3 }'); assert.strictEqual(util.inspect(new MapSubclass([['foo', 42]])), - "MapSubclass(1) [Map] { 'foo' => 42 }"); + "MapSubclass(1) { 'foo' => 42 }"); assert.strictEqual(util.inspect(new PromiseSubclass(() => {})), - 'PromiseSubclass [Promise] { }'); + 'PromiseSubclass { }'); assert.strictEqual(util.inspect(new SymbolNameClass()), 'Symbol(name) {}'); assert.strictEqual(