Skip to content
Closed
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
21 changes: 13 additions & 8 deletions lib/internal/util/inspect.js
Original file line number Diff line number Diff line change
Expand Up @@ -869,15 +869,21 @@ function formatValue(ctx, value, recurseTimes, typedArray) {
const context = value;
// 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) {
return ctx.stylize('<Revoked Proxy>', 'special');
}
value = proxy;
proxy = getProxyDetails(value, false);
} while (proxy !== undefined);
}

// Provide a hook for user-specified inspect functions.
Expand All @@ -892,8 +898,7 @@ function formatValue(ctx, value, recurseTimes, typedArray) {
// This makes sure the recurseTimes are reported as before while using
// a counter internally.
const depth = ctx.depth === null ? null : ctx.depth - recurseTimes;
const isCrossContext =
proxy !== undefined || !FunctionPrototypeSymbolHasInstance(Object, context);
const isCrossContext = context !== value || !FunctionPrototypeSymbolHasInstance(Object, context);
const ret = FunctionPrototypeCall(
maybeCustom,
context,
Expand Down Expand Up @@ -2433,7 +2438,7 @@ function hasBuiltInToString(value) {
if (proxyTarget === null) {
return true;
}
value = proxyTarget;
return hasBuiltInToString(proxyTarget);
}

let hasOwnToString = ObjectPrototypeHasOwnProperty;
Expand Down
34 changes: 33 additions & 1 deletion test/parallel/test-util-inspect-proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -179,3 +183,31 @@ const expected10 = '[Function (anonymous)]';
const expected11 = '[Function (anonymous)]';
assert.strictEqual(util.inspect(proxy10), expected10);
assert.strictEqual(util.inspect(proxy11), expected11);

const proxy12 = new Proxy([1, 2, 3], proxy5);
assert.strictEqual(
util.inspect(proxy12, { colors: true, breakLength: 1 }),
'[\n \x1B[33m1\x1B[39m,\n \x1B[33m2\x1B[39m,\n \x1B[33m3\x1B[39m\n]'
);
assert.strictEqual(util.format('%s', proxy12), '[ 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 }), '{}');
}

{
// 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 }), '<Revoked Proxy>');
}
Loading