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

Tom Van Cutsem tomvc.be at gmail.com
Thu Dec 20 12:07:58 PST 2012


2012/12/20 Allen Wirfs-Brock <allen at wirfs-brock.com>

>
> On Dec 20, 2012, at 2:21 AM, Tom Van Cutsem wrote:
>
> If target.baz is a writable data property
> proxy.baz = 42 will eventually call Object.defineProperty(proxy, 'baz',
> {value:42})
> (and *not* Object.defineProperty(proxy, 'baz',
> {value:42,enumerable:true,writable:true,configurable:true}) as it did
> previously)
> This behavior is consistent with the method and accessor case: in all
> cases, the target delegates back to the proxy.
>
>
> This is actually essential to maintaining ES5 default semantics because
> {value:42} and {value: 42, enumerable:true,writable:true,configurable:true}
> have quite different meanings to the ordinary [[DefineOwnProperty]].
>

Indeed. And this is what caused the issue I reported in the OP.


>
> It is equally important that if target.baz does not exist that
> [[DefineOwnProperty]] is called on proxy with with the full  {value:
> 42, enumerable:true,writable:true,configurable:true} descriptor to ensure
> that the new property gets created using the "crated by assignment"
> attributes rather than the [[DefineOwnProperty]] defaults.
>

Yes, this is the case.

> One thing that I learned from all this is that it's simpler to think of
> the proxy as *delegating* (as opposed to forwarding) to its target by
> default. And under the semantics of invoke = get + apply, that is actually
> the simplest option.
>
>
> Yes, this is the best way I have found to think about them and I've been
> patiently waiting for you to see the light :-)   However, a corollary is
> that most  internal method calls within derived internal methods/traps need
> to delegate back to the original "receiver".  In some cases, we don't
> provide the original receiver as an extra argument, so it isn't available
> to do this.
>
> A quick scan of the ordinary internal method suggests that we may have
> this problem for [[Delete]], [[Enumerate]], [[Keys]], and
> [[GetOwnProertyKeys]].
>
> More generally, I would argue that all Proxy traps (and the corresponding
> Reflect functions) potentially need access to the original "receiver".  We
> don't know what somebody is going to do in such traps and they well need to
> call back to the original receiver for the same sort of consistency issues
> we have encountered with  [[SetP]].  this is particularly apparent if you
> think multiple levels of proxies chained through their target slots.
>

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.

Cheers,
Tom
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20121220/7c59c0d2/attachment.html>


More information about the es-discuss mailing list