Skip to content

Commit

Permalink
console: fix console.dir crash on a revoked proxy
Browse files Browse the repository at this point in the history
Fixes: nodejs#43095

Signed-off-by: Daeyeon Jeong daeyeon.dev@gmail.com
  • Loading branch information
daeyeon committed May 14, 2022
1 parent 556df3d commit 8253a30
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 10 deletions.
25 changes: 15 additions & 10 deletions lib/internal/util/inspect.js
Original file line number Diff line number Diff line change
Expand Up @@ -724,16 +724,18 @@ function getCtxStyle(value, constructor, tag) {
return getPrefix(constructor, tag, fallback);
}

function formatProxy(ctx, proxy, recurseTimes) {
function formatProxy(ctx, target, handler, recurseTimes, showProperties = true) {
if (recurseTimes > ctx.depth && ctx.depth !== null) {
return ctx.stylize('Proxy [Array]', 'special');
}
recurseTimes += 1;
ctx.indentationLvl += 2;
const res = [
formatValue(ctx, proxy[0], recurseTimes),
formatValue(ctx, proxy[1], recurseTimes),
];
const res = showProperties ?
[
formatValue(ctx, target, recurseTimes),
formatValue(ctx, handler, recurseTimes),
] :
[];
ctx.indentationLvl -= 2;
return reduceToSingleString(
ctx, res, '', ['Proxy [', ']'], kArrayExtrasType, recurseTimes);
Expand All @@ -757,12 +759,15 @@ 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);
if (proxy !== undefined) {
const details = getProxyDetails(value, !!ctx.showProxy);
if (details !== undefined) {
if (ctx.showProxy) {
return formatProxy(ctx, proxy, recurseTimes);
return formatProxy(ctx, details[0], details[1], recurseTimes);
} else if (details === null) {
// The proxy is revoked. Both target and handler of it are null.
return formatProxy(ctx, details, null, recurseTimes, ctx.showProxy);
}
value = proxy;
value = details;
}

// Provide a hook for user-specified inspect functions.
Expand All @@ -778,7 +783,7 @@ function formatValue(ctx, value, recurseTimes, typedArray) {
// a counter internally.
const depth = ctx.depth === null ? null : ctx.depth - recurseTimes;
const isCrossContext =
proxy !== undefined || !(context instanceof Object);
details !== undefined || !(context instanceof Object);
const ret = FunctionPrototypeCall(
maybeCustom,
context,
Expand Down
12 changes: 12 additions & 0 deletions test/parallel/test-console-issue-43095.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
'use strict';

require('../common');
const { inspect } = require('node:util');

const r = Proxy.revocable({}, {});
r.revoke();

console.dir(r);
console.dir(r.proxy);
console.log(r.proxy);
console.log(inspect(r.proxy, { showProxy: true }));
19 changes: 19 additions & 0 deletions test/parallel/test-util-inspect-proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,25 @@ assert.strictEqual(handler, details[1]);
details = processUtil.getProxyDetails(proxyObj, false);
assert.strictEqual(target, details);

details = processUtil.getProxyDetails({}, true);
assert.strictEqual(details, undefined);

const r = Proxy.revocable({}, {});
r.revoke();

details = processUtil.getProxyDetails(r.proxy, true);
assert.strictEqual(details[0], null);
assert.strictEqual(details[1], null);

details = processUtil.getProxyDetails(r.proxy, false);
assert.strictEqual(details, null);

assert.strictEqual(util.inspect(r.proxy), 'Proxy [ ]');
assert.strictEqual(
util.inspect(r, { showProxy: true }),
'{ proxy: Proxy [ null, null ], revoke: [Function (anonymous)] }',
);

assert.strictEqual(
util.inspect(proxyObj, opts),
'Proxy [\n' +
Expand Down

0 comments on commit 8253a30

Please sign in to comment.