Skip to content

Commit ec2f098

Browse files
aqrlnaddaleax
authored andcommitted
util: change sparse arrays inspection format
Missing elements in sparse arrays used to be serialized to empty placeholders delimited with commas by util.inspect() and in some cases the result was a syntactically correct representation of a JavaScript array with shorter length than the original one. This commit implements @TimothyGu's suggestion to change the way util.inspect() formats sparse arrays to something similar to how Firefox shows them. Fixes: #11570 PR-URL: #11576 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Evan Lucas <[email protected]> Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Timothy Gu <[email protected]> Reviewed-By: Michaël Zasso <[email protected]> Reviewed-By: Colin Ihrig <[email protected]>
1 parent 6df23fa commit ec2f098

File tree

2 files changed

+35
-13
lines changed

2 files changed

+35
-13
lines changed

lib/util.js

+17-7
Original file line numberDiff line numberDiff line change
@@ -626,16 +626,26 @@ function formatObject(ctx, value, recurseTimes, visibleKeys, keys) {
626626

627627
function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
628628
var output = [];
629-
const maxLength = Math.min(Math.max(0, ctx.maxArrayLength), value.length);
630-
const remaining = value.length - maxLength;
631-
for (var i = 0; i < maxLength; ++i) {
632-
if (hasOwnProperty(value, String(i))) {
633-
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
634-
String(i), true));
629+
let visibleLength = 0;
630+
let index = 0;
631+
while (index < value.length && visibleLength < ctx.maxArrayLength) {
632+
let emptyItems = 0;
633+
while (index < value.length && !hasOwnProperty(value, String(index))) {
634+
emptyItems++;
635+
index++;
636+
}
637+
if (emptyItems > 0) {
638+
const ending = emptyItems > 1 ? 's' : '';
639+
const message = `<${emptyItems} empty item${ending}>`;
640+
output.push(ctx.stylize(message, 'undefined'));
635641
} else {
636-
output.push('');
642+
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
643+
String(index), true));
644+
index++;
637645
}
646+
visibleLength++;
638647
}
648+
const remaining = value.length - index;
639649
if (remaining > 0) {
640650
output.push(`... ${remaining} more item${remaining > 1 ? 's' : ''}`);
641651
}

test/parallel/test-util-inspect.js

+18-6
Original file line numberDiff line numberDiff line change
@@ -295,12 +295,18 @@ assert.strictEqual(util.inspect(-0), '-0');
295295
const a = ['foo', 'bar', 'baz'];
296296
assert.strictEqual(util.inspect(a), '[ \'foo\', \'bar\', \'baz\' ]');
297297
delete a[1];
298-
assert.strictEqual(util.inspect(a), '[ \'foo\', , \'baz\' ]');
298+
assert.strictEqual(util.inspect(a), '[ \'foo\', <1 empty item>, \'baz\' ]');
299299
assert.strictEqual(
300300
util.inspect(a, true),
301-
'[ \'foo\', , \'baz\', [length]: 3 ]'
301+
'[ \'foo\', <1 empty item>, \'baz\', [length]: 3 ]'
302+
);
303+
assert.strictEqual(util.inspect(new Array(5)), '[ <5 empty items> ]');
304+
a[3] = 'bar';
305+
a[100] = 'qux';
306+
assert.strictEqual(
307+
util.inspect(a, { breakLength: Infinity }),
308+
'[ \'foo\', <1 empty item>, \'baz\', \'bar\', <96 empty items>, \'qux\' ]'
302309
);
303-
assert.strictEqual(util.inspect(new Array(5)), '[ , , , , ]');
304310

305311
// test for Array constructor in different context
306312
{
@@ -835,15 +841,21 @@ checkAlignment(new Map(big_array.map(function(y) { return [y, null]; })));
835841
// Do not backport to v5/v4 unless all of
836842
// https://github.com/nodejs/node/pull/6334 is backported.
837843
{
838-
const x = Array(101);
844+
const x = new Array(101).fill();
839845
assert(/1 more item/.test(util.inspect(x)));
840846
}
841847

842848
{
843-
const x = Array(101);
849+
const x = new Array(101).fill();
844850
assert(!/1 more item/.test(util.inspect(x, {maxArrayLength: 101})));
845851
}
846852

853+
{
854+
const x = new Array(101).fill();
855+
assert(/^\[ ... 101 more items ]$/.test(
856+
util.inspect(x, {maxArrayLength: 0})));
857+
}
858+
847859
{
848860
const x = Array(101);
849861
assert(/^\[ ... 101 more items ]$/.test(
@@ -901,7 +913,7 @@ checkAlignment(new Map(big_array.map(function(y) { return [y, null]; })));
901913

902914
// util.inspect.defaultOptions tests
903915
{
904-
const arr = Array(101);
916+
const arr = new Array(101).fill();
905917
const obj = {a: {a: {a: {a: 1}}}};
906918

907919
const oldOptions = Object.assign({}, util.inspect.defaultOptions);

0 commit comments

Comments
 (0)