On Sep 23, 2013, at 3:50 PM, Brendan Eich wrote:
>> Allen Wirfs-Brock <mailto:[email protected]>
>> September 23, 2013 3:06 PM
>>
>> 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
>
> Now it depends on what you mean by "fool proof".
Takes into account dynamically added properties (particularly inherited),
[[Prototype]] mutation, subclassing,etc.
>>
>> 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.
>
> Vacuously true, and why we resisted invoke.
>
>> And with the current definition of F.p.call/apply there is nothing that the
>> client code can do to reestablish the consistency.
>
> To use either F.p.call or .apply, you must do obj.[[Get]]("m"). For function
> objects, [[Call]] is well-specified and what F.p.{c,a} use.
>
> For proxies, we need something akin to [[Call]]. Is that the point of
> [[InvokeFunction]]?
Exactly. [[InvokeFunction]] is the Proxy this aware version of [[Call]].
Rather than obj.m(args) turning into obj.[[Invoke]]("m",args) where [[Invoke]]
internally does [[Get]]+[[Call]] I'm suggesting that turns into:
f = obj.[[Get]]("m")
obj.[[InvokeFunction]](f,args)
(I've left out the extra Receiver parameters that [[Get]], [[Invoke]], and
[[InvokeFunction]] all can accept.)
[[Invoke]] would go away and the call operator would simply be implemented as
[[Get]]+[[InvokeFunction]].
In addition, F.p.call/apply would also use [[InvokeFunction]] instead of
[[Call]] whenever the passed this value is a Proxy.
>
>> 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]].
>
> Ok, but then Tom asked whether function objects targeted by direct proxies
> having their [[Call]] overridden was a problem?
Ultimately [[InvokeFunction]] performs a [[Call]] on some function object.
[[InvokeFunction]] doesn't replace [[Call]] as the primitive function
invocation hook.
>
>> 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]].
>
> If you can rename [[InvokeFunction]] to [[Invoke]] so my head stops
> exploding, I think we have a deal. But need Tom on board.
Yes, I want to do that renaming. But for now we are still talking about the
differences between [[Invoke]] and [[InvokeFunction]] so I can't do the
renaming yet. But a key point is that only one of them ends up in the spec.
and whichever it is will be named [[Invoke]].
Allen
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss