Proxies: wrong "receiver" used in default "set" trap

Allen Wirfs-Brock allen at wirfs-brock.com
Fri Dec 21 08:54:34 PST 2012


On Dec 21, 2012, at 5:15 AM, Andreas Rossberg wrote:

> On 21 December 2012 03:00, Allen Wirfs-Brock <allen at wirfs-brock.com> wrote:
> 
> On Dec 20, 2012, at 12:07 PM, Tom Van Cutsem wrote:
>> I'm not sure I follow. In my understanding, the original Receiver is only needed for traps that involve prototype-chain walking and are thus |this|-sensitive. That would be just [[GetP]] and [[SetP]]. One can make the case (David has done so in the past) for [[HasProperty]] and [[Enumerate]] since they also walk the proto-chain, although it's not strictly necessary as the language currently does not make these operations |this|-sensitive.
> 
> The proxy target delegation chain is also this-sensitive when it invokes internal methods.  For example, in the revised [[SetP]] step 5 it is important  that the [[DefineOwnProperty]] calls (in 5.e..ii and indirectly in 5.f.i are made on Receiver and not O.
> 
> [...]
> If you step back a bit and just think about the concepts of Lieberman delegation and self-calls without worry about the specific of the proxies or the ES MOP I think you will come to see that delegated target calls naturally should self-call back to the original object.  That's what Lieberman style delegation is all about.
> 
> While I agree with your line of reasoning in principle, it seems that your proposed change imposes substantial complications on implementations. While simple forwarding of missing traps allows reusing existing code for performing the respective operations (including all sorts of optimisations and special-casing), it seems to me that a delegation semantics requires duplicating much of the core functionality of objects to correctly deal with the rare case where the object is a proxy target.
> 
> So far, proxies where mainly a special case implementations could distinguish early on, and not care about them in the rest of the logic for a given operation (except where you had to do proto climbing). With delegation semantics everywhere, that is no longer the case, and everything becomes intertwined.
> 
> If a VM is no longer able to reuse existing optimisations easily for the proxy case, my guess is that such a semantics would make direct proxies significantly slower in practice. I, for one, would not look forward to implementing the change, let alone optimising it. :)
> 
> That said, I normally stand on the side of a better semantics. But we should be aware of the likely implications in this case.
> 
> /Andreas
> 

yes, I understand and share your concerns.  I don't yet have any actual proposed changes that I want to put on the table. For now, I'm only trying to understand the conceptual issues and why they seem to cause problems in certain cases.

But here is a sketch, of a possible approach that might work:

We've already parameterized the most important internal methods with a Receiver parameter.  Their only appear to be two or three others (for example, [[Delete]]) that, conceptually, should be making self-calls back to a Receiver and they don't seem to be commonly used in perf critical situations, so we probably could add that parameter without a great impact.

However, any user written "internal method" (in other words, any trap) might want to make self-calls.   But maybe that's not so bad because the only way (other than extending the implementation or via a host object API) to introduce such arbitrary, self-call dependent behaviors is via a Proxy.  Also, all delegation from a trap handler to the target object should be done via a Reflect.* call. So,  all Proxy trap signatures and all Reflect.* functions would need to include a Receiver parameter.

The Proxy internal methods would then be responsible for passing the Receiver parameter (the Proxy) to the traps and the Reflect.* functions would be responsible for propagating the Receiver parameter its target is a also a Proxy.

This would see to pretty much isolate the special case delegation semantics to situations that actually use a handler and the Reflect functions.

Allen
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20121221/fe988330/attachment-0001.html>


More information about the es-discuss mailing list