> These use cases can be made dynamic be some kind of
>
> Proxy.fromNowOnForwardUnknownPrivateSymbols(proxy, false);
>
> API. This is not truly dynamic. I'd say no truly dynamic use cases
> exist, where you must decide _at_the_exact_point_of_access_. IMO.


I would be ok with something more along the lines of:

    Proxy.preventAllFurtherCommunicationsThrough(proxy);

Meaning that the target becomes inaccessible through the proxy, through both 
traps that were specified in the handler and implicit forwarding, including 
private symbols.

One of the major problems I have with `unknownPrivateSymbol` can be represented 
in the following case:

    let create = Object.create,
        getOwnPropertyNames = Object.getOwnPropertyNames,

        $size = new Symbol(/* private */),
        $data = new Symbol(/* private */);

    class StringMap {

        constructor() {
            this[$size] = 0;
            this[$data] = create(null);
        }

        set(key, value) {

            let data = this[$data];

            if (!data)
                throw new TypeError('this object must be a StringMap');

            if (!(key in data))
                this[$size]++;

            data[key] = value;

        }

        get(key) {

            let data = this[$data];

            if (!data)
                throw new TypeError('this object must be a StringMap');

            return data[key];

        }

        size() {
            return this[$size];
        }

        keys() {

            let data = this[$data];

            if (!data)
                throw new TypeError('this object must be a StringMap');

            return getOwnPropertyNames(data);

        }

    }

I think it is wrong that a Proxy should be allowed to introduce an 
inconsistency in my object by permitting me to increase the private size 
property but then preventing me from adding the new key to the data set. For 
example:

    function getBrokenMap() {

        let map = new StringMap();
        map.set('apple', 'red');
        map.set('kiwi', 'green');

        let beEvil = false,
            evilProxy = new Proxy(map, {
                unknownPrivateSymbol: function() {
                    if (beEvil)
                        throw new Error();
                    beEvil = true;
                }
            });

        try {
            map.set('lemon', 'yellow');
        } catch(x) { }

        return map;

    }

    let map = getBrokenMap();

    map.size();        // => 3
    map.keys().length; // => 2

I think this is a problem from the standpoint of a library developer who wants 
to ensure the integrity of one's components.

In the discussion with David, I think we agreed that it is possible for a 
membrane to prevent communication between two objects without 
`unknownPrivateSymbol` given (1) they don't know each other directly and (2) no 
other third party knows both of them directly. We also agreed that given either 
1 or 2, the objects could establish means to communicate behind the membrane's 
back **regardless of whether `unknownPrivateSymbol` exists**.

In light of these considerations, I would strongly urge the removal of 
`unknownPrivateSymbol`. It allows breaking all private symbol communication in 
one fell swoop, but it also allows other things which, in my opinion, should 
not be allowed. As Brendan said, it's really none of your business to be able 
to interfere with my object's internals -- including, I would add, internal 
access to private symbols you don't know about.

If you want a way to cut communications, how about a function that disables all 
traps and all forwarding on the proxy (including private symbol forwarding)? 
That prevents the public method `set(key, value)` from being called which uses 
the internal private keys, so it doesn't mess up the integrity of my object.

Nathan                                    
_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to