Skip to content

Commit e9ac683

Browse files
BridgeARtargos
authored andcommitted
util: properly indent special properties
Calling `formatValue()` directly requires the indentation level to be set manually. This was not the case so far in most cases and the indentation was off in all these cases. PR-URL: #22291 Reviewed-By: Gus Caplan <[email protected]> Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent 459d676 commit e9ac683

File tree

2 files changed

+130
-11
lines changed

2 files changed

+130
-11
lines changed

lib/util.js

+28-9
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,9 @@ function findTypedConstructor(value) {
492492

493493
const getBoxedValue = formatPrimitive.bind(null, stylizeNoColor);
494494

495+
// Note: using `formatValue` directly requires the indentation level to be
496+
// corrected by setting `ctx.indentationLvL += diff` and then to decrease the
497+
// value afterwards again.
495498
function formatValue(ctx, value, recurseTimes) {
496499
// Primitive types cannot have properties
497500
if (typeof value !== 'object' && typeof value !== 'function') {
@@ -1011,17 +1014,18 @@ function formatTypedArray(ctx, value, recurseTimes, keys) {
10111014
output[i] = `... ${remaining} more item${remaining > 1 ? 's' : ''}`;
10121015
if (ctx.showHidden) {
10131016
// .buffer goes last, it's not a primitive like the others.
1014-
const extraKeys = [
1017+
ctx.indentationLvl += 2;
1018+
for (const key of [
10151019
'BYTES_PER_ELEMENT',
10161020
'length',
10171021
'byteLength',
10181022
'byteOffset',
10191023
'buffer'
1020-
];
1021-
for (i = 0; i < extraKeys.length; i++) {
1022-
const str = formatValue(ctx, value[extraKeys[i]], recurseTimes);
1023-
output.push(`[${extraKeys[i]}]: ${str}`);
1024+
]) {
1025+
const str = formatValue(ctx, value[key], recurseTimes);
1026+
output.push(`[${key}]: ${str}`);
10241027
}
1028+
ctx.indentationLvl -= 2;
10251029
}
10261030
// TypedArrays cannot have holes. Therefore it is safe to assume that all
10271031
// extra keys are indexed after value.length.
@@ -1034,8 +1038,11 @@ function formatTypedArray(ctx, value, recurseTimes, keys) {
10341038
function formatSet(ctx, value, recurseTimes, keys) {
10351039
const output = new Array(value.size + keys.length + (ctx.showHidden ? 1 : 0));
10361040
let i = 0;
1037-
for (const v of value)
1041+
ctx.indentationLvl += 2;
1042+
for (const v of value) {
10381043
output[i++] = formatValue(ctx, v, recurseTimes);
1044+
}
1045+
ctx.indentationLvl -= 2;
10391046
// With `showHidden`, `length` will display as a hidden property for
10401047
// arrays. For consistency's sake, do the same for `size`, even though this
10411048
// property isn't selected by Object.getOwnPropertyNames().
@@ -1050,9 +1057,12 @@ function formatSet(ctx, value, recurseTimes, keys) {
10501057
function formatMap(ctx, value, recurseTimes, keys) {
10511058
const output = new Array(value.size + keys.length + (ctx.showHidden ? 1 : 0));
10521059
let i = 0;
1053-
for (const [k, v] of value)
1060+
ctx.indentationLvl += 2;
1061+
for (const [k, v] of value) {
10541062
output[i++] = `${formatValue(ctx, k, recurseTimes)} => ` +
1055-
formatValue(ctx, v, recurseTimes);
1063+
formatValue(ctx, v, recurseTimes);
1064+
}
1065+
ctx.indentationLvl -= 2;
10561066
// See comment in formatSet
10571067
if (ctx.showHidden)
10581068
output[i++] = `[size]: ${ctx.stylize(`${value.size}`, 'number')}`;
@@ -1066,8 +1076,11 @@ function formatSetIterInner(ctx, value, recurseTimes, keys, entries, state) {
10661076
const maxArrayLength = Math.max(ctx.maxArrayLength, 0);
10671077
const maxLength = Math.min(maxArrayLength, entries.length);
10681078
let output = new Array(maxLength);
1069-
for (var i = 0; i < maxLength; ++i)
1079+
ctx.indentationLvl += 2;
1080+
for (var i = 0; i < maxLength; i++) {
10701081
output[i] = formatValue(ctx, entries[i], recurseTimes);
1082+
}
1083+
ctx.indentationLvl -= 2;
10711084
if (state === kWeak) {
10721085
// Sort all entries to have a halfway reliable output (if more entries than
10731086
// retrieved ones exist, we can not reliably return the same output).
@@ -1098,11 +1111,13 @@ function formatMapIterInner(ctx, value, recurseTimes, keys, entries, state) {
10981111
end = ' ]';
10991112
middle = ', ';
11001113
}
1114+
ctx.indentationLvl += 2;
11011115
for (; i < maxLength; i++) {
11021116
const pos = i * 2;
11031117
output[i] = `${start}${formatValue(ctx, entries[pos], recurseTimes)}` +
11041118
`${middle}${formatValue(ctx, entries[pos + 1], recurseTimes)}${end}`;
11051119
}
1120+
ctx.indentationLvl -= 2;
11061121
if (state === kWeak) {
11071122
// Sort all entries to have a halfway reliable output (if more entries
11081123
// than retrieved ones exist, we can not reliably return the same output).
@@ -1147,7 +1162,11 @@ function formatPromise(ctx, value, recurseTimes, keys) {
11471162
if (state === kPending) {
11481163
output = ['<pending>'];
11491164
} else {
1165+
// Using `formatValue` is correct here without the need to fix the
1166+
// indentation level.
1167+
ctx.indentationLvl += 2;
11501168
const str = formatValue(ctx, result, recurseTimes);
1169+
ctx.indentationLvl -= 2;
11511170
output = [state === kRejected ? `<rejected> ${str}` : str];
11521171
}
11531172
for (var n = 0; n < keys.length; n++) {

test/parallel/test-util-inspect.js

+102-2
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,6 @@ for (const showHidden of [true, false]) {
179179
' y: 1337 }');
180180
}
181181

182-
183182
[ Float32Array,
184183
Float64Array,
185184
Int16Array,
@@ -195,7 +194,7 @@ for (const showHidden of [true, false]) {
195194
array[0] = 65;
196195
array[1] = 97;
197196
assert.strictEqual(
198-
util.inspect(array, true),
197+
util.inspect(array, { showHidden: true }),
199198
`${constructor.name} [\n` +
200199
' 65,\n' +
201200
' 97,\n' +
@@ -1424,6 +1423,107 @@ util.inspect(process);
14241423
assert.strictEqual(out, expect);
14251424
}
14261425

1426+
// Check compact indentation.
1427+
{
1428+
const typed = new Uint8Array();
1429+
typed.buffer.foo = true;
1430+
const set = new Set([[1, 2]]);
1431+
const promise = Promise.resolve([[1, set]]);
1432+
const map = new Map([[promise, typed]]);
1433+
map.set(set.values(), map.values());
1434+
1435+
let out = util.inspect(map, { compact: false, showHidden: true, depth: 9 });
1436+
let expected = [
1437+
'Map {',
1438+
' Promise {',
1439+
' [',
1440+
' [',
1441+
' 1,',
1442+
' Set {',
1443+
' [',
1444+
' 1,',
1445+
' 2,',
1446+
' [length]: 2',
1447+
' ],',
1448+
' [size]: 1',
1449+
' },',
1450+
' [length]: 2',
1451+
' ],',
1452+
' [length]: 1',
1453+
' ]',
1454+
' } => Uint8Array [',
1455+
' [BYTES_PER_ELEMENT]: 1,',
1456+
' [length]: 0,',
1457+
' [byteLength]: 0,',
1458+
' [byteOffset]: 0,',
1459+
' [buffer]: ArrayBuffer {',
1460+
' byteLength: 0,',
1461+
' foo: true',
1462+
' }',
1463+
' ],',
1464+
' [Set Iterator] {',
1465+
' [',
1466+
' 1,',
1467+
' 2,',
1468+
' [length]: 2',
1469+
' ]',
1470+
' } => [Map Iterator] {',
1471+
' Uint8Array [',
1472+
' [BYTES_PER_ELEMENT]: 1,',
1473+
' [length]: 0,',
1474+
' [byteLength]: 0,',
1475+
' [byteOffset]: 0,',
1476+
' [buffer]: ArrayBuffer {',
1477+
' byteLength: 0,',
1478+
' foo: true',
1479+
' }',
1480+
' ],',
1481+
' [Circular]',
1482+
' },',
1483+
' [size]: 2',
1484+
'}'
1485+
].join('\n');
1486+
1487+
assert.strict.equal(out, expected);
1488+
1489+
out = util.inspect(map, { showHidden: true, depth: 9, breakLength: 4 });
1490+
expected = [
1491+
'Map {',
1492+
' Promise {',
1493+
' [ [ 1,',
1494+
' Set {',
1495+
' [ 1,',
1496+
' 2,',
1497+
' [length]: 2 ],',
1498+
' [size]: 1 },',
1499+
' [length]: 2 ],',
1500+
' [length]: 1 ] } => Uint8Array [',
1501+
' [BYTES_PER_ELEMENT]: 1,',
1502+
' [length]: 0,',
1503+
' [byteLength]: 0,',
1504+
' [byteOffset]: 0,',
1505+
' [buffer]: ArrayBuffer {',
1506+
' byteLength: 0,',
1507+
' foo: true } ],',
1508+
' [Set Iterator] {',
1509+
' [ 1,',
1510+
' 2,',
1511+
' [length]: 2 ] } => [Map Iterator] {',
1512+
' Uint8Array [',
1513+
' [BYTES_PER_ELEMENT]: 1,',
1514+
' [length]: 0,',
1515+
' [byteLength]: 0,',
1516+
' [byteOffset]: 0,',
1517+
' [buffer]: ArrayBuffer {',
1518+
' byteLength: 0,',
1519+
' foo: true } ],',
1520+
' [Circular] },',
1521+
' [size]: 2 }'
1522+
].join('\n');
1523+
1524+
assert.strict.equal(out, expected);
1525+
}
1526+
14271527
{ // Test WeakMap
14281528
const obj = {};
14291529
const arr = [];

0 commit comments

Comments
 (0)