Skip to content

Commit 9c88fe1

Browse files
committed
console: fix console.dir crash on a revoked proxy
Signed-off-by: Daeyeon Jeong [email protected]
1 parent 556df3d commit 9c88fe1

File tree

3 files changed

+46
-10
lines changed

3 files changed

+46
-10
lines changed

lib/internal/util/inspect.js

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -724,16 +724,18 @@ function getCtxStyle(value, constructor, tag) {
724724
return getPrefix(constructor, tag, fallback);
725725
}
726726

727-
function formatProxy(ctx, proxy, recurseTimes) {
727+
function formatProxy(ctx, target, handler, recurseTimes, showProperties = true) {
728728
if (recurseTimes > ctx.depth && ctx.depth !== null) {
729729
return ctx.stylize('Proxy [Array]', 'special');
730730
}
731731
recurseTimes += 1;
732732
ctx.indentationLvl += 2;
733-
const res = [
734-
formatValue(ctx, proxy[0], recurseTimes),
735-
formatValue(ctx, proxy[1], recurseTimes),
736-
];
733+
const res = showProperties ?
734+
[
735+
formatValue(ctx, target, recurseTimes),
736+
formatValue(ctx, handler, recurseTimes),
737+
] :
738+
[];
737739
ctx.indentationLvl -= 2;
738740
return reduceToSingleString(
739741
ctx, res, '', ['Proxy [', ']'], kArrayExtrasType, recurseTimes);
@@ -757,12 +759,15 @@ function formatValue(ctx, value, recurseTimes, typedArray) {
757759
const context = value;
758760
// Always check for proxies to prevent side effects and to prevent triggering
759761
// any proxy handlers.
760-
const proxy = getProxyDetails(value, !!ctx.showProxy);
761-
if (proxy !== undefined) {
762+
const details = getProxyDetails(value, !!ctx.showProxy);
763+
if (details !== undefined) {
762764
if (ctx.showProxy) {
763-
return formatProxy(ctx, proxy, recurseTimes);
765+
return formatProxy(ctx, details[0], details[1], recurseTimes);
766+
} else if (details === null) {
767+
// The proxy is revoked. Both target and handler of it are null.
768+
return formatProxy(ctx, details, null, recurseTimes, ctx.showProxy);
764769
}
765-
value = proxy;
770+
value = details;
766771
}
767772

768773
// Provide a hook for user-specified inspect functions.
@@ -778,7 +783,7 @@ function formatValue(ctx, value, recurseTimes, typedArray) {
778783
// a counter internally.
779784
const depth = ctx.depth === null ? null : ctx.depth - recurseTimes;
780785
const isCrossContext =
781-
proxy !== undefined || !(context instanceof Object);
786+
details !== undefined || !(context instanceof Object);
782787
const ret = FunctionPrototypeCall(
783788
maybeCustom,
784789
context,
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
'use strict';
2+
3+
require('../common');
4+
const { inspect } = require('node:util');
5+
6+
const r = Proxy.revocable({}, {});
7+
r.revoke();
8+
9+
console.dir(r);
10+
console.dir(r.proxy);
11+
console.log(r.proxy);
12+
console.log(inspect(r.proxy, { showProxy: true }));

test/parallel/test-util-inspect-proxy.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,25 @@ assert.strictEqual(handler, details[1]);
5757
details = processUtil.getProxyDetails(proxyObj, false);
5858
assert.strictEqual(target, details);
5959

60+
details = processUtil.getProxyDetails({}, true);
61+
assert.strictEqual(details, undefined);
62+
63+
const r = Proxy.revocable({}, {});
64+
r.revoke();
65+
66+
details = processUtil.getProxyDetails(r.proxy, true);
67+
assert.strictEqual(details[0], null);
68+
assert.strictEqual(details[1], null);
69+
70+
details = processUtil.getProxyDetails(r.proxy, false);
71+
assert.strictEqual(details, null);
72+
73+
assert.strictEqual(util.inspect(r.proxy), 'Proxy [ ]');
74+
assert.strictEqual(
75+
util.inspect(r, { showProxy: true }),
76+
'{ proxy: Proxy [ null, null ], revoke: [Function (anonymous)] }',
77+
);
78+
6079
assert.strictEqual(
6180
util.inspect(proxyObj, opts),
6281
'Proxy [\n' +

0 commit comments

Comments
 (0)