diff --git a/lib/internal/util/inspect.js b/lib/internal/util/inspect.js index 701cc34cebff15..7054e35477e172 100644 --- a/lib/internal/util/inspect.js +++ b/lib/internal/util/inspect.js @@ -117,6 +117,9 @@ const setSizeGetter = uncurryThis( ObjectGetOwnPropertyDescriptor(SetPrototype, 'size').get); const mapSizeGetter = uncurryThis( ObjectGetOwnPropertyDescriptor(MapPrototype, 'size').get); +const typedArraySizeGetter = uncurryThis( + ObjectGetOwnPropertyDescriptor( + ObjectGetPrototypeOf(Uint8Array.prototype), 'length').get); let hexSlice; @@ -567,18 +570,18 @@ function addPrototypeProperties(ctx, main, obj, recurseTimes, isProto, output) { } while (++depth !== 3); } -function getPrefix(constructor, tag, fallback) { +function getPrefix(constructor, tag, fallback, size = '') { if (constructor === null) { if (tag !== '') { - return `[${fallback}: null prototype] [${tag}] `; + return `[${fallback}${size}: null prototype] [${tag}] `; } - return `[${fallback}: null prototype] `; + return `[${fallback}${size}: null prototype] `; } if (tag !== '' && constructor !== tag) { - return `${constructor} [${tag}] `; + return `${constructor}${size} [${tag}] `; } - return `${constructor} `; + return `${constructor}${size} `; } // Look up the keys of the object. @@ -763,58 +766,48 @@ function formatRaw(ctx, value, recurseTimes, typedArray) { if (value[SymbolIterator] || constructor === null) { noIterator = false; if (ArrayIsArray(value)) { - keys = getOwnNonIndexProperties(value, filter); // Only set the constructor for non ordinary ("Array [...]") arrays. - const prefix = getPrefix(constructor, tag, 'Array'); - braces = [`${prefix === 'Array ' ? '' : prefix}[`, ']']; + const prefix = (constructor !== 'Array' || tag !== '') ? + getPrefix(constructor, tag, 'Array', `(${value.length})`) : + ''; + keys = getOwnNonIndexProperties(value, filter); + braces = [`${prefix}[`, ']']; if (value.length === 0 && keys.length === 0 && protoProps === undefined) return `${braces[0]}]`; extrasType = kArrayExtrasType; formatter = formatArray; } else if (isSet(value)) { const size = setSizeGetter(value); + const prefix = getPrefix(constructor, tag, 'Set', `(${size})`); keys = getKeys(value, ctx.showHidden); - let prefix = ''; - if (constructor !== null) { - if (constructor === tag) - tag = ''; - prefix = getPrefix(`${constructor}(${size})`, tag, ''); - formatter = formatSet.bind(null, value, size); - } else { - prefix = getPrefix(constructor, tag, `Set(${size})`); - formatter = formatSet.bind(null, SetPrototypeValues(value), size); - } + formatter = constructor !== null ? + formatSet.bind(null, value) : + formatSet.bind(null, SetPrototypeValues(value)); if (size === 0 && keys.length === 0 && protoProps === undefined) return `${prefix}{}`; braces = [`${prefix}{`, '}']; } else if (isMap(value)) { const size = mapSizeGetter(value); + const prefix = getPrefix(constructor, tag, 'Map', `(${size})`); keys = getKeys(value, ctx.showHidden); - let prefix = ''; - if (constructor !== null) { - if (constructor === tag) - tag = ''; - prefix = getPrefix(`${constructor}(${size})`, tag, ''); - formatter = formatMap.bind(null, value, size); - } else { - prefix = getPrefix(constructor, tag, `Map(${size})`); - formatter = formatMap.bind(null, MapPrototypeEntries(value), size); - } + formatter = constructor !== null ? + formatMap.bind(null, value) : + formatMap.bind(null, MapPrototypeEntries(value)); if (size === 0 && keys.length === 0 && protoProps === undefined) return `${prefix}{}`; braces = [`${prefix}{`, '}']; } else if (isTypedArray(value)) { keys = getOwnNonIndexProperties(value, filter); let bound = value; - let prefix = ''; + let fallback = ''; if (constructor === null) { const constr = findTypedConstructor(value); - prefix = getPrefix(constructor, tag, constr.name); + fallback = constr.name; // Reconstruct the array information. bound = new constr(value); - } else { - prefix = getPrefix(constructor, tag); } + const size = typedArraySizeGetter(value); + const prefix = getPrefix(constructor, tag, fallback, `(${size})`); braces = [`${prefix}[`, ']']; if (value.length === 0 && keys.length === 0 && !ctx.showHidden) return `${braces[0]}]`; @@ -1430,7 +1423,7 @@ function formatTypedArray(value, ctx, ignored, recurseTimes) { return output; } -function formatSet(value, size, ctx, ignored, recurseTimes) { +function formatSet(value, ctx, ignored, recurseTimes) { const output = []; ctx.indentationLvl += 2; for (const v of value) { @@ -1440,7 +1433,7 @@ function formatSet(value, size, ctx, ignored, recurseTimes) { return output; } -function formatMap(value, size, ctx, ignored, recurseTimes) { +function formatMap(value, ctx, ignored, recurseTimes) { const output = []; ctx.indentationLvl += 2; for (const [k, v] of value) { diff --git a/test/parallel/test-assert-deep.js b/test/parallel/test-assert-deep.js index fc2f96741ca7ef..454b1920f00aee 100644 --- a/test/parallel/test-assert-deep.js +++ b/test/parallel/test-assert-deep.js @@ -51,8 +51,8 @@ assert.throws( { code: 'ERR_ASSERTION', message: `${defaultMsgStartFull} ... Lines skipped\n\n` + - '+ Uint8Array [\n' + - '- Buffer [Uint8Array] [\n 120,\n...\n 122,\n 10\n ]' + '+ Uint8Array(4) [\n' + + '- Buffer(4) [Uint8Array] [\n 120,\n...\n 122,\n 10\n ]' } ); assert.deepEqual(arr, buf); @@ -66,7 +66,7 @@ assert.deepEqual(arr, buf); { code: 'ERR_ASSERTION', message: `${defaultMsgStartFull}\n\n` + - ' Buffer [Uint8Array] [\n' + + ' Buffer(4) [Uint8Array] [\n' + ' 120,\n' + ' 121,\n' + ' 122,\n' + @@ -86,7 +86,7 @@ assert.deepEqual(arr, buf); { code: 'ERR_ASSERTION', message: `${defaultMsgStartFull}\n\n` + - ' Uint8Array [\n' + + ' Uint8Array(4) [\n' + ' 120,\n' + ' 121,\n' + ' 122,\n' + diff --git a/test/parallel/test-buffer-inspect.js b/test/parallel/test-buffer-inspect.js index d6ecf6b7fc5c38..1e8212e876344a 100644 --- a/test/parallel/test-buffer-inspect.js +++ b/test/parallel/test-buffer-inspect.js @@ -58,7 +58,7 @@ b.inspect = undefined; b.prop = new Uint8Array(0); assert.strictEqual( util.inspect(b), - '' + '' ); b = Buffer.alloc(0); diff --git a/test/parallel/test-fs-read-empty-buffer.js b/test/parallel/test-fs-read-empty-buffer.js index 2f44b9a1843a6b..8ca08448182d4a 100644 --- a/test/parallel/test-fs-read-empty-buffer.js +++ b/test/parallel/test-fs-read-empty-buffer.js @@ -15,7 +15,7 @@ assert.throws( { code: 'ERR_INVALID_ARG_VALUE', message: 'The argument \'buffer\' is empty and cannot be written. ' + - 'Received Uint8Array []' + 'Received Uint8Array(0) []' } ); @@ -24,7 +24,7 @@ assert.throws( { code: 'ERR_INVALID_ARG_VALUE', message: 'The argument \'buffer\' is empty and cannot be written. ' + - 'Received Uint8Array []' + 'Received Uint8Array(0) []' } ); @@ -35,7 +35,7 @@ assert.throws( { code: 'ERR_INVALID_ARG_VALUE', message: 'The argument \'buffer\' is empty and cannot be written. ' + - 'Received Uint8Array []' + 'Received Uint8Array(0) []' } ); })(); diff --git a/test/parallel/test-util-format.js b/test/parallel/test-util-format.js index e07ec6d6a34c2f..0599fda1d63456 100644 --- a/test/parallel/test-util-format.js +++ b/test/parallel/test-util-format.js @@ -158,7 +158,7 @@ assert.strictEqual(util.format('%s', () => 5), '() => 5'); class Foobar extends Array { aaa = true; } assert.strictEqual( util.format('%s', new Foobar(5)), - 'Foobar [ <5 empty items>, aaa: true ]' + 'Foobar(5) [ <5 empty items>, aaa: true ]' ); // Subclassing: diff --git a/test/parallel/test-util-inspect.js b/test/parallel/test-util-inspect.js index 93a22743cec320..7795b1adffd27f 100644 --- a/test/parallel/test-util-inspect.js +++ b/test/parallel/test-util-inspect.js @@ -127,7 +127,7 @@ assert.strictEqual(util.inspect({ 'a': { 'b': { 'c': 2 } } }, false, 1), '{ a: { b: [Object] } }'); assert.strictEqual(util.inspect({ 'a': { 'b': ['c'] } }, false, 1), '{ a: { b: [Array] } }'); -assert.strictEqual(util.inspect(new Uint8Array(0)), 'Uint8Array []'); +assert.strictEqual(util.inspect(new Uint8Array(0)), 'Uint8Array(0) []'); assert(inspect(new Uint8Array(0), { showHidden: true }).includes('[buffer]')); assert.strictEqual( util.inspect( @@ -264,7 +264,7 @@ assert(!/Object/.test( array[1] = 97; assert.strictEqual( util.inspect(array, { showHidden: true }), - `${constructor.name} [\n` + + `${constructor.name}(${length}) [\n` + ' 65,\n' + ' 97,\n' + ` [BYTES_PER_ELEMENT]: ${constructor.BYTES_PER_ELEMENT},\n` + @@ -274,7 +274,7 @@ assert(!/Object/.test( ` [buffer]: ArrayBuffer { byteLength: ${byteLength} }\n]`); assert.strictEqual( util.inspect(array, false), - `${constructor.name} [ 65, 97 ]` + `${constructor.name}(${length}) [ 65, 97 ]` ); }); @@ -298,7 +298,7 @@ assert(!/Object/.test( array[1] = 97; assert.strictEqual( util.inspect(array, true), - `${constructor.name} [\n` + + `${constructor.name}(${length}) [\n` + ' 65,\n' + ' 97,\n' + ` [BYTES_PER_ELEMENT]: ${constructor.BYTES_PER_ELEMENT},\n` + @@ -308,7 +308,7 @@ assert(!/Object/.test( ` [buffer]: ArrayBuffer { byteLength: ${byteLength} }\n]`); assert.strictEqual( util.inspect(array, false), - `${constructor.name} [ 65, 97 ]` + `${constructor.name}(${length}) [ 65, 97 ]` ); }); @@ -398,11 +398,11 @@ assert.strictEqual( arr[49] = 'I win'; assert.strictEqual( util.inspect(arr), - "CustomArray [ <49 empty items>, 'I win' ]" + "CustomArray(50) [ <49 empty items>, 'I win' ]" ); assert.strictEqual( util.inspect(arr, { showHidden: true }), - 'CustomArray [\n' + + 'CustomArray(50) [\n' + ' <49 empty items>,\n' + " 'I win',\n" + ' [length]: 50,\n' + @@ -1301,7 +1301,7 @@ if (typeof Symbol !== 'undefined') { assert.strictEqual(util.inspect(x), 'ObjectSubclass { foo: 42 }'); assert.strictEqual(util.inspect(new ArraySubclass(1, 2, 3)), - 'ArraySubclass [ 1, 2, 3 ]'); + 'ArraySubclass(3) [ 1, 2, 3 ]'); assert.strictEqual(util.inspect(new SetSubclass([1, 2, 3])), 'SetSubclass(3) [Set] { 1, 2, 3 }'); assert.strictEqual(util.inspect(new MapSubclass([['foo', 42]])), @@ -1397,7 +1397,7 @@ if (typeof Symbol !== 'undefined') { assert(util.inspect(x).endsWith('1 more item\n]')); assert(!util.inspect(x, { maxArrayLength: 101 }).includes('1 more item')); assert.strictEqual(util.inspect(x, { maxArrayLength: 0 }), - 'Uint8Array [ ... 101 more items ]'); + 'Uint8Array(101) [ ... 101 more items ]'); assert(!util.inspect(x, { maxArrayLength: null }).includes('1 more item')); assert(util.inspect(x, { maxArrayLength: Infinity }).endsWith(' 0, 0\n]')); } @@ -1681,7 +1681,7 @@ util.inspect(process); ' ],', ' [length]: 1', ' ]', - ' } => Uint8Array [', + ' } => Uint8Array(0) [', ' [BYTES_PER_ELEMENT]: 1,', ' [length]: 0,', ' [byteLength]: 0,', @@ -1698,7 +1698,7 @@ util.inspect(process); ' [length]: 2', ' ]', ' } => [Map Iterator] {', - ' Uint8Array [', + ' Uint8Array(0) [', ' [BYTES_PER_ELEMENT]: 1,', ' [length]: 0,', ' [byteLength]: 0,', @@ -1728,7 +1728,7 @@ util.inspect(process); ' ],', ' [length]: 1', ' ]', - ' } => Uint8Array [', + ' } => Uint8Array(0) [', ' [BYTES_PER_ELEMENT]: 1,', ' [length]: 0,', ' [byteLength]: 0,', @@ -1736,7 +1736,7 @@ util.inspect(process); ' [buffer]: ArrayBuffer { byteLength: 0, foo: true }', ' ],', ' [Set Iterator] { [ 1, 2, [length]: 2 ] } => [Map Iterator] {', - ' Uint8Array [', + ' Uint8Array(0) [', ' [BYTES_PER_ELEMENT]: 1,', ' [length]: 0,', ' [byteLength]: 0,', @@ -1762,7 +1762,7 @@ util.inspect(process); ' 2,', ' [length]: 2 ] },', ' [length]: 2 ],', - ' [length]: 1 ] } => Uint8Array [', + ' [length]: 1 ] } => Uint8Array(0) [', ' [BYTES_PER_ELEMENT]: 1,', ' [length]: 0,', ' [byteLength]: 0,', @@ -1774,7 +1774,7 @@ util.inspect(process); ' [ 1,', ' 2,', ' [length]: 2 ] } => [Map Iterator] {', - ' Uint8Array [', + ' Uint8Array(0) [', ' [BYTES_PER_ELEMENT]: 1,', ' [length]: 0,', ' [byteLength]: 0,', @@ -1951,7 +1951,7 @@ assert.strictEqual(util.inspect('"\'${a}'), "'\"\\'${a}'"); [new Set([1, 2]).entries(), '[Set Entries] { [ 1, 1 ], [ 2, 2 ] }'], [new Map([[1, 2]]).keys(), '[Map Iterator] { 1 }'], [new Date(2000), '1970-01-01T00:00:02.000Z'], - [new Uint8Array(2), 'Uint8Array [ 0, 0 ]'], + [new Uint8Array(2), 'Uint8Array(2) [ 0, 0 ]'], [new Promise((resolve) => setTimeout(resolve, 10)), 'Promise { }'], [new WeakSet(), 'WeakSet { }'], [new WeakMap(), 'WeakMap { }'], @@ -1977,23 +1977,23 @@ assert.strictEqual(util.inspect('"\'${a}'), "'\"\\'${a}'"); // Verify that having no prototype still produces nice results. [ - [[1, 3, 4], '[Array: null prototype] [ 1, 3, 4 ]'], + [[1, 3, 4], '[Array(3): null prototype] [ 1, 3, 4 ]'], [new Set([1, 2]), '[Set(2): null prototype] { 1, 2 }'], [new Map([[1, 2]]), '[Map(1): null prototype] { 1 => 2 }'], [new Promise((resolve) => setTimeout(resolve, 10)), '[Promise: null prototype] { }'], [new WeakSet(), '[WeakSet: null prototype] { }'], [new WeakMap(), '[WeakMap: null prototype] { }'], - [new Uint8Array(2), '[Uint8Array: null prototype] [ 0, 0 ]'], - [new Uint16Array(2), '[Uint16Array: null prototype] [ 0, 0 ]'], - [new Uint32Array(2), '[Uint32Array: null prototype] [ 0, 0 ]'], - [new Int8Array(2), '[Int8Array: null prototype] [ 0, 0 ]'], - [new Int16Array(2), '[Int16Array: null prototype] [ 0, 0 ]'], - [new Int32Array(2), '[Int32Array: null prototype] [ 0, 0 ]'], - [new Float32Array(2), '[Float32Array: null prototype] [ 0, 0 ]'], - [new Float64Array(2), '[Float64Array: null prototype] [ 0, 0 ]'], - [new BigInt64Array(2), '[BigInt64Array: null prototype] [ 0n, 0n ]'], - [new BigUint64Array(2), '[BigUint64Array: null prototype] [ 0n, 0n ]'], + [new Uint8Array(2), '[Uint8Array(2): null prototype] [ 0, 0 ]'], + [new Uint16Array(2), '[Uint16Array(2): null prototype] [ 0, 0 ]'], + [new Uint32Array(2), '[Uint32Array(2): null prototype] [ 0, 0 ]'], + [new Int8Array(2), '[Int8Array(2): null prototype] [ 0, 0 ]'], + [new Int16Array(2), '[Int16Array(2): null prototype] [ 0, 0 ]'], + [new Int32Array(2), '[Int32Array(2): null prototype] [ 0, 0 ]'], + [new Float32Array(2), '[Float32Array(2): null prototype] [ 0, 0 ]'], + [new Float64Array(2), '[Float64Array(2): null prototype] [ 0, 0 ]'], + [new BigInt64Array(2), '[BigInt64Array(2): null prototype] [ 0n, 0n ]'], + [new BigUint64Array(2), '[BigUint64Array(2): null prototype] [ 0n, 0n ]'], [new ArrayBuffer(16), '[ArrayBuffer: null prototype] {\n' + ' [Uint8Contents]: <00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00>,\n' + ' byteLength: undefined\n}'], @@ -2031,8 +2031,10 @@ assert.strictEqual(util.inspect('"\'${a}'), "'\"\\'${a}'"); class Foo extends base {} const value = new Foo(...input); const symbol = value[Symbol.toStringTag]; - const expected = `Foo ${symbol ? `[${symbol}] ` : ''}${rawExpected}`; - const expectedWithoutProto = `[${base.name}: null prototype] ${rawExpected}`; + const size = base.name.includes('Array') ? `(${input[0]})` : ''; + const expected = `Foo${size} ${symbol ? `[${symbol}] ` : ''}${rawExpected}`; + const expectedWithoutProto = + `[${base.name}${size}: null prototype] ${rawExpected}`; assert.strictEqual(util.inspect(value), expected); value.foo = 'bar'; assert.notStrictEqual(util.inspect(value), expected); @@ -2055,8 +2057,9 @@ assert.strictEqual(util.inspect('"\'${a}'), "'\"\\'${a}'"); assert.strictEqual(inspect(1n), '1n'); assert.strictEqual(inspect(Object(-1n)), '[BigInt: -1n]'); assert.strictEqual(inspect(Object(13n)), '[BigInt: 13n]'); -assert.strictEqual(inspect(new BigInt64Array([0n])), 'BigInt64Array [ 0n ]'); -assert.strictEqual(inspect(new BigUint64Array([0n])), 'BigUint64Array [ 0n ]'); +assert.strictEqual(inspect(new BigInt64Array([0n])), 'BigInt64Array(1) [ 0n ]'); +assert.strictEqual( + inspect(new BigUint64Array([0n])), 'BigUint64Array(1) [ 0n ]'); // Verify non-enumerable keys get escaped. { @@ -2175,7 +2178,7 @@ assert.strictEqual( Object.setPrototypeOf(obj, value); assert.strictEqual( util.inspect(obj), - 'Object <[Array: null prototype] []> { a: true }' + 'Object <[Array(0): null prototype] []> { a: true }' ); function StorageObject() {}