Le 19/09/2013 10:53, Tom Van Cutsem a écrit :
2013/9/18 David Bruant <[email protected] <mailto:[email protected]>>

    ... I just realized that in your examples, the private state is
    stored in a weakmap which requires target identity. If I recall,
    the original problem wasn't so much with weakmaps, but rather with
    Date instances which is slightly different.
    If solving weakmap lookups via |this| binding is worth solving,
    maybe we need to start considering solving weakmap lookups via the
    receiver of get and set traps, etc. As well as weakmap lookups via
    1st, 2nd, 3rd, etc. argument.


We already have a solution to this: membranes do exactly the right wrapping/unwrapping for all arguments (including |this|, return values, and thrown exceptions).
In a membrane, the method is wrapped and, when called, can unwrap |this| as well as all arguments before making the call to the target. This makes interaction with private state seamless. Membranes don't need invoke (if anyone feel this isn't clear, I'm happy to write the code). The problem being addressed by invoke is "isolated" (non-membrane) proxies and how they interact with private state. Given this is the problem being solved, why auto-unwrapping |this| and not all arguments?

    What does make the 0th argument (this binding) so special?


The fact that many OO programmers don't consider |this| to be an argument
If nothing else, Function.prototype.call makes very clear that |this| is an argument. The "o.method()" notation is just convenient and expressive syntactic sugar for "method.call(o)".

Further, a long-standing invariant in JS has been the equivalence of o.m(...args) and m.call(o, ...args). The invoke trap allows allows to break this invariant. I'm not sure this is for the best. This promotes a given coding pattern, but at the detriment of another. A generic solution to how private state interacts with proxy wouldn't promote any coding pattern, wouldn't break invariants.

I have the impression of seeing the same sort of bias we had for prototype being special in the original Proxy design (Proxy.create(handler, prototype)). |this| doesn't need to be specialized in the proxy design.

and depend on it being of a particular "type".
A well-behaving proxy should be able to emulate a type (modulo branding because of object identity)... well... I guess it depends on what we call a "type". Is an object considered of a given type only if it's strictly been the output of a given constructor? Can't a well-behaving proxy emulate a type? What's the point of proxies if the answer is no to the previous question?

The methods on many of JS's built-ins are a good example. But this is getting philosophical. The fact remains that we should make it easy for proxies to translate |proxy.method(...args)| into |target.method(...args)| calls.
Why "should" we? The original motivation is private state. Are there other needs? The fact that none was identified before the private state issue came up suggests that there might not be.

I'm still inclined to think a generic solution to private state and proxies should be found. Given this solution, the invoke trap may end up being plain redundant. That would be unfortunate. I realize private state isn't figured out for ES6, so I think this issue should be left pending, the invoke trap included.

David
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to