Skip to content

Commit

Permalink
util: change sparse arrays inspection format
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
aqrln authored and addaleax committed Mar 10, 2017
1 parent 6df23fa commit ec2f098
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 13 deletions.
24 changes: 17 additions & 7 deletions lib/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -626,16 +626,26 @@ function formatObject(ctx, value, recurseTimes, visibleKeys, keys) {

function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
var output = [];
const maxLength = Math.min(Math.max(0, ctx.maxArrayLength), value.length);
const remaining = value.length - maxLength;
for (var i = 0; i < maxLength; ++i) {
if (hasOwnProperty(value, String(i))) {
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
String(i), true));
let visibleLength = 0;
let index = 0;
while (index < value.length && visibleLength < ctx.maxArrayLength) {
let emptyItems = 0;
while (index < value.length && !hasOwnProperty(value, String(index))) {
emptyItems++;
index++;
}
if (emptyItems > 0) {
const ending = emptyItems > 1 ? 's' : '';
const message = `<${emptyItems} empty item${ending}>`;
output.push(ctx.stylize(message, 'undefined'));
} else {
output.push('');
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
String(index), true));
index++;
}
visibleLength++;
}
const remaining = value.length - index;
if (remaining > 0) {
output.push(`... ${remaining} more item${remaining > 1 ? 's' : ''}`);
}
Expand Down
24 changes: 18 additions & 6 deletions test/parallel/test-util-inspect.js
Original file line number Diff line number Diff line change
Expand Up @@ -295,12 +295,18 @@ assert.strictEqual(util.inspect(-0), '-0');
const a = ['foo', 'bar', 'baz'];
assert.strictEqual(util.inspect(a), '[ \'foo\', \'bar\', \'baz\' ]');
delete a[1];
assert.strictEqual(util.inspect(a), '[ \'foo\', , \'baz\' ]');
assert.strictEqual(util.inspect(a), '[ \'foo\', <1 empty item>, \'baz\' ]');
assert.strictEqual(
util.inspect(a, true),
'[ \'foo\', , \'baz\', [length]: 3 ]'
'[ \'foo\', <1 empty item>, \'baz\', [length]: 3 ]'
);
assert.strictEqual(util.inspect(new Array(5)), '[ <5 empty items> ]');
a[3] = 'bar';
a[100] = 'qux';
assert.strictEqual(
util.inspect(a, { breakLength: Infinity }),
'[ \'foo\', <1 empty item>, \'baz\', \'bar\', <96 empty items>, \'qux\' ]'
);
assert.strictEqual(util.inspect(new Array(5)), '[ , , , , ]');

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

{
const x = Array(101);
const x = new Array(101).fill();
assert(!/1 more item/.test(util.inspect(x, {maxArrayLength: 101})));
}

{
const x = new Array(101).fill();
assert(/^\[ ... 101 more items ]$/.test(
util.inspect(x, {maxArrayLength: 0})));
}

{
const x = Array(101);
assert(/^\[ ... 101 more items ]$/.test(
Expand Down Expand Up @@ -901,7 +913,7 @@ checkAlignment(new Map(big_array.map(function(y) { return [y, null]; })));

// util.inspect.defaultOptions tests
{
const arr = Array(101);
const arr = new Array(101).fill();
const obj = {a: {a: {a: {a: 1}}}};

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

0 comments on commit ec2f098

Please sign in to comment.