From 8253a307ce405a1cd5c35245abc7f6e47f9c16bc Mon Sep 17 00:00:00 2001 From: Daeyeon Jeong Date: Sat, 14 May 2022 22:44:26 +0900 Subject: [PATCH] console: fix console.dir crash on a revoked proxy Fixes: https://github.com/nodejs/node/issues/43095 Signed-off-by: Daeyeon Jeong daeyeon.dev@gmail.com --- lib/internal/util/inspect.js | 25 ++++++++++++++--------- test/parallel/test-console-issue-43095.js | 12 +++++++++++ test/parallel/test-util-inspect-proxy.js | 19 +++++++++++++++++ 3 files changed, 46 insertions(+), 10 deletions(-) create mode 100644 test/parallel/test-console-issue-43095.js diff --git a/lib/internal/util/inspect.js b/lib/internal/util/inspect.js index d78a4e97d218a6..a28a561f179f03 100644 --- a/lib/internal/util/inspect.js +++ b/lib/internal/util/inspect.js @@ -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); @@ -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. @@ -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, diff --git a/test/parallel/test-console-issue-43095.js b/test/parallel/test-console-issue-43095.js new file mode 100644 index 00000000000000..647f4af2df4f96 --- /dev/null +++ b/test/parallel/test-console-issue-43095.js @@ -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 })); diff --git a/test/parallel/test-util-inspect-proxy.js b/test/parallel/test-util-inspect-proxy.js index 3e1341fadfc9f9..fe69409a63a980 100644 --- a/test/parallel/test-util-inspect-proxy.js +++ b/test/parallel/test-util-inspect-proxy.js @@ -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' +