Skip to content

Commit

Permalink
util: improve prototype inspection using inspect() and showHidden
Browse files Browse the repository at this point in the history
The fast path for the prototype inspection had a bug that caused some
prototype properties to be skipped that should in fact be inspected.

PR-URL: #31113
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Rich Trott <[email protected]>
  • Loading branch information
BridgeAR committed Jan 3, 2020
1 parent 9b7cf09 commit 697908e
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 13 deletions.
12 changes: 5 additions & 7 deletions lib/internal/util/inspect.js
Original file line number Diff line number Diff line change
Expand Up @@ -465,10 +465,10 @@ function getConstructorName(obj, ctx, recurseTimes, protoProps) {
typeof descriptor.value === 'function' &&
descriptor.value.name !== '') {
if (protoProps !== undefined &&
!builtInObjects.has(descriptor.value.name)) {
const isProto = firstProto !== undefined;
(firstProto !== obj ||
!builtInObjects.has(descriptor.value.name))) {
addPrototypeProperties(
ctx, tmp, obj, recurseTimes, isProto, protoProps);
ctx, tmp, firstProto || tmp, recurseTimes, protoProps);
}
return descriptor.value.name;
}
Expand Down Expand Up @@ -506,12 +506,12 @@ function getConstructorName(obj, ctx, recurseTimes, protoProps) {
// This function has the side effect of adding prototype properties to the
// `output` argument (which is an array). This is intended to highlight user
// defined prototype properties.
function addPrototypeProperties(ctx, main, obj, recurseTimes, isProto, output) {
function addPrototypeProperties(ctx, main, obj, recurseTimes, output) {
let depth = 0;
let keys;
let keySet;
do {
if (!isProto) {
if (depth !== 0 || main === obj) {
obj = ObjectGetPrototypeOf(obj);
// Stop as soon as a null prototype is encountered.
if (obj === null) {
Expand All @@ -524,8 +524,6 @@ function addPrototypeProperties(ctx, main, obj, recurseTimes, isProto, output) {
builtInObjects.has(descriptor.value.name)) {
return;
}
} else {
isProto = false;
}

if (depth === 0) {
Expand Down
29 changes: 23 additions & 6 deletions test/parallel/test-util-inspect.js
Original file line number Diff line number Diff line change
Expand Up @@ -1695,7 +1695,8 @@ util.inspect(process);
' 1,',
' 2,',
' [length]: 2',
' ]',
' ],',
" [Symbol(Symbol.toStringTag)]: 'Set Iterator'",
' } => <ref *1> [Map Iterator] {',
' Uint8Array(0) [',
' [BYTES_PER_ELEMENT]: 1,',
Expand All @@ -1707,7 +1708,8 @@ util.inspect(process);
' foo: true',
' }',
' ],',
' [Circular *1]',
' [Circular *1],',
" [Symbol(Symbol.toStringTag)]: 'Map Iterator'",
' }',
'}'
].join('\n');
Expand All @@ -1734,15 +1736,19 @@ util.inspect(process);
' [byteOffset]: 0,',
' [buffer]: ArrayBuffer { byteLength: 0, foo: true }',
' ],',
' [Set Iterator] { [ 1, 2, [length]: 2 ] } => <ref *1> [Map Iterator] {',
' [Set Iterator] {',
' [ 1, 2, [length]: 2 ],',
" [Symbol(Symbol.toStringTag)]: 'Set Iterator'",
' } => <ref *1> [Map Iterator] {',
' Uint8Array(0) [',
' [BYTES_PER_ELEMENT]: 1,',
' [length]: 0,',
' [byteLength]: 0,',
' [byteOffset]: 0,',
' [buffer]: ArrayBuffer { byteLength: 0, foo: true }',
' ],',
' [Circular *1]',
' [Circular *1],',
" [Symbol(Symbol.toStringTag)]: 'Map Iterator'",
' }',
'}'
].join('\n');
Expand Down Expand Up @@ -1772,7 +1778,9 @@ util.inspect(process);
' [Set Iterator] {',
' [ 1,',
' 2,',
' [length]: 2 ] } => <ref *1> [Map Iterator] {',
' [length]: 2 ],',
' [Symbol(Symbol.toStringTag)]:',
" 'Set Iterator' } => <ref *1> [Map Iterator] {",
' Uint8Array(0) [',
' [BYTES_PER_ELEMENT]: 1,',
' [length]: 0,',
Expand All @@ -1781,7 +1789,9 @@ util.inspect(process);
' [buffer]: ArrayBuffer {',
' byteLength: 0,',
' foo: true } ],',
' [Circular *1] } }'
' [Circular *1],',
' [Symbol(Symbol.toStringTag)]:',
" 'Map Iterator' } }"
].join('\n');

assert.strict.equal(out, expected);
Expand Down Expand Up @@ -2680,4 +2690,11 @@ assert.strictEqual(
' \x1B[2m[def]: \x1B[36m[Getter/Setter]\x1B[39m\x1B[22m\n' +
'}'
);

const obj = Object.create({ abc: true, def: 5, toString() {} });
assert.strictEqual(
inspect(obj, { showHidden: true, colors: true }),
'{ \x1B[2mabc: \x1B[33mtrue\x1B[39m\x1B[22m, ' +
'\x1B[2mdef: \x1B[33m5\x1B[39m\x1B[22m }'
);
}

0 comments on commit 697908e

Please sign in to comment.