[[Invoke]] and implicit method calls

Allen Wirfs-Brock allen at wirfs-brock.com
Tue Sep 10 09:04:35 PDT 2013


On Sep 10, 2013, at 4:14 AM, Brendan Eich wrote:

> I think we should preserve double-lifting via one trap in the meta-handler. No has-before-invoke. Allen?

Well, then we loose the flexibility for a meta-level proxy to control the this-binding used when invoking proxy traps on it. Perhaps this isn't an issue for meta-level proxies, but it was the primary motivation for introducing [[Invoke]].

Also, see below...

> 
> /be
> 
>> Tom Van Cutsem <mailto:tomvc.be at gmail.com>
>> September 10, 2013 3:58 AM
>> +1 for refactoring to use [[Invoke]] for most of these.
>> 
>> One reservation about the use of [[Invoke]] to call proxy traps (i.e. functions on handler objects): the alternative pattern of first probing with HasProperty destroys the "double lifting" pattern, which depends on the proxy only ever performing 1 type of operation (a property access) on its handler.
>> 
>> (double lifting is a pattern whereby the handler object is itself a proxy. It allows you to write very generic proxies that only need to implement a single "get" trap. See <http://soft.vub.ac.be/~tvcutsem/invokedynamic/assets/proxies.pdf <http://soft.vub.ac.be/%7Etvcutsem/invokedynamic/assets/proxies.pdf>> section 4.5 for details.)
>> 
>> If we refactor to use [[HasProperty]] + [[Invoke]] to call traps, the double lifting pattern requires implementing both the has() trap and the get() trap. Not fatal, but I just want to point it out.

Another possibility is to do [[Get]] + [[Invoke]]?  However,  in most cases would do two [[Get]]'s of the method property and there is the possibility that they would produce inconsistent results. But that's also true of [[HasProperty]]+[[Invoke]]

I beginning to think that the best solution is to add a [[InvokeFunction]] internal method/trap.  It's just like [[Invoke]] except that it assumes that the [[Get]] step has already been performed (the function is passed in rather than the property key).  This still allows the handler to intercede in mapping the this value or other arguments.  In fact, perhaps, we could simply replace [[Invoke]] with [[InvokeFunction]] and turn all the current [[Invoke]] calls into [[Get]]+[[InvokeFunction]].  This would also address the conditional [[Invoke]] issues being discussed in this thread.

Allen







>> 
>> Regards,
>> Tom
>> 
>> 
>> 
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>> Jason Orendorff <mailto:jason.orendorff at gmail.com>
>> September 9, 2013 4:23 PM
>> 
>> A lot more can be found by searching for [[Call]]:
>> - the call to @@toPrimitive from ToPrimitive (in 7.1.1)
>> - the call to @@hasInstance from instanceofOperator (in 12.8.1)
>> - the call to .toISOString from Date.prototype.toJSON (in 20.3.4.37)
>> - the call to .join from Array.prototype.toString (in 22.1.3.27)
>> - the call to .set from the Map constructor (in 23.1.1.1)
>> - the call to .add from the Set constructor (in 23.2.1.1)
>> 
>> and at that point I stopped looking.
>> 
>> -j
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>> 
>> Allen Wirfs-Brock <mailto:allen at wirfs-brock.com>
>> September 9, 2013 2:50 PM
>> On Sep 9, 2013, at 2:37 PM, Jason Orendorff wrote:
>> 
>>> There are some places in the spec where we might use [[Invoke]], but don't:
>>> 
>>> - implicit .toString() and .valueOf() calls
>>>  (except Object.prototype.toLocaleString)
>>> - implicit .toJSON() calls
>>> - calls to Proxy handler methods
>>> 
>>> This seems unfortunate. Proxies with default handlers will work in
>>> most places, thanks to the default [[Invoke]] trap, but not in ("" +
>>> proxyObject) etc.
>>> 
>>> Is this still likely to change?
>> 
>> I'll take a look at it.  My first reaction is that this sounds like a good idea.
>> 
>>> The apparent reason [[Invoke]] is not used in these places is that
>>> they all do a [[Get]] first and check whether the property has a
>>> callable value.
>> 
>> Actually, I don't think even considered those uses when I added [[Invoke]].
>> 
>> 
>> Allen
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>> 
>> Jason Orendorff <mailto:jason.orendorff at gmail.com>
>> September 9, 2013 2:37 PM
>> There are some places in the spec where we might use [[Invoke]], but don't:
>> 
>> - implicit .toString() and .valueOf() calls
>> (except Object.prototype.toLocaleString)
>> - implicit .toJSON() calls
>> - calls to Proxy handler methods
>> 
>> This seems unfortunate. Proxies with default handlers will work in
>> most places, thanks to the default [[Invoke]] trap, but not in ("" +
>> proxyObject) etc.
>> 
>> Is this still likely to change?
>> 
>> The apparent reason [[Invoke]] is not used in these places is that
>> they all do a [[Get]] first and check whether the property has a
>> callable value. But in the algorithm for yield*, in 14.4.1.2, we have
>> a similar check-before-calling situation, implemented using a
>> different idiom:
>> 
>> (step 4.d.viii in the last algorithm of 14.4.1.2)
>> 
>> Having a [[GetMethod]] hook instead of an [[Invoke]] hook might make
>> it easier to use consistently everywhere.
>> 
>> -j
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>> 
> 



More information about the es-discuss mailing list