[[Invoke]] and implicit method calls

Allen Wirfs-Brock allen at wirfs-brock.com
Mon Sep 23 15:06:57 PDT 2013


On Sep 23, 2013, at 12:53 PM, Brendan Eich wrote:

> Allen Wirfs-Brock wrote:
>> I'm actually more concerned about inconsistent behavior for both internal (eg, valueOf) and user coded conditional calls.
> 
> Why? Lots of traps have to be implemented consistently, why is any invoke used for explicit method calls, but get+call for implicit conversions and user-scripted funarg extraction followed by later call, any different?

It's a matter of internal vs external consistency. The implementor of a Proxy handler needs to internally consistently implement the 'get', 'set', 'has', 'invoke', etc. traps in order to manifest an object that exhibits the normally expected object semantics. But there is no fool proof (I contend) way for the proxy implementor to achieve 'invoke' consistency with 'get+F.p.call

JS programmer have been trained that:

    obj.m(args)

is equivalent to:

   let f = obj.m;
   f.call(obj, args)

Sometimes they place additional code between the property access and the call.  That code might make the call conditional.  It might memorize f and obj in order to defer the call to an arbitrary point in the future.  

Prior to proxies this was always valid because the semantics of both, at the MOP level were: f = obj.[[Get]]("m"); f.[[Call]](obj,args).  But with proxies and [[Invoke]], this equivalent is no longer the case.  And with the current definition of F.p.call/apply there is nothing that the client code can do to reestablish the consistency.

This can be fixed, if obj.m(args) has the semantics of [[Get]]+[[InvokeFunction]] and F.p.call/apply also uses [[InvokeFunction]]  (noting that is the vast majority of cases [[InvokeFunction]] is exactly the same as [[Call]].  The JS programmers expected equivalence is maintained yet transparent proxies still have an opportunity to do forward of this values.

BTW, it also restore left to right evaluation of the call operator which regressed when the call operator was implemented using [[Invoke]].

Allen

 


More information about the es-discuss mailing list