Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 41 additions & 28 deletions lib/internal/util/inspect.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,6 @@ const {
StringPrototypeSplit,
StringPrototypeStartsWith,
StringPrototypeToLowerCase,
StringPrototypeTrim,
StringPrototypeValueOf,
SymbolIterator,
SymbolPrototypeToString,
Expand Down Expand Up @@ -1223,6 +1222,7 @@ function formatRaw(ctx, value, recurseTimes, typedArray) {
const filter = ctx.showHidden ? ALL_PROPERTIES : ONLY_ENUMERABLE;

let extrasType = kObjectType;
let extraKeys;

// Iterators and the rest are split to reduce checks.
// We have to check all values in case the constructor is set to null.
Expand Down Expand Up @@ -1278,6 +1278,11 @@ function formatRaw(ctx, value, recurseTimes, typedArray) {
// bound function is required to reconstruct missing information.
formatter = FunctionPrototypeBind(formatTypedArray, null, bound, size);
extrasType = kArrayExtrasType;

if (ctx.showHidden) {
extraKeys = ['BYTES_PER_ELEMENT', 'length', 'byteLength', 'byteOffset', 'buffer'];
typedArray = true;
}
} else if (isMapIterator(value)) {
keys = getKeys(value, ctx.showHidden);
braces = getIteratorBraces('Map', tag);
Expand Down Expand Up @@ -1347,14 +1352,14 @@ function formatRaw(ctx, value, recurseTimes, typedArray) {
formatter = formatArrayBuffer;
} else if (keys.length === 0 && protoProps === undefined) {
return prefix +
`{ byteLength: ${formatNumber(ctx.stylize, value.byteLength, false)} }`;
`{ [byteLength]: ${formatNumber(ctx.stylize, value.byteLength, false)} }`;
}
braces[0] = `${prefix}{`;
ArrayPrototypeUnshift(keys, 'byteLength');
extraKeys = ['byteLength'];
} else if (isDataView(value)) {
braces[0] = `${getPrefix(constructor, tag, 'DataView')}{`;
// .buffer goes last, it's not a primitive like the others.
ArrayPrototypeUnshift(keys, 'byteLength', 'byteOffset', 'buffer');
extraKeys = ['byteLength', 'byteOffset', 'buffer'];
} else if (isPromise(value)) {
braces[0] = `${getPrefix(constructor, tag, 'Promise')}{`;
formatter = formatPromise;
Expand Down Expand Up @@ -1404,6 +1409,18 @@ function formatRaw(ctx, value, recurseTimes, typedArray) {
const indentationLvl = ctx.indentationLvl;
try {
output = formatter(ctx, value, recurseTimes);
if (extraKeys !== undefined) {
for (i = 0; i < extraKeys.length; i++) {
let formatted;
try {
formatted = formatExtraProperties(ctx, value, recurseTimes, extraKeys[i], typedArray);
} catch {
const tempValue = { [extraKeys[i]]: value.buffer[extraKeys[i]] };
formatted = formatExtraProperties(ctx, tempValue, recurseTimes, extraKeys[i], typedArray);
}
ArrayPrototypePush(output, formatted);
}
}
for (i = 0; i < keys.length; i++) {
ArrayPrototypePush(
output,
Expand Down Expand Up @@ -2263,11 +2280,15 @@ function formatArrayBuffer(ctx, value) {
}
if (hexSlice === undefined)
hexSlice = uncurryThis(require('buffer').Buffer.prototype.hexSlice);
let str = StringPrototypeTrim(RegExpPrototypeSymbolReplace(
/(.{2})/g,
hexSlice(buffer, 0, MathMin(ctx.maxArrayLength, buffer.length)),
'$1 ',
));
const rawString = hexSlice(buffer, 0, MathMin(ctx.maxArrayLength, buffer.length));
let str = '';
let i = 0;
for (; i < rawString.length - 2; i += 2) {
str += `${rawString[i]}${rawString[i + 1]} `;
}
if (rawString.length > 0) {
str += `${rawString[i]}${rawString[i + 1]}`;
}
const remaining = buffer.length - ctx.maxArrayLength;
if (remaining > 0)
str += ` ... ${remaining} more byte${remaining > 1 ? 's' : ''}`;
Expand All @@ -2294,7 +2315,7 @@ function formatArray(ctx, value, recurseTimes) {
return output;
}

function formatTypedArray(value, length, ctx, ignored, recurseTimes) {
function formatTypedArray(value, length, ctx) {
const maxLength = MathMin(MathMax(0, ctx.maxArrayLength), length);
const remaining = value.length - maxLength;
const output = new Array(maxLength);
Expand All @@ -2307,22 +2328,6 @@ function formatTypedArray(value, length, ctx, ignored, recurseTimes) {
if (remaining > 0) {
output[maxLength] = remainingText(remaining);
}
if (ctx.showHidden) {
// .buffer goes last, it's not a primitive like the others.
// All besides `BYTES_PER_ELEMENT` are actually getters.
ctx.indentationLvl += 2;
for (const key of [
'BYTES_PER_ELEMENT',
'length',
'byteLength',
'byteOffset',
'buffer',
]) {
const str = formatValue(ctx, value[key], recurseTimes, true);
ArrayPrototypePush(output, `[${key}]: ${str}`);
}
ctx.indentationLvl -= 2;
}
return output;
}

Expand Down Expand Up @@ -2470,12 +2475,20 @@ function formatPromise(ctx, value, recurseTimes) {
return output;
}

function formatExtraProperties(ctx, value, recurseTimes, key, typedArray) {
ctx.indentationLvl += 2;
const str = formatValue(ctx, value[key], recurseTimes, typedArray);
ctx.indentationLvl -= 2;

// These entries are mainly getters. Should they be formatted like getters?
return ctx.stylize(`[${key}]: ${str}`, 'string');
}

function formatProperty(ctx, value, recurseTimes, key, type, desc,
original = value) {
let name, str;
let extra = ' ';
desc ||= ObjectGetOwnPropertyDescriptor(value, key) ||
{ value: value[key], enumerable: true };
desc ??= ObjectGetOwnPropertyDescriptor(value, key);
if (desc.value !== undefined) {
const diff = (ctx.compact !== true || type !== kObjectType) ? 2 : 3;
ctx.indentationLvl += diff;
Expand Down
2 changes: 1 addition & 1 deletion test/parallel/test-util-format.js
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,7 @@ assert.strictEqual(

assert.strictEqual(
util.format(new SharedArrayBuffer(4)),
'SharedArrayBuffer { [Uint8Contents]: <00 00 00 00>, byteLength: 4 }'
'SharedArrayBuffer { [Uint8Contents]: <00 00 00 00>, [byteLength]: 4 }'
);

assert.strictEqual(
Expand Down
111 changes: 61 additions & 50 deletions test/parallel/test-util-inspect.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,56 +172,67 @@ assert.doesNotMatch(
const dv = new DataView(ab, 1, 2);
assert.strictEqual(
util.inspect(ab, showHidden),
'ArrayBuffer { [Uint8Contents]: <01 02 03 04>, byteLength: 4 }'
'ArrayBuffer { [Uint8Contents]: <01 02 03 04>, [byteLength]: 4 }'
);
assert.strictEqual(util.inspect(new DataView(ab, 1, 2), showHidden),
'DataView {\n' +
' byteLength: 2,\n' +
' byteOffset: 1,\n' +
' buffer: ArrayBuffer {' +
' [Uint8Contents]: <01 02 03 04>, byteLength: 4 }\n}');
' [byteLength]: 2,\n' +
' [byteOffset]: 1,\n' +
' [buffer]: ArrayBuffer {' +
' [Uint8Contents]: <01 02 03 04>, [byteLength]: 4 }\n}');
assert.strictEqual(
util.inspect(ab, showHidden),
'ArrayBuffer { [Uint8Contents]: <01 02 03 04>, byteLength: 4 }'
'ArrayBuffer { [Uint8Contents]: <01 02 03 04>, [byteLength]: 4 }'
);
assert.strictEqual(util.inspect(dv, showHidden),
'DataView {\n' +
' byteLength: 2,\n' +
' byteOffset: 1,\n' +
' buffer: ArrayBuffer { [Uint8Contents]: ' +
'<01 02 03 04>, byteLength: 4 }\n}');
' [byteLength]: 2,\n' +
' [byteOffset]: 1,\n' +
' [buffer]: ArrayBuffer { [Uint8Contents]: ' +
'<01 02 03 04>, [byteLength]: 4 }\n}');
ab.x = 42;
dv.y = 1337;
assert.strictEqual(util.inspect(ab, showHidden),
'ArrayBuffer { [Uint8Contents]: <01 02 03 04>, ' +
'byteLength: 4, x: 42 }');
assert.strictEqual(util.inspect(dv, showHidden),
'[byteLength]: 4, x: 42 }');
assert.strictEqual(util.inspect(dv, { showHidden, breakLength: 82 }),
'DataView {\n' +
' byteLength: 2,\n' +
' byteOffset: 1,\n' +
' buffer: ArrayBuffer { [Uint8Contents]: <01 02 03 04>,' +
' byteLength: 4, x: 42 },\n' +
' [byteLength]: 2,\n' +
' [byteOffset]: 1,\n' +
' [buffer]: ArrayBuffer { [Uint8Contents]: <01 02 03 04>,' +
' [byteLength]: 4, x: 42 },\n' +
' y: 1337\n}');
}

{
const ab = new ArrayBuffer(42);
const dv = new DataView(ab);

assert.strictEqual(ab.byteLength, 42);
new MessageChannel().port1.postMessage(ab, [ ab ]);
assert.strictEqual(ab.byteLength, 0);
assert.strictEqual(util.inspect(ab),
'ArrayBuffer { (detached), byteLength: 0 }');
'ArrayBuffer { (detached), [byteLength]: 0 }');

assert.strictEqual(
util.inspect(dv),
'DataView {\n' +
' [byteLength]: 0,\n' +
' [byteOffset]: undefined,\n' +
' [buffer]: ArrayBuffer { (detached), [byteLength]: 0 }\n' +
' }',
);
}

// Truncate output for ArrayBuffers using plural or singular bytes
{
const ab = new ArrayBuffer(3);
assert.strictEqual(util.inspect(ab, { showHidden: true, maxArrayLength: 2 }),
assert.strictEqual(util.inspect(ab, { showHidden: true, maxArrayLength: 2, breakLength: 82 }),
'ArrayBuffer { [Uint8Contents]' +
': <00 00 ... 1 more byte>, byteLength: 3 }');
assert.strictEqual(util.inspect(ab, { showHidden: true, maxArrayLength: 1 }),
': <00 00 ... 1 more byte>, [byteLength]: 3 }');
assert.strictEqual(util.inspect(ab, { showHidden: true, maxArrayLength: 1, breakLength: 82 }),
'ArrayBuffer { [Uint8Contents]' +
': <00 ... 2 more bytes>, byteLength: 3 }');
': <00 ... 2 more bytes>, [byteLength]: 3 }');
}

// Now do the same checks but from a different context.
Expand All @@ -231,35 +242,35 @@ assert.doesNotMatch(
const dv = vm.runInNewContext('new DataView(ab, 1, 2)', { ab });
assert.strictEqual(
util.inspect(ab, showHidden),
'ArrayBuffer { [Uint8Contents]: <00 00 00 00>, byteLength: 4 }'
'ArrayBuffer { [Uint8Contents]: <00 00 00 00>, [byteLength]: 4 }'
);
assert.strictEqual(util.inspect(new DataView(ab, 1, 2), showHidden),
'DataView {\n' +
' byteLength: 2,\n' +
' byteOffset: 1,\n' +
' buffer: ArrayBuffer { [Uint8Contents]: <00 00 00 00>,' +
' byteLength: 4 }\n}');
' [byteLength]: 2,\n' +
' [byteOffset]: 1,\n' +
' [buffer]: ArrayBuffer { [Uint8Contents]: <00 00 00 00>,' +
' [byteLength]: 4 }\n}');
assert.strictEqual(
util.inspect(ab, showHidden),
'ArrayBuffer { [Uint8Contents]: <00 00 00 00>, byteLength: 4 }'
'ArrayBuffer { [Uint8Contents]: <00 00 00 00>, [byteLength]: 4 }'
);
assert.strictEqual(util.inspect(dv, showHidden),
'DataView {\n' +
' byteLength: 2,\n' +
' byteOffset: 1,\n' +
' buffer: ArrayBuffer { [Uint8Contents]: <00 00 00 00>,' +
' byteLength: 4 }\n}');
' [byteLength]: 2,\n' +
' [byteOffset]: 1,\n' +
' [buffer]: ArrayBuffer { [Uint8Contents]: <00 00 00 00>,' +
' [byteLength]: 4 }\n}');
ab.x = 42;
dv.y = 1337;
assert.strictEqual(util.inspect(ab, showHidden),
'ArrayBuffer { [Uint8Contents]: <00 00 00 00>, ' +
'byteLength: 4, x: 42 }');
assert.strictEqual(util.inspect(dv, showHidden),
'[byteLength]: 4, x: 42 }');
assert.strictEqual(util.inspect(dv, { showHidden, breakLength: 82 }),
'DataView {\n' +
' byteLength: 2,\n' +
' byteOffset: 1,\n' +
' buffer: ArrayBuffer { [Uint8Contents]: <00 00 00 00>,' +
' byteLength: 4, x: 42 },\n' +
' [byteLength]: 2,\n' +
' [byteOffset]: 1,\n' +
' [buffer]: ArrayBuffer { [Uint8Contents]: <00 00 00 00>,' +
' [byteLength]: 4, x: 42 },\n' +
' y: 1337\n}');
}

Expand All @@ -286,7 +297,7 @@ assert.doesNotMatch(
` [length]: ${length},\n` +
` [byteLength]: ${byteLength},\n` +
' [byteOffset]: 0,\n' +
` [buffer]: ArrayBuffer { byteLength: ${byteLength} }\n]`);
` [buffer]: ArrayBuffer { [byteLength]: ${byteLength} }\n]`);
assert.strictEqual(
util.inspect(array, false),
`${constructor.name}(${length}) [ 65, 97 ]`
Expand Down Expand Up @@ -320,7 +331,7 @@ assert.doesNotMatch(
` [length]: ${length},\n` +
` [byteLength]: ${byteLength},\n` +
' [byteOffset]: 0,\n' +
` [buffer]: ArrayBuffer { byteLength: ${byteLength} }\n]`);
` [buffer]: ArrayBuffer { [byteLength]: ${byteLength} }\n]`);
assert.strictEqual(
util.inspect(array, false),
`${constructor.name}(${length}) [ 65, 97 ]`
Expand Down Expand Up @@ -1837,7 +1848,7 @@ util.inspect(process);
' [byteLength]: 0,',
' [byteOffset]: 0,',
' [buffer]: ArrayBuffer {',
' byteLength: 0,',
' [byteLength]: 0,',
' foo: true',
' }',
' ],',
Expand All @@ -1855,7 +1866,7 @@ util.inspect(process);
' [byteLength]: 0,',
' [byteOffset]: 0,',
' [buffer]: ArrayBuffer {',
' byteLength: 0,',
' [byteLength]: 0,',
' foo: true',
' }',
' ],',
Expand Down Expand Up @@ -1885,7 +1896,7 @@ util.inspect(process);
' [length]: 0,',
' [byteLength]: 0,',
' [byteOffset]: 0,',
' [buffer]: ArrayBuffer { byteLength: 0, foo: true }',
' [buffer]: ArrayBuffer { [byteLength]: 0, foo: true }',
' ],',
' [Set Iterator] {',
' [ 1, 2, [length]: 2 ],',
Expand All @@ -1896,7 +1907,7 @@ util.inspect(process);
' [length]: 0,',
' [byteLength]: 0,',
' [byteOffset]: 0,',
' [buffer]: ArrayBuffer { byteLength: 0, foo: true }',
' [buffer]: ArrayBuffer { [byteLength]: 0, foo: true }',
' ],',
' [Circular *1],',
" [Symbol(Symbol.toStringTag)]: 'Map Iterator'",
Expand Down Expand Up @@ -1924,7 +1935,7 @@ util.inspect(process);
' [byteLength]: 0,',
' [byteOffset]: 0,',
' [buffer]: ArrayBuffer {',
' byteLength: 0,',
' [byteLength]: 0,',
' foo: true } ],',
' [Set Iterator] {',
' [ 1,',
Expand All @@ -1938,7 +1949,7 @@ util.inspect(process);
' [byteLength]: 0,',
' [byteOffset]: 0,',
' [buffer]: ArrayBuffer {',
' byteLength: 0,',
' [byteLength]: 0,',
' foo: true } ],',
' [Circular *1],',
' [Symbol(Symbol.toStringTag)]:',
Expand Down Expand Up @@ -2244,12 +2255,12 @@ assert.strictEqual(util.inspect('"\'${a}'), "'\"\\'${a}'");
[new BigUint64Array(2), '[BigUint64Array(2): null prototype] [ 0n, 0n ]'],
[new ArrayBuffer(16), '[ArrayBuffer: null prototype] {\n' +
' [Uint8Contents]: <00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00>,\n' +
' byteLength: undefined\n}'],
' [byteLength]: undefined\n}'],
[new DataView(new ArrayBuffer(16)),
'[DataView: null prototype] {\n byteLength: undefined,\n ' +
'byteOffset: undefined,\n buffer: undefined\n}'],
'[DataView: null prototype] {\n [byteLength]: undefined,\n ' +
'[byteOffset]: undefined,\n [buffer]: undefined\n}'],
[new SharedArrayBuffer(2), '[SharedArrayBuffer: null prototype] ' +
'{\n [Uint8Contents]: <00 00>,\n byteLength: undefined\n}'],
'{\n [Uint8Contents]: <00 00>,\n [byteLength]: undefined\n}'],
[/foobar/, '[RegExp: null prototype] /foobar/'],
[new Date('Sun, 14 Feb 2010 11:48:40 GMT'),
'[Date: null prototype] 2010-02-14T11:48:40.000Z'],
Expand Down Expand Up @@ -3632,7 +3643,7 @@ assert.strictEqual(
assert.strictEqual(
util.inspect(o),
'{\n' +
' arrayBuffer: ArrayBuffer { [Uint8Contents]: <>, byteLength: 0 },\n' +
' arrayBuffer: ArrayBuffer { [Uint8Contents]: <>, [byteLength]: 0 },\n' +
' buffer: <Buffer 48 65 6c 6c 6f>,\n' +
' typedArray: TypedArray(5) [Uint8Array] [ 72, 101, 108, 108, 111 ],\n' +
' array: [],\n' +
Expand Down
Loading