Skip to content

Commit d3c0f46

Browse files
BridgeARBethGriggs
authored andcommitted
util: add (typed) array length to the default output
Align the inspect output with the one used in the Chrome dev tools. A recent survey outlined that most users prefer to see the number of set and map entries. This should count as well for array sizes. The size is only added to regular arrays in case the constructor is not the default constructor. Typed arrays always indicate their size. Backport-PR-URL: #31431 PR-URL: #31027 Reviewed-By: Michaël Zasso <[email protected]> Reviewed-By: Rich Trott <[email protected]> Reviewed-By: Anto Aravinth <[email protected]>
1 parent 19a3f8b commit d3c0f46

File tree

6 files changed

+69
-73
lines changed

6 files changed

+69
-73
lines changed

‎lib/internal/util/inspect.js‎

Lines changed: 25 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,9 @@ const setSizeGetter = uncurryThis(
119119
ObjectGetOwnPropertyDescriptor(SetPrototype,'size').get);
120120
constmapSizeGetter=uncurryThis(
121121
ObjectGetOwnPropertyDescriptor(MapPrototype,'size').get);
122+
consttypedArraySizeGetter=uncurryThis(
123+
ObjectGetOwnPropertyDescriptor(
124+
ObjectGetPrototypeOf(Uint8Array.prototype),'length').get);
122125

123126
lethexSlice;
124127

@@ -564,18 +567,18 @@ function addPrototypeProperties(ctx, main, obj, recurseTimes, isProto, output){
564567
}while(++depth!==3);
565568
}
566569

567-
functiongetPrefix(constructor,tag,fallback){
570+
functiongetPrefix(constructor,tag,fallback,size=''){
568571
if(constructor===null){
569572
if(tag!==''){
570-
return`[${fallback}: null prototype] [${tag}] `;
573+
return`[${fallback}${size}: null prototype] [${tag}] `;
571574
}
572-
return`[${fallback}: null prototype] `;
575+
return`[${fallback}${size}: null prototype] `;
573576
}
574577

575578
if(tag!==''&&constructor!==tag){
576-
return`${constructor} [${tag}] `;
579+
return`${constructor}${size} [${tag}] `;
577580
}
578-
return`${constructor} `;
581+
return`${constructor}${size} `;
579582
}
580583

581584
// Look up the keys of the object.
@@ -760,58 +763,48 @@ function formatRaw(ctx, value, recurseTimes, typedArray){
760763
if(value[SymbolIterator]||constructor===null){
761764
noIterator=false;
762765
if(ArrayIsArray(value)){
763-
keys=getOwnNonIndexProperties(value,filter);
764766
// Only set the constructor for non ordinary ("Array [...]") arrays.
765-
constprefix=getPrefix(constructor,tag,'Array');
766-
braces=[`${prefix==='Array ' ? '' : prefix}[`,']'];
767+
constprefix=(constructor!=='Array'||tag!=='') ?
768+
getPrefix(constructor,tag,'Array',`(${value.length})`) :
769+
'';
770+
keys=getOwnNonIndexProperties(value,filter);
771+
braces=[`${prefix}[`,']'];
767772
if(value.length===0&&keys.length===0&&protoProps===undefined)
768773
return`${braces[0]}]`;
769774
extrasType=kArrayExtrasType;
770775
formatter=formatArray;
771776
}elseif(isSet(value)){
772777
constsize=setSizeGetter(value);
778+
constprefix=getPrefix(constructor,tag,'Set');
773779
keys=getKeys(value,ctx.showHidden);
774-
letprefix='';
775-
if(constructor!==null){
776-
if(constructor===tag)
777-
tag='';
778-
prefix=getPrefix(`${constructor}`,tag,'');
779-
formatter=formatSet.bind(null,value,size);
780-
}else{
781-
prefix=getPrefix(constructor,tag,'Set');
782-
formatter=formatSet.bind(null,SetPrototypeValues(value),size);
783-
}
780+
formatter=constructor!==null ?
781+
formatSet.bind(null,value,size) :
782+
formatSet.bind(null,SetPrototypeValues(value),size);
784783
if(size===0&&keys.length===0&&protoProps===undefined)
785784
return`${prefix}{}`;
786785
braces=[`${prefix}{`,'}'];
787786
}elseif(isMap(value)){
788787
constsize=mapSizeGetter(value);
788+
constprefix=getPrefix(constructor,tag,'Map');
789789
keys=getKeys(value,ctx.showHidden);
790-
letprefix='';
791-
if(constructor!==null){
792-
if(constructor===tag)
793-
tag='';
794-
prefix=getPrefix(`${constructor}`,tag,'');
795-
formatter=formatMap.bind(null,value,size);
796-
}else{
797-
prefix=getPrefix(constructor,tag,'Map');
798-
formatter=formatMap.bind(null,MapPrototypeEntries(value),size);
799-
}
790+
formatter=constructor!==null ?
791+
formatMap.bind(null,value,size) :
792+
formatMap.bind(null,MapPrototypeEntries(value),size);
800793
if(size===0&&keys.length===0&&protoProps===undefined)
801794
return`${prefix}{}`;
802795
braces=[`${prefix}{`,'}'];
803796
}elseif(isTypedArray(value)){
804797
keys=getOwnNonIndexProperties(value,filter);
805798
letbound=value;
806-
letprefix='';
799+
letfallback='';
807800
if(constructor===null){
808801
constconstr=findTypedConstructor(value);
809-
prefix=getPrefix(constructor,tag,constr.name);
802+
fallback=constr.name;
810803
// Reconstruct the array information.
811804
bound=newconstr(value);
812-
}else{
813-
prefix=getPrefix(constructor,tag);
814805
}
806+
constsize=typedArraySizeGetter(value);
807+
constprefix=getPrefix(constructor,tag,fallback,`(${size})`);
815808
braces=[`${prefix}[`,']'];
816809
if(value.length===0&&keys.length===0&&!ctx.showHidden)
817810
return`${braces[0]}]`;

‎test/parallel/test-assert-deep.js‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ assert.throws(
5151
{
5252
code: 'ERR_ASSERTION',
5353
message: `${defaultMsgStartFull} ... Lines skipped\n\n`+
54-
'+ Uint8Array [\n'+
55-
'- Buffer [Uint8Array] [\n 120,\n...\n 122,\n 10\n ]'
54+
'+ Uint8Array(4) [\n'+
55+
'- Buffer(4) [Uint8Array] [\n 120,\n...\n 122,\n 10\n ]'
5656
}
5757
);
5858
assert.deepEqual(arr,buf);
@@ -66,7 +66,7 @@ assert.deepEqual(arr, buf);
6666
{
6767
code: 'ERR_ASSERTION',
6868
message: `${defaultMsgStartFull}\n\n`+
69-
' Buffer [Uint8Array] [\n'+
69+
' Buffer(4) [Uint8Array] [\n'+
7070
' 120,\n'+
7171
' 121,\n'+
7272
' 122,\n'+
@@ -86,7 +86,7 @@ assert.deepEqual(arr, buf);
8686
{
8787
code: 'ERR_ASSERTION',
8888
message: `${defaultMsgStartFull}\n\n`+
89-
' Uint8Array [\n'+
89+
' Uint8Array(4) [\n'+
9090
' 120,\n'+
9191
' 121,\n'+
9292
' 122,\n'+

‎test/parallel/test-buffer-inspect.js‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ b.inspect = undefined;
5858
b.prop=newUint8Array(0);
5959
assert.strictEqual(
6060
util.inspect(b),
61-
'<Buffer 31 32, inspect: undefined, prop: Uint8Array []>'
61+
'<Buffer 31 32, inspect: undefined, prop: Uint8Array(0) []>'
6262
);
6363

6464
b=Buffer.alloc(0);

‎test/parallel/test-fs-read-empty-buffer.js‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ assert.throws(
1515
{
1616
code: 'ERR_INVALID_ARG_VALUE',
1717
message: 'The argument \'buffer\' is empty and cannot be written. '+
18-
'Received Uint8Array []'
18+
'Received Uint8Array(0) []'
1919
}
2020
);
2121

@@ -24,7 +24,7 @@ assert.throws(
2424
{
2525
code: 'ERR_INVALID_ARG_VALUE',
2626
message: 'The argument \'buffer\' is empty and cannot be written. '+
27-
'Received Uint8Array []'
27+
'Received Uint8Array(0) []'
2828
}
2929
);
3030

@@ -35,7 +35,7 @@ assert.throws(
3535
{
3636
code: 'ERR_INVALID_ARG_VALUE',
3737
message: 'The argument \'buffer\' is empty and cannot be written. '+
38-
'Received Uint8Array []'
38+
'Received Uint8Array(0) []'
3939
}
4040
);
4141
})();

‎test/parallel/test-util-format.js‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ assert.strictEqual(util.format('%s', () => 5), '() => 5');
158158
classFoobarextendsArray{aaa=true;}
159159
assert.strictEqual(
160160
util.format('%s',newFoobar(5)),
161-
'Foobar [ <5 empty items>, aaa: true ]'
161+
'Foobar(5) [ <5 empty items>, aaa: true ]'
162162
);
163163

164164
// Subclassing:

‎test/parallel/test-util-inspect.js‎

Lines changed: 35 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ assert.strictEqual(util.inspect({'a':{'b':{'c': 2 } } }, false, 1),
126126
'{a:{b: [Object] } }');
127127
assert.strictEqual(util.inspect({'a': {'b': ['c']}},false,1),
128128
'{a:{b: [Array] } }');
129-
assert.strictEqual(util.inspect(newUint8Array(0)),'Uint8Array []');
129+
assert.strictEqual(util.inspect(newUint8Array(0)),'Uint8Array(0) []');
130130
assert(inspect(newUint8Array(0),{showHidden: true}).includes('[buffer]'));
131131
assert.strictEqual(
132132
util.inspect(
@@ -263,7 +263,7 @@ assert(!/Object/.test(
263263
array[1]=97;
264264
assert.strictEqual(
265265
util.inspect(array,{showHidden: true}),
266-
`${constructor.name} [\n`+
266+
`${constructor.name}(${length}) [\n`+
267267
' 65,\n'+
268268
' 97,\n'+
269269
` [BYTES_PER_ELEMENT]: ${constructor.BYTES_PER_ELEMENT},\n`+
@@ -273,7 +273,7 @@ assert(!/Object/.test(
273273
` [buffer]: ArrayBuffer{byteLength: ${byteLength} }\n]`);
274274
assert.strictEqual(
275275
util.inspect(array,false),
276-
`${constructor.name} [ 65, 97 ]`
276+
`${constructor.name}(${length}) [ 65, 97 ]`
277277
);
278278
});
279279

@@ -297,7 +297,7 @@ assert(!/Object/.test(
297297
array[1]=97;
298298
assert.strictEqual(
299299
util.inspect(array,true),
300-
`${constructor.name} [\n`+
300+
`${constructor.name}(${length}) [\n`+
301301
' 65,\n'+
302302
' 97,\n'+
303303
` [BYTES_PER_ELEMENT]: ${constructor.BYTES_PER_ELEMENT},\n`+
@@ -307,7 +307,7 @@ assert(!/Object/.test(
307307
` [buffer]: ArrayBuffer{byteLength: ${byteLength} }\n]`);
308308
assert.strictEqual(
309309
util.inspect(array,false),
310-
`${constructor.name} [ 65, 97 ]`
310+
`${constructor.name}(${length}) [ 65, 97 ]`
311311
);
312312
});
313313

@@ -397,11 +397,11 @@ assert.strictEqual(
397397
arr[49]='I win';
398398
assert.strictEqual(
399399
util.inspect(arr),
400-
"CustomArray [ <49 empty items>, 'I win' ]"
400+
"CustomArray(50) [ <49 empty items>, 'I win' ]"
401401
);
402402
assert.strictEqual(
403403
util.inspect(arr,{showHidden: true}),
404-
'CustomArray [\n'+
404+
'CustomArray(50) [\n'+
405405
' <49 empty items>,\n'+
406406
" 'I win',\n"+
407407
' [length]: 50,\n'+
@@ -1291,7 +1291,7 @@ if (typeof Symbol !== 'undefined'){
12911291
assert.strictEqual(util.inspect(x),
12921292
'ObjectSubclass{foo: 42 }');
12931293
assert.strictEqual(util.inspect(newArraySubclass(1,2,3)),
1294-
'ArraySubclass [ 1, 2, 3 ]');
1294+
'ArraySubclass(3) [ 1, 2, 3 ]');
12951295
assert.strictEqual(util.inspect(newSetSubclass([1,2,3])),
12961296
'SetSubclass [Set]{1, 2, 3 }');
12971297
assert.strictEqual(util.inspect(newMapSubclass([['foo',42]])),
@@ -1387,7 +1387,7 @@ if (typeof Symbol !== 'undefined'){
13871387
assert(util.inspect(x).endsWith('1 more item\n]'));
13881388
assert(!util.inspect(x,{maxArrayLength: 101}).includes('1 more item'));
13891389
assert.strictEqual(util.inspect(x,{maxArrayLength: 0}),
1390-
'Uint8Array [ ... 101 more items ]');
1390+
'Uint8Array(101) [ ... 101 more items ]');
13911391
assert(!util.inspect(x,{maxArrayLength: null}).includes('1 more item'));
13921392
assert(util.inspect(x,{maxArrayLength: Infinity}).endsWith(' 0, 0\n]'));
13931393
}
@@ -1672,7 +1672,7 @@ util.inspect(process);
16721672
' ],',
16731673
' [length]: 1',
16741674
' ]',
1675-
' } => Uint8Array [',
1675+
' } => Uint8Array(0) [',
16761676
' [BYTES_PER_ELEMENT]: 1,',
16771677
' [length]: 0,',
16781678
' [byteLength]: 0,',
@@ -1689,7 +1689,7 @@ util.inspect(process);
16891689
' [length]: 2',
16901690
' ]',
16911691
'} => [Map Iterator]{',
1692-
' Uint8Array [',
1692+
' Uint8Array(0) [',
16931693
' [BYTES_PER_ELEMENT]: 1,',
16941694
' [length]: 0,',
16951695
' [byteLength]: 0,',
@@ -1720,15 +1720,15 @@ util.inspect(process);
17201720
' ],',
17211721
' [length]: 1',
17221722
' ]',
1723-
' } => Uint8Array [',
1723+
' } => Uint8Array(0) [',
17241724
' [BYTES_PER_ELEMENT]: 1,',
17251725
' [length]: 0,',
17261726
' [byteLength]: 0,',
17271727
' [byteOffset]: 0,',
17281728
' [buffer]: ArrayBuffer{byteLength: 0, foo: true }',
17291729
' ],',
17301730
' [Set Iterator]{[ 1, 2, [length]: 2 ] } => [Map Iterator]{',
1731-
' Uint8Array [',
1731+
' Uint8Array(0) [',
17321732
' [BYTES_PER_ELEMENT]: 1,',
17331733
' [length]: 0,',
17341734
' [byteLength]: 0,',
@@ -1756,7 +1756,7 @@ util.inspect(process);
17561756
' [length]: 2 ],',
17571757
' [size]: 1 },',
17581758
' [length]: 2 ],',
1759-
' [length]: 1 ] } => Uint8Array [',
1759+
' [length]: 1 ] } => Uint8Array(0) [',
17601760
' [BYTES_PER_ELEMENT]: 1,',
17611761
' [length]: 0,',
17621762
' [byteLength]: 0,',
@@ -1768,7 +1768,7 @@ util.inspect(process);
17681768
' [ 1,',
17691769
' 2,',
17701770
' [length]: 2 ] } => [Map Iterator]{',
1771-
' Uint8Array [',
1771+
' Uint8Array(0) [',
17721772
' [BYTES_PER_ELEMENT]: 1,',
17731773
' [length]: 0,',
17741774
' [byteLength]: 0,',
@@ -1946,7 +1946,7 @@ assert.strictEqual(util.inspect('"\'${a}'), "'\"\\'${a}'");
19461946
[newSet([1,2]).entries(),'[Set Entries]{[ 1, 1 ], [ 2, 2 ] }'],
19471947
[newMap([[1,2]]).keys(),'[Map Iterator]{1 }'],
19481948
[newDate(2000),'1970-01-01T00:00:02.000Z'],
1949-
[newUint8Array(2),'Uint8Array [ 0, 0 ]'],
1949+
[newUint8Array(2),'Uint8Array(2) [ 0, 0 ]'],
19501950
[newPromise((resolve)=>setTimeout(resolve,10)),'Promise{<pending>}'],
19511951
[newWeakSet(),'WeakSet{<items unknown>}'],
19521952
[newWeakMap(),'WeakMap{<items unknown>}'],
@@ -1972,23 +1972,23 @@ assert.strictEqual(util.inspect('"\'${a}'), "'\"\\'${a}'");
19721972

19731973
// Verify that having no prototype still produces nice results.
19741974
[
1975-
[[1,3,4],'[Array: null prototype] [ 1, 3, 4 ]'],
1975+
[[1,3,4],'[Array(3): null prototype] [ 1, 3, 4 ]'],
19761976
[newSet([1,2]),'[Set: null prototype]{1, 2 }'],
19771977
[newMap([[1,2]]),'[Map: null prototype]{1 => 2 }'],
19781978
[newPromise((resolve)=>setTimeout(resolve,10)),
19791979
'[Promise: null prototype]{<pending>}'],
19801980
[newWeakSet(),'[WeakSet: null prototype]{<items unknown>}'],
19811981
[newWeakMap(),'[WeakMap: null prototype]{<items unknown>}'],
1982-
[newUint8Array(2),'[Uint8Array: null prototype] [ 0, 0 ]'],
1983-
[newUint16Array(2),'[Uint16Array: null prototype] [ 0, 0 ]'],
1984-
[newUint32Array(2),'[Uint32Array: null prototype] [ 0, 0 ]'],
1985-
[newInt8Array(2),'[Int8Array: null prototype] [ 0, 0 ]'],
1986-
[newInt16Array(2),'[Int16Array: null prototype] [ 0, 0 ]'],
1987-
[newInt32Array(2),'[Int32Array: null prototype] [ 0, 0 ]'],
1988-
[newFloat32Array(2),'[Float32Array: null prototype] [ 0, 0 ]'],
1989-
[newFloat64Array(2),'[Float64Array: null prototype] [ 0, 0 ]'],
1990-
[newBigInt64Array(2),'[BigInt64Array: null prototype] [ 0n, 0n ]'],
1991-
[newBigUint64Array(2),'[BigUint64Array: null prototype] [ 0n, 0n ]'],
1982+
[newUint8Array(2),'[Uint8Array(2): null prototype] [ 0, 0 ]'],
1983+
[newUint16Array(2),'[Uint16Array(2): null prototype] [ 0, 0 ]'],
1984+
[newUint32Array(2),'[Uint32Array(2): null prototype] [ 0, 0 ]'],
1985+
[newInt8Array(2),'[Int8Array(2): null prototype] [ 0, 0 ]'],
1986+
[newInt16Array(2),'[Int16Array(2): null prototype] [ 0, 0 ]'],
1987+
[newInt32Array(2),'[Int32Array(2): null prototype] [ 0, 0 ]'],
1988+
[newFloat32Array(2),'[Float32Array(2): null prototype] [ 0, 0 ]'],
1989+
[newFloat64Array(2),'[Float64Array(2): null prototype] [ 0, 0 ]'],
1990+
[newBigInt64Array(2),'[BigInt64Array(2): null prototype] [ 0n, 0n ]'],
1991+
[newBigUint64Array(2),'[BigUint64Array(2): null prototype] [ 0n, 0n ]'],
19921992
[newArrayBuffer(16),'[ArrayBuffer: null prototype]{\n'+
19931993
' [Uint8Contents]: <00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00>,\n'+
19941994
' byteLength: undefined\n}'],
@@ -2026,8 +2026,10 @@ assert.strictEqual(util.inspect('"\'${a}'), "'\"\\'${a}'");
20262026
classFooextendsbase{}
20272027
constvalue=newFoo(...input);
20282028
constsymbol=value[Symbol.toStringTag];
2029-
constexpected=`Foo ${symbol ? `[${symbol}] ` : ''}${rawExpected}`;
2030-
constexpectedWithoutProto=`[${base.name}: null prototype] ${rawExpected}`;
2029+
constsize=base.name.includes('Array') ? `(${input[0]})` : '';
2030+
constexpected=`Foo${size}${symbol ? `[${symbol}] ` : ''}${rawExpected}`;
2031+
constexpectedWithoutProto=
2032+
`[${base.name}${size}: null prototype] ${rawExpected}`;
20312033
assert.strictEqual(util.inspect(value),expected);
20322034
value.foo='bar';
20332035
assert.notStrictEqual(util.inspect(value),expected);
@@ -2050,8 +2052,9 @@ assert.strictEqual(util.inspect('"\'${a}'), "'\"\\'${a}'");
20502052
assert.strictEqual(inspect(1n),'1n');
20512053
assert.strictEqual(inspect(Object(-1n)),'[BigInt: -1n]');
20522054
assert.strictEqual(inspect(Object(13n)),'[BigInt: 13n]');
2053-
assert.strictEqual(inspect(newBigInt64Array([0n])),'BigInt64Array [ 0n ]');
2054-
assert.strictEqual(inspect(newBigUint64Array([0n])),'BigUint64Array [ 0n ]');
2055+
assert.strictEqual(inspect(newBigInt64Array([0n])),'BigInt64Array(1) [ 0n ]');
2056+
assert.strictEqual(
2057+
inspect(newBigUint64Array([0n])),'BigUint64Array(1) [ 0n ]');
20552058

20562059
// Verify non-enumerable keys get escaped.
20572060
{
@@ -2170,7 +2173,7 @@ assert.strictEqual(
21702173
Object.setPrototypeOf(obj,value);
21712174
assert.strictEqual(
21722175
util.inspect(obj),
2173-
'Object <[Array: null prototype] []>{a: true }'
2176+
'Object <[Array(0): null prototype] []>{a: true }'
21742177
);
21752178

21762179
functionStorageObject(){}

0 commit comments

Comments
(0)