Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proxies: console.log uses overridden proxy methods by default #12453

Closed
ace-n opened this issue Apr 16, 2017 · 8 comments
Closed

Proxies: console.log uses overridden proxy methods by default #12453

ace-n opened this issue Apr 16, 2017 · 8 comments
Labels
util Issues and PRs related to the built-in util module.

Comments

@ace-n
Copy link

ace-n commented Apr 16, 2017

Version: 8.0.0-pre
Platform: Darwin MACHINE_NAME.local 14.3.0 Darwin Kernel Version 14.3.0: Mon Mar 23 11:59:05 PDT 2015; root:xnu-2782.20.48~5/RELEASE_X86_64 x86_64

The following code sample throws an error, due to console.log using the proxy's overridden get - is it supposed to? (FWIW, Chrome's v8 does not throw an error and instead logs the target of the Proxy.)

'use strict';

const handler = {
    get: function(target, prop) {
      throw new Error('whoops');
    }
};
const sandbox = new Proxy({foo: 'bar'}, handler);
console.log(sandbox);
/Users/ace/Desktop/node/test.js:5
      throw new Error('whoops');
      ^

Error: whoops
    at Object.get (/Users/ace/Desktop/node/test.js:5:13)
    at formatValue (util.js:311:38)
    at inspect (util.js:152:10)
    at exports.format (util.js:34:24)
    at Console.log (console.js:85:24)
    at Object.<anonymous> (/Users/ace/Desktop/node/test.js:9:9)
    at Module._compile (module.js:571:32)
    at Object.Module._extensions..js (module.js:580:10)
    at Module.load (module.js:488:32)
    at tryModuleLoad (module.js:447:12)
@addaleax addaleax added the util Issues and PRs related to the built-in util module. label Apr 16, 2017
@addaleax
Copy link
Member

Just fyi, util.inspect (and console.dir indirectly too) has a showProxy option that lets you enable displaying the proxy itself, see https://nodejs.org/api/util.html#util_util_inspect_object_options.

But I see your point, and I’m not sure whether this should be a bug or not myself. What’s the alternative to passing the error along? Just defaulting to displaying the Proxy target doesn’t seem quite right…

@ace-n
Copy link
Author

ace-n commented Apr 16, 2017

To be honest, it makes sense to me that console.log should respect the Proxy (and, as you said, pass the error along). But it doesn't seem like it does so universally:

'use strict';

const handler = {
    get: function(target, prop) {
      return target[prop] + "baz";
    }
};
const sandbox = new Proxy({foo: 'bar'}, handler);
console.log(sandbox);
console.log(sandbox.foo);
{ foo: 'bar' } // should this be { foo: 'barbaz' }?
barbaz

Perhaps this is a question for the v8 folks?

@addaleax
Copy link
Member

That latter behaviour is because util.inspect uses Object.getOwnPropertyDescriptor to get the value, and in your example the proxy doesn’t provide that trap.

(Ironically, one of the reasons util.inspect does that is to avoid getters that might throw errors. 😄)

@ace-n
Copy link
Author

ace-n commented Apr 16, 2017

Here's an example with the trap added:

'use strict';

const handler = {
    get: function(target, prop) {
      return (target && target[prop] && typeof target[prop] == 'string') ?
      	target[prop] + "baz" :
      	target[prop];
    },
    getOwnPropertyDescriptor: function(target, prop) {
      let a = Object.getOwnPropertyDescriptor(target, prop);
      if (a)
      	a.value = this.get(target, prop);
      return a;
    }
};
const sandbox = new Proxy({foo: 'bar'}, handler);
console.log(sandbox);
console.log(sandbox.foo);
{ foo: 'barbaz' }
barbaz

At first glance, it seems like everything is working correctly in this example (that doesn't involve error throwing). Perhaps this is just an eccentricity of Node or even Javascript itself? (I'm not sure if the ECMA specification has anything to say about this.)

@TimothyGu
Copy link
Member

There are really no consensus on what console.log should do in this instance.

The way Chrome handles it is always displaying the proxied target in the short one-line view, and providing more information about the proxy once you expand it:

image
image

Firefox on the other hand always displays the proxied values, and does not allow introspection of the internal slots of the proxy object:

image

And in case of thrown errors, it just says "Error":

image

FWIW the Console Standard does not say anything about the possibility of throwing either.

@Trott
Copy link
Member

Trott commented Aug 2, 2017

Should this remain open?

@BridgeAR
Copy link
Member

As far as I see it everything is working as it should. I am closing this therefore.

@bnoordhuis
Copy link
Member

Linking to #13784 - it's related in the sense that we currently lack a safe way to inspect JS values.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
util Issues and PRs related to the built-in util module.
Projects
None yet
Development

No branches or pull requests

6 participants