<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div><div>On Aug 11, 2011, at 11:20 AM, Tom Van Cutsem wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div class="gmail_quote"><div>We've been over this at the March meeting. The consensus then was to settle on adding proxy as a last, optional argument to minimize impact on the API and recursion hazards.</div></div></blockquote><div><br></div>Right, and I agree putting proxy last is best. Not all agreed at the July meeting, but we may have to revisit, since we tried to get rid of proxy parameters altogether and thereby dodged the at end vs. at start issue.</div><div><br></div><div>Optional at end is best because most traps do not need to declare or use proxy, and furthermore, doing so (as one must if proxy comes first, except for single-parameter traps) raises the odds of mistakenly trapping through the proxy, creating runaway recursion.</div><div><br></div><div>But see below on receiver vs. proxy being a distinction without a difference for get and set.</div><div><br></div><div><br><blockquote type="cite"><div class="gmail_quote">
<div> </div><blockquote class="gmail_quote" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex; position: static; z-index: auto; ">Another alternative: the proxy could be "passed" via a data property on the handler. But the only use for the proxy reference is as a key in a weakmap, and if the handler references it, the handler could just as well be the key -- or the handler could simply hold the value associated by the weakmap.<br>

<br>
Conclusion: no rationale for adding a |proxy| parameter to all traps.<br></blockquote><div><br></div><div>There are a couple of motivating goals that may have been overlooked:</div><div><br></div><div>- as David pointed out, giving traps access to |proxy| also gives them access to the proxy's prototype, which is the enabler to turn getPropertyDescriptor and getPropertyNames into derived traps (cf. <<a href="http://wiki.ecmascript.org/doku.php?id=strawman:proxy_derived_traps">http://wiki.ecmascript.org/doku.php?id=strawman:proxy_derived_traps</a>>)</div></div></blockquote><div><br></div>That is a point we cleanly missed in the July meeting. Thanks for raising it. I hope we can discuss here in advance of the September meeting and strive for consensus.</div><div><br></div><div><br><blockquote type="cite"><div class="gmail_quote">
<div>- passing |proxy| as an argument to the derived traps allows a straightforward Javascript implementation of these traps to more closely reflect the actual default behavior. For instance, the following default |get| trap doesn't perform proper normalization for property descriptors:</div>
<div><br></div><div><div>  get: function(receiver, name) {</div><div>    var desc = this.getPropertyDescriptor(name); // desc is not normalized</div><div>    if (desc === undefined) { return undefined; }</div><div>    if ('value' in desc) {</div>
<div>      return desc.value;</div><div>    } else {</div><div>      var getter = desc.get;</div><div>      if (getter === undefined) { return undefined; }</div><div>      return getter.call(receiver);</div><div>    }</div>
<div>  },</div></div><div><br></div><div>While the following does:</div><div><br></div><div><div>  get: function(name, proxy) {</div><div>    var desc = Object.getPropertyDescriptor(proxy, name);</div><div>    if (desc === undefined) { return undefined; }</div>
<div>    if ('value' in desc) {</div><div>      return desc.value;</div><div>    } else {</div><div>      // note: no need to store desc.get into a local var, it's guaranteed</div><div>      // to be a data property on normalized property descriptors</div>
<div>      if (desc.get === undefined) { return undefined; }</div><div>      return desc.get.call(proxy);</div><div>    }</div><div>  },</div></div></div></blockquote><div><br></div>This seems to miss Sean's point that receiver is never other than the proxy for get and set. That follows from how native object [[Get]] works in ES5.</div><div><br></div><div><br></div><div><blockquote type="cite"><div class="gmail_quote"><div>This ties in with Kevin's request of being able to more accurately emulate default trap implementations in Javascript. This becomes important when writing wrappers for handler objects. I've come across this myself when working on the FixedHandler.</div></div></blockquote><div><br></div>I'm sympathetic to this point, but it doesn't require proxy trailing parameters for all traps -- just for some.</div><div><br></div><div><br><blockquote type="cite"><div class="gmail_quote">
<div>Were these goals considered? My feeling is that 2 less fundamental traps for the price of an optional |proxy| argument is a good deal. Also, given that |get| and |set| require the proxy/receiver argument anyway, passing the proxy to all traps makes for a more consistent API.</div></div></blockquote><br></div><div>If we put proxy last for get and set (replacing the leading receiver), we have a global consistency, but the "local" (w.r.t. underlying spec meta-methods, and base-level accessor functions) parameter order is oddly reversed: (name, proxy) instead of (proxy, name).</div><div><br></div><div>Consistency is never consistent or complete along all the dimensions. (h/t Goedel ;-)</div><div><br></div><div>/be</div><br></body></html>