<div class="gmail_quote">2012/11/12 Allen Wirfs-Brock <span dir="ltr"><<a href="mailto:allen@wirfs-brock.com" target="_blank">allen@wirfs-brock.com</a>></span><br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div style="word-wrap:break-word"><br></div></blockquote><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div><div>I think the root issue relates to polymorphic dispatch of the internal methods and the transparent forwarding of unhanded traps to the Proxy target object.</div>
<div><br></div><div>Every-time the spec. calls an internal method it is implicitly doing a polymorphic dispatch using that object's "handler"  as the "type". (we can think of ordinary objects as having a intrinsic handler that dispatches to the ordinary implementation of the internal methods).  The specification's implementation of the ordinary internal methods generally assumes that the "this object" that the internal method is operating upon is the object that did the original polymorphic dispatch (remember, no inheritance of internal methods).  This means that within those internal method algorithms it can be assume that a self-calll to an internal method will dispatch to the same ordinary handler.  [[HasProperty]] can self-call [[HasOwnProperty]] safely assuming that it will be using the same two coordinated implementation. </div>
<div><br></div><div>However, if the ordinary [[HasProperty]] is being evaluated on a Proxy target because it was forwarded by the Proxy [[HasProperty]], its "this object" is the target, not the proxy and so its call to [[HasOwnProperty]] dispatches via the target and not the proxy.  We get an answer that is consistent, relative to the target object but not consistent relative to the proxy-based object that [[HasProperty]] was originally invoked upon.</div>
</div></div></blockquote><div><br></div><div>Yes, this is a good summary of the issue, which I'll call the "forwarding-footgun". But let me make a further distinction as there are two ways in which an inconsistency between fundamental and derived traps can occur:</div>
<div><br></div><div><div>1) a proxy handler implements a derived trap, but forgets to implement the associated fundamental trap.</div></div><div>2) a proxy handler implements a fundamental trap, but forgets to implement the associated derived traps.</div>
<div><br></div><div>1) is what you described above.</div><div><br></div><div>2) can be solved by having the handler subclass the standard Handler (see <<a href="http://wiki.ecmascript.org/doku.php?id=harmony:virtual_object_api">http://wiki.ecmascript.org/doku.php?id=harmony:virtual_object_api</a>>): by "subclassing" the Handler and overriding some fundamental traps, one is guaranteed that any derived traps will automatically call the overridden fundamental trap.</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div><div>What we have is a situation that is very similar to that which requires the inclusion of a receiver argument in [[GetP]]/[[SetP]] calls, but along a different dimension.  </div>
</div></div></blockquote><div><br></div><div>I don't yet see how the "receiver" argument is similar to fusing derived and fundamental traps into a single trap.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div style="word-wrap:break-word"><div class="im"><blockquote type="cite"><div class="gmail_quote"><div><br></div><div>Note that the "invariant enforcement" technique still doesn't allow a proxy with non-config/non-extensibility invariants to lie about its own properties. There are post-condition assertions on both "getOwnPropertyDescriptor" and "hasOwn" that ensure this. More generally: as long as a proxy p doesn't answer "true" to Object.isFrozen(p), its behavior can be arbitrary. Only when some sensible invariants are established on the proxy's target is the proxy's behavior restrained.</div>
</div></blockquote><div><br></div></div><div>Yes, and the concern is that most Proxy uses will not be in the context of  frozen object so in most cases none of the "invariant  enforcement" will not help with this problem.</div>
</div></blockquote><div><br></div><div>I may have been misunderstood: I didn't claim that invariant enforcement solves the forwarding-footgun, only that the inconsistent behavior caused by the forwarding-footgun is not in itself an issue. It doesn't invalidate code that relies on invariants.</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div>I've never been a big fan of dynamic invariant enforcement for proxies and I'm still not.  I am concerned that the current interfaces and factoring of derived/fundamental along with the target forwarding semantics is a footgun that is going to led to difficult to identify bugs.</div>
</div></blockquote><div><br></div><div>Hold on: the invariant enforcement mechanism to me feels entirely independent of the derived/fundamental trap distinction. We still need invariant enforcement even if we fuse all derived traps into the fundamentals (or get rid of the derived traps entirely).</div>
<div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div><div>For now, I can spec. the current factoring I think we should continue to look at it from this perspective and see if we can minimize the size of the footgun.  </div>
</div></div></blockquote><div><br></div><div>I agree we should keep the options open. As I mentioned above, the 'Handler' standard object, when used appropriately, can remedy one half of the forwarding-footgun.</div>
<div><br></div><div>Cheers,</div><div>Tom</div></div>