mirror of
https://github.com/zebrajr/node.git
synced 2026-01-15 12:15:26 +00:00
util: fix nested proxy inspection
Fixes: https://github.com/nodejs/node/issues/61061 PR-URL: https://github.com/nodejs/node/pull/61077 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: LiviaMedeiros <livia@cirno.name> Reviewed-By: Juan José Arboleda <soyjuanarbol@gmail.com> Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
This commit is contained in:
committed by
GitHub
parent
799feac6f5
commit
9120924de1
@@ -1118,17 +1118,29 @@ function formatValue(ctx, value, recurseTimes, typedArray) {
|
||||
|
||||
// Memorize the context for custom inspection on proxies.
|
||||
const context = value;
|
||||
let proxies = 0;
|
||||
// Always check for proxies to prevent side effects and to prevent triggering
|
||||
// any proxy handlers.
|
||||
const proxy = getProxyDetails(value, !!ctx.showProxy);
|
||||
let proxy = getProxyDetails(value, !!ctx.showProxy);
|
||||
if (proxy !== undefined) {
|
||||
if (proxy === null || proxy[0] === null) {
|
||||
return ctx.stylize('<Revoked Proxy>', 'special');
|
||||
}
|
||||
if (ctx.showProxy) {
|
||||
if (proxy[0] === null) {
|
||||
return ctx.stylize('<Revoked Proxy>', 'special');
|
||||
}
|
||||
return formatProxy(ctx, proxy, recurseTimes);
|
||||
}
|
||||
value = proxy;
|
||||
do {
|
||||
if (proxy === null) {
|
||||
let formatted = ctx.stylize('<Revoked Proxy>', 'special');
|
||||
for (let i = 0; i < proxies; i++) {
|
||||
formatted = `${ctx.stylize('Proxy(', 'special')}${formatted}${ctx.stylize(')', 'special')}`;
|
||||
}
|
||||
return formatted;
|
||||
}
|
||||
value = proxy;
|
||||
proxy = getProxyDetails(value, false);
|
||||
proxies += 1;
|
||||
} while (proxy !== undefined);
|
||||
}
|
||||
|
||||
// Provide a hook for user-specified inspect functions.
|
||||
@@ -1144,7 +1156,7 @@ function formatValue(ctx, value, recurseTimes, typedArray) {
|
||||
// a counter internally.
|
||||
const depth = ctx.depth === null ? null : ctx.depth - recurseTimes;
|
||||
const isCrossContext =
|
||||
proxy !== undefined || !FunctionPrototypeSymbolHasInstance(Object, context);
|
||||
proxies !== 0 || !FunctionPrototypeSymbolHasInstance(Object, context);
|
||||
const ret = FunctionPrototypeCall(
|
||||
maybeCustom,
|
||||
context,
|
||||
@@ -1180,10 +1192,12 @@ function formatValue(ctx, value, recurseTimes, typedArray) {
|
||||
return ctx.stylize(`[Circular *${index}]`, 'special');
|
||||
}
|
||||
|
||||
const formatted = formatRaw(ctx, value, recurseTimes, typedArray);
|
||||
let formatted = formatRaw(ctx, value, recurseTimes, typedArray);
|
||||
|
||||
if (proxy !== undefined) {
|
||||
return `${ctx.stylize('Proxy(', 'special')}${formatted}${ctx.stylize(')', 'special')}`;
|
||||
if (proxies !== 0) {
|
||||
for (let i = 0; i < proxies; i++) {
|
||||
formatted = `${ctx.stylize('Proxy(', 'special')}${formatted}${ctx.stylize(')', 'special')}`;
|
||||
}
|
||||
}
|
||||
|
||||
return formatted;
|
||||
@@ -2691,7 +2705,7 @@ function hasBuiltInToString(value) {
|
||||
if (proxyTarget === null) {
|
||||
return true;
|
||||
}
|
||||
value = proxyTarget;
|
||||
return hasBuiltInToString(proxyTarget);
|
||||
}
|
||||
|
||||
let hasOwnToString = ObjectPrototypeHasOwnProperty;
|
||||
|
||||
@@ -42,7 +42,11 @@ proxyObj = new Proxy(target, handler);
|
||||
util.inspect(proxyObj, opts);
|
||||
|
||||
// Make sure inspecting object does not trigger any proxy traps.
|
||||
util.format('%s', proxyObj);
|
||||
// %i%f%d use Symbol.toPrimitive to convert the value to a string.
|
||||
// %j uses JSON.stringify, accessing the value's toJSON and toString method.
|
||||
util.format('%s%o%O%c', proxyObj, proxyObj, proxyObj, proxyObj);
|
||||
const nestedProxy = new Proxy(new Proxy({}, handler), {});
|
||||
util.format('%s%o%O%c', nestedProxy, nestedProxy, nestedProxy, nestedProxy);
|
||||
|
||||
// getProxyDetails is an internal method, not intended for public use.
|
||||
// This is here to test that the internals are working correctly.
|
||||
@@ -135,6 +139,10 @@ const expected6 = 'Proxy [\n' +
|
||||
' Proxy [ Proxy [Array], Proxy [Array] ]\n' +
|
||||
' ]\n' +
|
||||
']';
|
||||
const expected2NoShowProxy = 'Proxy(Proxy({}))';
|
||||
const expected3NoShowProxy = 'Proxy(Proxy(Proxy({})))';
|
||||
const expected4NoShowProxy = 'Proxy(Proxy(Proxy(Proxy({}))))';
|
||||
const expected5NoShowProxy = 'Proxy(Proxy(Proxy(Proxy(Proxy({})))))';
|
||||
assert.strictEqual(
|
||||
util.inspect(proxy1, { showProxy: 1, depth: null }),
|
||||
expected1);
|
||||
@@ -144,11 +152,11 @@ assert.strictEqual(util.inspect(proxy4, opts), expected4);
|
||||
assert.strictEqual(util.inspect(proxy5, opts), expected5);
|
||||
assert.strictEqual(util.inspect(proxy6, opts), expected6);
|
||||
assert.strictEqual(util.inspect(proxy1), expected0);
|
||||
assert.strictEqual(util.inspect(proxy2), expected0);
|
||||
assert.strictEqual(util.inspect(proxy3), expected0);
|
||||
assert.strictEqual(util.inspect(proxy4), expected0);
|
||||
assert.strictEqual(util.inspect(proxy5), expected0);
|
||||
assert.strictEqual(util.inspect(proxy6), expected0);
|
||||
assert.strictEqual(util.inspect(proxy2), expected2NoShowProxy);
|
||||
assert.strictEqual(util.inspect(proxy3), expected3NoShowProxy);
|
||||
assert.strictEqual(util.inspect(proxy4), expected2NoShowProxy);
|
||||
assert.strictEqual(util.inspect(proxy5), expected4NoShowProxy);
|
||||
assert.strictEqual(util.inspect(proxy6), expected5NoShowProxy);
|
||||
|
||||
// Just for fun, let's create a Proxy using Arrays.
|
||||
const proxy7 = new Proxy([], []);
|
||||
@@ -188,3 +196,24 @@ assert.strictEqual(
|
||||
')\x1B[39m'
|
||||
);
|
||||
assert.strictEqual(util.format('%s', proxy12), 'Proxy([ 1, 2, 3 ])');
|
||||
|
||||
{
|
||||
// Nested proxies should not trigger any proxy handlers.
|
||||
const nestedProxy = new Proxy(new Proxy(new Proxy({}, handler), {}), {});
|
||||
|
||||
assert.strictEqual(
|
||||
util.inspect(nestedProxy, { showProxy: true }),
|
||||
'Proxy [ Proxy [ Proxy [ {}, [Object] ], {} ], {} ]'
|
||||
);
|
||||
assert.strictEqual(util.inspect(nestedProxy, { showProxy: false }), expected3NoShowProxy);
|
||||
}
|
||||
|
||||
{
|
||||
// Nested revoked proxies should work as expected as well as custom inspection functions.
|
||||
const revocable = Proxy.revocable({}, handler);
|
||||
revocable.revoke();
|
||||
const nestedProxy = new Proxy(revocable.proxy, {});
|
||||
|
||||
assert.strictEqual(util.inspect(nestedProxy, { showProxy: true }), 'Proxy [ <Revoked Proxy>, {} ]');
|
||||
assert.strictEqual(util.inspect(nestedProxy, { showProxy: false }), 'Proxy(<Revoked Proxy>)');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user