On Sep 21, 2013, at 2:53 AM, Tom Van Cutsem wrote:
>
> 2013/9/21 Allen Wirfs-Brock <[email protected]>
>
> On Sep 20, 2013, at 5:31 PM, Brendan Eich wrote:
> > Given this, having the legacy internal calls continue to use get+call
> seems fine to me. A proxy implementing toString, e.g., can make it work using
> these traps just as well as via get+invoke, and without double lookup or
> boolean-trap-smelling (id | func) parameterization of invoke.
>
> In that case, why not just use [[Get]]+[[InvokeFunction]] in all cases
> (including obj.m(()) and not have the current [[Invoke]] at all. It allows
> the proxy handler to correctly intercede on all method invocations including
> conditional cones.
>
> Yes, except:
>
> a) proxies must then still allocate a temporary function object in the get
> trap. Thus, the primary reason for having a derived trap (less allocations),
> disappears.
??? Not in the normal cases where function already exist for the method
properties. They would only have to be allocated for the more exceptional
situation where the handler is trying to directly implemented method behavior
within the handler (via a switch statement, etc)
or was there something else you had in mind with the above assertion?
> b) every method call on a proxy triggers at least 2 traps ("get" + "invoke").
> Another selling point of invoke() was that method calls go through one trap
> only.
Yes, we do have the added overhead, of two traps but with the benefit is that
we get a more consistent semantics that is a better match to current ES
expectations.
If we really are worried about the overhead of two traps we could have a
derived "invoke" trap that does "get"+"invokeFunction" but I'm not sure the
complexity is worth it (or that there would actually be any saving, isn't the
the default implementation of "invoke" just going to essentially trigger the
other two traps?)
> c) double-lifting needs 2 traps (get + invoke) rather than just get.
I don't think so, using [[invokeFunction]] instead of [[Invoke]] eliminates the
need for two:
the current dispatch mechanism for Proxy Mop operations is essentially
let trap = handler.[[Get]]("handlerName");
...
trap.[[Call]](handler,args);
if [[InvokeFunction]] was available this would become
let trap = handler.[[Get]]("handlerName");
...
handler.[[InvokeFunction]](trap, handler,args);
The default behavior of [[InvokeFunction]] on a Proxy that does not have a
corresponding "invokeFunction" trap defined is equivalent to a [[Call]] of the
passed function so the behavior would be exactly the same. All the metameta
handler needs to define is "get".
>
> At that point, we're better off dropping [[InvokeFunction]] entirely.
>
> As Brendan mentioned, methods are extractable in JS. A new MOP operation
> doesn't relieve proxies from honoring that contract.
It still appears to me that [[Get]]+[[InvokeFunction]] and respec'ing
F.p.call/apply in terms of [[InvokeFunction]] is the closest semantic match to
this expected behavior plus has the least anomalies WRT transparent proxying of
built-ins with private state (and user defined classes that we WeakMaps for
private state).
>
> I believe we made the right trade-offs so far and still stand by the
> status-quo.
Which status-quo? We have some fundamental semantic consistency issues
involving Proxies and method invocation.
We have a number of alternatives that have been discussed and they all seem to
have both pros and cons associated with them. I also believe that done of them
perfectly resolves all of the semantic consistency issues and at the same time
preserves perfect actual or conceptual backwards compatibility. Personally,
I'm finding it difficult to remember all of the various pros and cons that we
have individually discussed for each alternative. I suspect we need to put
together a side-by-side for each alternative so we can compare them._______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss