[[Invoke]] and implicit method calls

David Bruant bruant.d at gmail.com
Fri Sep 20 02:57:23 PDT 2013

Le 19/09/2013 10:53, Tom Van Cutsem a écrit :
> 2013/9/18 David Bruant <bruant.d at gmail.com <mailto:bruant.d at gmail.com>>
>     ... 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.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20130920/aaad5eac/attachment.html>

More information about the es-discuss mailing list