console,util: fix missing recursion end while inspecting prototypes
This makes sure prototypes won't be inspected infinitely for some obscure object creations. The depth is now taken into account and the recursion ends when the depth limit is reached. PR-URL: https://github.com/nodejs/node/pull/29647 Fixes: https://github.com/nodejs/node/issues/29646 Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com> Reviewed-By: Minwoo Jung <minwoo@nodesource.com>
This commit is contained in:
parent
0c32ca96c8
commit
1fa403762c
@ -351,7 +351,7 @@ function getEmptyFormatArray() {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
function getConstructorName(obj, ctx) {
|
function getConstructorName(obj, ctx, recurseTimes) {
|
||||||
let firstProto;
|
let firstProto;
|
||||||
const tmp = obj;
|
const tmp = obj;
|
||||||
while (obj) {
|
while (obj) {
|
||||||
@ -372,12 +372,25 @@ function getConstructorName(obj, ctx) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return `${internalGetConstructorName(tmp)} <${inspect(firstProto, {
|
const res = internalGetConstructorName(tmp);
|
||||||
|
|
||||||
|
if (recurseTimes > ctx.depth && ctx.depth !== null) {
|
||||||
|
return `${res} <Complex prototype>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const protoConstr = getConstructorName(firstProto, ctx, recurseTimes + 1);
|
||||||
|
|
||||||
|
if (protoConstr === null) {
|
||||||
|
return `${res} <${inspect(firstProto, {
|
||||||
...ctx,
|
...ctx,
|
||||||
customInspect: false
|
customInspect: false,
|
||||||
|
depth: -1
|
||||||
})}>`;
|
})}>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return `${res} <${protoConstr}>`;
|
||||||
|
}
|
||||||
|
|
||||||
function getPrefix(constructor, tag, fallback) {
|
function getPrefix(constructor, tag, fallback) {
|
||||||
if (constructor === null) {
|
if (constructor === null) {
|
||||||
if (tag !== '') {
|
if (tag !== '') {
|
||||||
@ -581,7 +594,7 @@ function formatValue(ctx, value, recurseTimes, typedArray) {
|
|||||||
function formatRaw(ctx, value, recurseTimes, typedArray) {
|
function formatRaw(ctx, value, recurseTimes, typedArray) {
|
||||||
let keys;
|
let keys;
|
||||||
|
|
||||||
const constructor = getConstructorName(value, ctx);
|
const constructor = getConstructorName(value, ctx, recurseTimes);
|
||||||
let tag = value[Symbol.toStringTag];
|
let tag = value[Symbol.toStringTag];
|
||||||
// Only list the tag in case it's non-enumerable / not an own property.
|
// Only list the tag in case it's non-enumerable / not an own property.
|
||||||
// Otherwise we'd print this twice.
|
// Otherwise we'd print this twice.
|
||||||
|
@ -2114,6 +2114,21 @@ assert.strictEqual(
|
|||||||
inspect(obj),
|
inspect(obj),
|
||||||
"Array <[Object: null prototype] {}> { '0': 1, '1': 2, '2': 3 }"
|
"Array <[Object: null prototype] {}> { '0': 1, '1': 2, '2': 3 }"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
StorageObject.prototype = Object.create(null);
|
||||||
|
Object.setPrototypeOf(StorageObject.prototype, Object.create(null));
|
||||||
|
Object.setPrototypeOf(
|
||||||
|
Object.getPrototypeOf(StorageObject.prototype),
|
||||||
|
Object.create(null)
|
||||||
|
);
|
||||||
|
assert.strictEqual(
|
||||||
|
util.inspect(new StorageObject()),
|
||||||
|
'StorageObject <Object <Object <[Object: null prototype] {}>>> {}'
|
||||||
|
);
|
||||||
|
assert.strictEqual(
|
||||||
|
util.inspect(new StorageObject(), { depth: 1 }),
|
||||||
|
'StorageObject <Object <Object <Complex prototype>>> {}'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that the fallback always works.
|
// Check that the fallback always works.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user