`console.log(proxy)` invokes `get` trap with built-in Symbols
- Version: v6.9.2 and v7.4.0
- Platform: Ubuntu 16.06 LTS
- Subsystem: console, util
Calling console.log (util.inspect with default opts) on an instance of a Proxy invokes the get trap with some built-in Symbols. (It also invokes the trap with "inspect" and "valueOf", which is different than browser behavior but doesn't seem as problematic.)
In node:
> var p = new Proxy({a: 1}, {get(o, p) { console.log(typeof p, p); }}); console.log(p) symbol Symbol(util.inspect.custom) string inspect string valueOf symbol Symbol(Symbol.toStringTag) { a: 1 }
In chrome:
> var p = new Proxy({a: 1}, {get(o, p) { console.log(typeof p, p); }}); console.log(p) Proxy {a: 1}
In FF:
> var p = new Proxy({a: 1}, {get(o, p) { console.log(typeof p, p); }}); console.log(p) Proxy { <target>: Object, <handler>: Object }
In Edge:
MSEdge output
var p = new Proxy({a: 1}, {get(o, p) { console.log(typeof p, p); }}); console.log(p) undefined string toString eval code (7) (1,40) string constructor eval code (7) (1,40) string constructor eval code (7) (1,40) string constructor eval code (7) (1,40) string constructor eval code (7) (1,40) string constructor eval code (7) (1,40) string constructor eval code (7) (1,40) string __defineGetter__ eval code (7) (1,40) string __defineSetter__ eval code (7) (1,40) string __lookupGetter__ eval code (7) (1,40) string __lookupSetter__ eval code (7) (1,40) string __proto__ eval code (7) (1,40) string a eval code (7) (1,40) string constructor eval code (7) (1,40) string hasOwnProperty eval code (7) (1,40) string isPrototypeOf eval code (7) (1,40) string propertyIsEnumerable eval code (7) (1,40) string toLocaleString eval code (7) (1,40) string toString eval code (7) (1,40) string valueOf eval code (7) (1,40) string toString eval code (7) (1,40) [object Object] eval code (7) (1,71) { __defineGetter__: undefined, __defineSetter__: undefined, __lookupGetter__: undefined, __lookupSetter__: undefined, __proto__: undefined, a: undefined, constructor: undefined, hasOwnProperty: undefined, isPrototypeOf: undefined, propertyIsEnumerable: undefined, toLocaleString: undefined, toString: undefined, valueOf: undefined }
If you're expecting your object to have Symbol keys and thus handle them, that's fine, but if you're only using string keys, then this can make it necessary to add a guard clause like if (typeof p !== "string") return o[p]; within the get trap. None of the above three browsers invoke the trap with a Symbol, by comparison.
The showProxy: true option for util.inspect prevents these four calls and making it the default could be a fix, but from the comments in #6465 it is apparently too slow. However, a simple isProxy binding (args.GetReturnValue().Set(args[0]->IsProxy())) is 10x faster than the getProxyDetails binding (29 ms vs 280 ms for 1M ops), and the target can be inspected the same as a plain object (without the binding). It seems like there's some special casing that could be done cheaply to avoid invoking the get trap with symbols, or even invoking it at all.
Maybe this is a wontfix -- maybe it's only sane if symbols are handled -- but right now this seems like an addition required to make some get traps compatible with node.