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: https://github.com/nodejs/node/pull/22291 Reviewed-By: Gus Caplan <me@gus.host> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
parent
59c8abf886
commit
1abc613b32
37
lib/util.js
37
lib/util.js
@ -543,6 +543,9 @@ function findTypedConstructor(value) {
|
||||
|
||||
const getBoxedValue = formatPrimitive.bind(null, stylizeNoColor);
|
||||
|
||||
// Note: using `formatValue` directly requires the indentation level to be
|
||||
// corrected by setting `ctx.indentationLvL += diff` and then to decrease the
|
||||
// value afterwards again.
|
||||
function formatValue(ctx, value, recurseTimes) {
|
||||
// Primitive types cannot have properties
|
||||
if (typeof value !== 'object' && typeof value !== 'function') {
|
||||
@ -1063,17 +1066,18 @@ function formatTypedArray(ctx, value, recurseTimes, keys) {
|
||||
output[i] = `... ${remaining} more item${remaining > 1 ? 's' : ''}`;
|
||||
if (ctx.showHidden) {
|
||||
// .buffer goes last, it's not a primitive like the others.
|
||||
const extraKeys = [
|
||||
ctx.indentationLvl += 2;
|
||||
for (const key of [
|
||||
'BYTES_PER_ELEMENT',
|
||||
'length',
|
||||
'byteLength',
|
||||
'byteOffset',
|
||||
'buffer'
|
||||
];
|
||||
for (i = 0; i < extraKeys.length; i++) {
|
||||
const str = formatValue(ctx, value[extraKeys[i]], recurseTimes);
|
||||
output.push(`[${extraKeys[i]}]: ${str}`);
|
||||
]) {
|
||||
const str = formatValue(ctx, value[key], recurseTimes);
|
||||
output.push(`[${key}]: ${str}`);
|
||||
}
|
||||
ctx.indentationLvl -= 2;
|
||||
}
|
||||
// TypedArrays cannot have holes. Therefore it is safe to assume that all
|
||||
// extra keys are indexed after value.length.
|
||||
@ -1086,8 +1090,11 @@ function formatTypedArray(ctx, value, recurseTimes, keys) {
|
||||
function formatSet(ctx, value, recurseTimes, keys) {
|
||||
const output = new Array(value.size + keys.length + (ctx.showHidden ? 1 : 0));
|
||||
let i = 0;
|
||||
for (const v of value)
|
||||
ctx.indentationLvl += 2;
|
||||
for (const v of value) {
|
||||
output[i++] = formatValue(ctx, v, recurseTimes);
|
||||
}
|
||||
ctx.indentationLvl -= 2;
|
||||
// With `showHidden`, `length` will display as a hidden property for
|
||||
// arrays. For consistency's sake, do the same for `size`, even though this
|
||||
// property isn't selected by Object.getOwnPropertyNames().
|
||||
@ -1102,9 +1109,12 @@ function formatSet(ctx, value, recurseTimes, keys) {
|
||||
function formatMap(ctx, value, recurseTimes, keys) {
|
||||
const output = new Array(value.size + keys.length + (ctx.showHidden ? 1 : 0));
|
||||
let i = 0;
|
||||
for (const [k, v] of value)
|
||||
ctx.indentationLvl += 2;
|
||||
for (const [k, v] of value) {
|
||||
output[i++] = `${formatValue(ctx, k, recurseTimes)} => ` +
|
||||
formatValue(ctx, v, recurseTimes);
|
||||
formatValue(ctx, v, recurseTimes);
|
||||
}
|
||||
ctx.indentationLvl -= 2;
|
||||
// See comment in formatSet
|
||||
if (ctx.showHidden)
|
||||
output[i++] = `[size]: ${ctx.stylize(`${value.size}`, 'number')}`;
|
||||
@ -1118,8 +1128,11 @@ function formatSetIterInner(ctx, value, recurseTimes, keys, entries, state) {
|
||||
const maxArrayLength = Math.max(ctx.maxArrayLength, 0);
|
||||
const maxLength = Math.min(maxArrayLength, entries.length);
|
||||
let output = new Array(maxLength);
|
||||
for (var i = 0; i < maxLength; ++i)
|
||||
ctx.indentationLvl += 2;
|
||||
for (var i = 0; i < maxLength; i++) {
|
||||
output[i] = formatValue(ctx, entries[i], recurseTimes);
|
||||
}
|
||||
ctx.indentationLvl -= 2;
|
||||
if (state === kWeak) {
|
||||
// Sort all entries to have a halfway reliable output (if more entries than
|
||||
// retrieved ones exist, we can not reliably return the same output).
|
||||
@ -1150,11 +1163,13 @@ function formatMapIterInner(ctx, value, recurseTimes, keys, entries, state) {
|
||||
end = ' ]';
|
||||
middle = ', ';
|
||||
}
|
||||
ctx.indentationLvl += 2;
|
||||
for (; i < maxLength; i++) {
|
||||
const pos = i * 2;
|
||||
output[i] = `${start}${formatValue(ctx, entries[pos], recurseTimes)}` +
|
||||
`${middle}${formatValue(ctx, entries[pos + 1], recurseTimes)}${end}`;
|
||||
}
|
||||
ctx.indentationLvl -= 2;
|
||||
if (state === kWeak) {
|
||||
// Sort all entries to have a halfway reliable output (if more entries
|
||||
// than retrieved ones exist, we can not reliably return the same output).
|
||||
@ -1199,7 +1214,11 @@ function formatPromise(ctx, value, recurseTimes, keys) {
|
||||
if (state === kPending) {
|
||||
output = ['<pending>'];
|
||||
} else {
|
||||
// Using `formatValue` is correct here without the need to fix the
|
||||
// indentation level.
|
||||
ctx.indentationLvl += 2;
|
||||
const str = formatValue(ctx, result, recurseTimes);
|
||||
ctx.indentationLvl -= 2;
|
||||
output = [state === kRejected ? `<rejected> ${str}` : str];
|
||||
}
|
||||
for (var n = 0; n < keys.length; n++) {
|
||||
|
@ -179,7 +179,6 @@ for (const showHidden of [true, false]) {
|
||||
' y: 1337 }');
|
||||
}
|
||||
|
||||
|
||||
[ Float32Array,
|
||||
Float64Array,
|
||||
Int16Array,
|
||||
@ -195,7 +194,7 @@ for (const showHidden of [true, false]) {
|
||||
array[0] = 65;
|
||||
array[1] = 97;
|
||||
assert.strictEqual(
|
||||
util.inspect(array, true),
|
||||
util.inspect(array, { showHidden: true }),
|
||||
`${constructor.name} [\n` +
|
||||
' 65,\n' +
|
||||
' 97,\n' +
|
||||
@ -1362,6 +1361,107 @@ util.inspect(process);
|
||||
assert.strictEqual(out, expect);
|
||||
}
|
||||
|
||||
// Check compact indentation.
|
||||
{
|
||||
const typed = new Uint8Array();
|
||||
typed.buffer.foo = true;
|
||||
const set = new Set([[1, 2]]);
|
||||
const promise = Promise.resolve([[1, set]]);
|
||||
const map = new Map([[promise, typed]]);
|
||||
map.set(set.values(), map.values());
|
||||
|
||||
let out = util.inspect(map, { compact: false, showHidden: true, depth: 9 });
|
||||
let expected = [
|
||||
'Map {',
|
||||
' Promise {',
|
||||
' [',
|
||||
' [',
|
||||
' 1,',
|
||||
' Set {',
|
||||
' [',
|
||||
' 1,',
|
||||
' 2,',
|
||||
' [length]: 2',
|
||||
' ],',
|
||||
' [size]: 1',
|
||||
' },',
|
||||
' [length]: 2',
|
||||
' ],',
|
||||
' [length]: 1',
|
||||
' ]',
|
||||
' } => Uint8Array [',
|
||||
' [BYTES_PER_ELEMENT]: 1,',
|
||||
' [length]: 0,',
|
||||
' [byteLength]: 0,',
|
||||
' [byteOffset]: 0,',
|
||||
' [buffer]: ArrayBuffer {',
|
||||
' byteLength: 0,',
|
||||
' foo: true',
|
||||
' }',
|
||||
' ],',
|
||||
' [Set Iterator] {',
|
||||
' [',
|
||||
' 1,',
|
||||
' 2,',
|
||||
' [length]: 2',
|
||||
' ]',
|
||||
' } => [Map Iterator] {',
|
||||
' Uint8Array [',
|
||||
' [BYTES_PER_ELEMENT]: 1,',
|
||||
' [length]: 0,',
|
||||
' [byteLength]: 0,',
|
||||
' [byteOffset]: 0,',
|
||||
' [buffer]: ArrayBuffer {',
|
||||
' byteLength: 0,',
|
||||
' foo: true',
|
||||
' }',
|
||||
' ],',
|
||||
' [Circular]',
|
||||
' },',
|
||||
' [size]: 2',
|
||||
'}'
|
||||
].join('\n');
|
||||
|
||||
assert.strict.equal(out, expected);
|
||||
|
||||
out = util.inspect(map, { showHidden: true, depth: 9, breakLength: 4 });
|
||||
expected = [
|
||||
'Map {',
|
||||
' Promise {',
|
||||
' [ [ 1,',
|
||||
' Set {',
|
||||
' [ 1,',
|
||||
' 2,',
|
||||
' [length]: 2 ],',
|
||||
' [size]: 1 },',
|
||||
' [length]: 2 ],',
|
||||
' [length]: 1 ] } => Uint8Array [',
|
||||
' [BYTES_PER_ELEMENT]: 1,',
|
||||
' [length]: 0,',
|
||||
' [byteLength]: 0,',
|
||||
' [byteOffset]: 0,',
|
||||
' [buffer]: ArrayBuffer {',
|
||||
' byteLength: 0,',
|
||||
' foo: true } ],',
|
||||
' [Set Iterator] {',
|
||||
' [ 1,',
|
||||
' 2,',
|
||||
' [length]: 2 ] } => [Map Iterator] {',
|
||||
' Uint8Array [',
|
||||
' [BYTES_PER_ELEMENT]: 1,',
|
||||
' [length]: 0,',
|
||||
' [byteLength]: 0,',
|
||||
' [byteOffset]: 0,',
|
||||
' [buffer]: ArrayBuffer {',
|
||||
' byteLength: 0,',
|
||||
' foo: true } ],',
|
||||
' [Circular] },',
|
||||
' [size]: 2 }'
|
||||
].join('\n');
|
||||
|
||||
assert.strict.equal(out, expected);
|
||||
}
|
||||
|
||||
{ // Test WeakMap
|
||||
const obj = {};
|
||||
const arr = [];
|
||||
|
Loading…
x
Reference in New Issue
Block a user