> 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:

    // ES5
    function SimpleDate(timestamp) {
    
        timestamp = +timestamp;

        this.setTime = function setTime(time) {
            timestamp = +time;
        }

        this.getTime = function getTime() {
            return timestamp;
        }
    
    }

Trying to rewrite it in ES6 produces these possibilities:

    // ES6 Symbols

    // Forgive me for not knowing what the current
    // correct syntax is for creating a symbol:
    let timestamp = new Symbol();

    class SimpleDate {

        construct(time) {
            this.setTime(time);
        }

        setTime(time) {
            this[timestamp] = +time;
        }

        getTime() {
            return this[timestamp];
        }

    }


    // ES6 WeakMap

    let timeMap = new WeakMap(),
        // Store WeakMap methods to maintain integrity of the internal state.
        WeakMapGet = Function.prototype.call.bind(WeakMap.prototype.get),
        WeakMapSet = Function.prototype.call.bind(WeakMap.prototype.set);

    class SimpleDate {

        construct(time) {
        this.setTime(time);
        }

        setTime(time) {
            WeakMapSet(timeMap, this, +time);
        }

        getTime() {
            return WeakMapGet(timeMap, this);
        }

    }

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.

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

It sounds to me like if I am writing defensive library code, I will always want 
to use a WeakMap instead of a Symbol. 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?                                         
_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to