WeakMap better than Private Symbols? (was: direct_proxies "problem")

David Bruant 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 [2] 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
>> implementations).
> 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:
>
> (code)
>
> 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 
purpose!)

> 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 
currently exists.

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

> 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.
>
> Thoughts?
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)

David


More information about the es-discuss mailing list