node icon indicating copy to clipboard operation
node copied to clipboard

console.log(proxy) default output is less than helpful

Open jasnell opened this issue 2 weeks ago • 5 comments

Version

All

Platform

All

Subsystem

console/util.inspect

What steps will reproduce the bug?

const p = new Proxy({}, {
  ownKeys() { return ['a']; },
  getOwnPropertyDescriptor() {
    return { value: 1, writable: false, enumerable: true, configurable: true };
  },
  has() { return true; },
  get() { return 1; },
});
console.log(p);  // Outputs '{}'

How often does it reproduce? Is there a required condition?

Always

What is the expected behavior? Why is that the expected behavior?

Ideally, the output would include all enumerable properties, just like it would with a normal, non-proxy object.

What do you see instead?

{} ... omitting the enumerable ownKeys

Additional information

No response

jasnell avatar Dec 05 '25 16:12 jasnell

/cc @BridgeAR

jasnell avatar Dec 05 '25 16:12 jasnell

So:

  • Check if an object is a proxy (isProxy with the internal API)
  • If it is, call ObjectKeys on it and format those values like other objects.

This would be related to https://github.com/nodejs/node/pull/26241 which made the code stricter and not looser (see https://github.com/nodejs/node/issues/10731 ).

IIRC util.inspect does have showProxies but that wouldn't work in this case since it'd just show the original object (empty) and the definition/fact there is ownKeys.

So - the question is "can we determine if calling the proxy traps is side effect free" - maybe if the proxy is tagged well enough we can check kHasSideEffect and if it's side effect free execute it.

benjamingr avatar Dec 07 '25 18:12 benjamingr

This is working as intended so far. We actively do not trigger any proxy traps.

We could in theory add another mode that would trigger all proxy traps that the implementation might use, while they could change over time without any guarantee for what proxy traps would be triggered and when. I personally do not think we should implement that.

Figuring out if a proxy trap is side effect free is also impossible, as far as I can tell and it would not overcome the above issue, as well as potentially being confusing for users to trigger traps in some cases while not in others.

BridgeAR avatar Dec 08 '25 11:12 BridgeAR

That's fine, an understandable. At the very least, it might make sense to add some detail to the output so it's at least more helpful than returning {}... something like { [Proxy] } or something that would indicate that there's something unusual with the case would be helpful.

jasnell avatar Dec 08 '25 16:12 jasnell

I checked and Safari, Firefox, and Chrome all show that information by default. So I guess we could indeed show that the object is proxied as well. It does expose some information about it though and I am uncertain if it matches user's expectations in all cases.

Maybe someone else might want to chime in?

BridgeAR avatar Dec 08 '25 17:12 BridgeAR

Showing that the object is proxied SGTM. We could also print the names of the proxy traps that are defined.

targos avatar Dec 10 '25 13:12 targos

@targos that would effectively result in showProxy option being set to true (it only inspects the traps and logs these methods in addition to inspecting the actual object).

BridgeAR avatar Dec 11 '25 15:12 BridgeAR