This is a placeholder page to record the ongoing discussion on the interaction between direct_proxies and private_name_objects.
The basic issue is that a proxy can’t just intercept operations involving private names naively, since that would allow a malicious proxy to steal private names, e.g.:
let n = new Name() obj[n] // if obj is a proxy, the proxy handler sees: handler.get(target, n, obj)
Here’s another problematic case described by Sam Tobin-Hochstadt.
An earlier design discussed at the July TC39 meeting split up all traps into “normal” and “name” variants, where the “name” variants would need to “prove” to the proxy that they knew of the intercepted private name, given its “public” part. This lead to some concern about the overhead required to transparently deal with names and lead us to explore some alternative designs, one of which is detailed below:
var whitelist = new WeakSet() var p = Proxy(target, handler, whitelist) var n1 = new Name() var n2 = new Name() whitelist.add(n1) p[n1] // calls handler.get(target, n1, p) p[n2] // calls handler.unknownPrivateName(target)
unknownPrivateName(target) trap.unknownPrivateName trap is not defined, or the trap invocation returns true, the operation is forwarded to the target (the handler never sees the name).unknownPrivateName trap returns false, a TypeError is thrown. This is useful for proxies that don’t want to forward operations on names they don’t know about (membranes probably want to do this)unknownPrivateName trap for any operation involving private names (it’s as if the whitelist is always empty).Lookup on the whitelist
Care must be taken that a proxy can’t specify its own whitelist to interfere with the lookup of private names. To this end, the whitelist must be a built-in WeakSet, and the lookup of a private name name occurs by calling the built-in/intrinsic WeakSet.prototype.has method. Overriding this method will not influence private name lookup. The check is performed as if the proxy performs:
WeakSet.prototype.has.call(whitelist, name) // assuming the original definition of WeakSet.prototype.has
Advantages
get vs getName, has vs hasName, etc.).public properties)unknownPrivateName trap allows the handler to define its own policy w.r.t. how to deal with unknown private names.unknownPrivateName trap are oblivious to private names: any operation involving a private name is just forwarded to the target, without consulting the handler.true. An effort is underway to prototype this in Spidermonkey.unknownPrivateName trap to return or throw explicitly, rather than having it a return a boolean. See this es-discuss thread.Discussion during TC39 September 2012 meeting, Boston:
WeakSet.prototype.has is changed, proxy still calls the intrinsic one (to prevent stealing of names via an overridden method)Proxy(target, handler, [n1, n2])), which is then coerced into (i.e. whose elements are copied into) a WeakSet. One problem with this is that updating the original array-like won’t then update the coerced WeakSet, which may be confusing..public property of private names. If we don’t drop the .public property, don’t need the whitelist but instead just a resolvePrivateName trap. If we stick with the whitelist, we should not pass the .public property to the unknownPrivateName/resolvePrivateName trap.resolvePrivateName(target, name.public) → undefined | name trap into a simpler unknownPrivateName(target) → boolean trap. At this point, the .public property on private names is no longer needed as far as proxies are concerned.resolvePrivateName(target, public) trap worked as follows:resolvePrivateName trap is not defined, or the trap invocation returns undefined, the operation is forwarded to the target.resolvePrivateName trap returns the private name corresponding to public, the operation is trapped as if the private name were in the whitelist.