Description
- 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.