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

Tom Van Cutsem tomvc.be at gmail.com
Wed Dec 19 02:01:29 PST 2012


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

> I think it has to be A, for consistency with [[Call]].  Note that when
> [[Call]] is directly forwarded to the target, the this value is set to
> target. It wouldn't be self-consistent if directly forwarded foo.access and
> foo.method() invocations used different this values.
>

Hmm, in the current proxies draft spec, the default [[Call]] behavior does
not modify the thisBinding upon forwarding, so:

var that = {}
var proxy = Proxy(function() { return this === that; }, {}) // default
"apply" trap
proxy.call(that) // true

It would be very strange for |this| to be bound to the function object
itself. That typically does not make sense.

I assume that by "proxy is the initial receiver", you mean that for a
> [[SetP]]/[[GetP]] invocation that  SameValue(O,Receiver) is true.  If so,
> that also seems right to me.  In writjing various
> [[SetP]]/[[GetP]]/equivalent proxy traps, this test is one I've found that
> I routine have  to make.  It basically distinguished between the initial
> application of the operation and  a proto climbing (or other similar
> delegating) application.
>

Yes, that is what I meant.

I'm actually surprised that I didn't notice this wrong receiver issue when
> I incorporated Proxy exotics into the ES6 spec. as I spend a lot of time
> thinking about what was the correct this value to forward in various
> situations.  I'm not blissfully happy with the current forwarding model,
> but I think it is ok as long as we make sure it is completely self
> consistent.  The situations I was concerned with are similar for [[Call]]
> when it is directly forward.  If prox.foo() is forwarded so that the foo
> method is invoked with the proxy's target as the this value then any
> this.bar() calls within the foo method dispatches through the target rather
> than prox.  From an OO delegation perspective this feels wrong.  However,
> it feels ok if you think of direct forward not as a form of object
> delegation but rather redirection to a completely oindependent object(the
> target).  In that case, it is very important that all forwarding
> consistently use the target as the receiver.
>

Yes, the behavior here is odd:
for "direct" method invocations such as proxy.foo(), we want pure
forwarding behavior, with |this| bound to the target in the forwarded call.
for "delegated" method invocations such as Object.create(proxy).foo(),
prototype-based inheritance dictates that inside the forwarded foo(),
|this| should be bound to the child object.

It's because we are mixing Lieberman-style delegation with plain
forwarding. The above behavior is the best compromise I can come up with.

If you really want to [[Call]] a target method with the proxy as the this
> value or do the equivalent for [[SetP]]//[[GetP]] you can do it by
> providing a hander that does what you want rather than depending upon
> direct forwarding.
>

Yes. It's important to point out that we're only talking about the default
behavior here. There are many policy decisions a proxy author can make. We
have to choose one as the default. I think we're in agreement that for
property access/assignment, the default should be to rebind |this| to the
target for "direct" accesses, and to leave |this| unmodified for
"delegated" accesses.

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


More information about the es-discuss mailing list