WeakMap better than Private Symbols? (was: direct_proxies "problem")
bruant.d at gmail.com
Thu Jan 10 08:40:45 PST 2013
Le 10/01/2013 17:22, Nathan Wall a écrit :
>> Choosing symbols or a weakmap would make a huge difference in how proxy
>> replacement would react to DOM algorithms.
>> If the DOM in terms of accessing private properties, then proxies can
>> replace DOM objects transparently. Their "unknownPrivateSymbol" trap
>> will be called  and if they don't throw, the access to the private
>> property will be transparently forwarded to the target without the
>> private symbol ever leaking (it actually wouldn't need to exist in
> Private Symbols are great for their syntactic advantages, but they're also more observable than WeakMaps, and can't be used as a replacement to closures for representing internal state. As a library author, I find this unhelpful. Consider the following SimpleDate implementations:
> AFAIK the two ES6 implementations above should function the same, except when (1) a Proxy uses a SimpleDate as the target and (2) a SimpleDate is frozen.
> In the case of (1), the implementation using a private symbol will have internal accesses to the `timestamp` symbol exposed through the unknownPrivateSymbol trap.
The trap does not expose the symbol. That would be a bad leak.
The third "whitelist" argument in the proxy constructor is here to
communicate whether the proxy knows the privatesymbol or not.
When [[Get]] or [[Set]] (or other property operations) happens with a
whitelisted private symbol, the get or set (or other) trap is called
with the symbol itself (since it's known). If the name isn't in the
whitelist, the unknownPrivateSymbol trap is called with target as the
*only* trap argument (the private name is not exposed and that's on
> In the case of (2), the implementation using a private symbol will fail on a call to `setTime` when the object is frozen (I think).
True. Note that it's not a new thing. It's also an issue with string
properties. In that regard, symbols are only consistent with what
> It sounds to me like if I am writing defensive library code, I will always want to use a WeakMap instead of a Symbol.
You can also wrap all the objects you expose in a proxy that doesn't
allow being frozen (throw in the preventExtensions/seal/freeze traps).
Or make your properties non-configurable accessors.
A bit drastic and costly, but doable if defensiveness matters over
> In both (1) and (2), I would want my object to behave the way the WeakMap implementation behaves, not the Symbol way. Note that, though there are other deviations the ES5 implementation makes, in both (1) and (2) the ES5 one behaves the same as the WeakMap one -- the closure hides the internal state from the unknownPrivateSymbol trap and protects it against freezing.
> Initially, one of the things I loved about Symbols was that it allowed internal state to be specified without using closures, so that prototypal inheritance can be more fully relied upon. However, due to these considerations, I'm not sure Symbols have much use to me anymore.
Interaction between proxies and symbols have been carefully considered
and that shouldn't be a worry for you. The Proxy API has been designed
with preventing private symbols leaks. I don't think there is much that
can be done about the freezing problem than the 2 solutions I suggested
(which can be reasonable).
I think I've described how private names can be used equivalently to
weakmaps. There may be performance issues (though I don't know how
weakmaps perfs are at scale against the perf issues that would come with
the solutions I've suggested)
More information about the es-discuss