[[Invoke]] and implicit method calls
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...
More information about the es-discuss