July TC39 meeting notes, day 1

Tom Van Cutsem tomvc.be at gmail.com
Thu Aug 11 11:20:05 PDT 2011

2011/7/28 Brendan Eich <brendan at mozilla.com>

> == Handler access to proxies ==
> Proxy handler traps need to receive the proxy as a parameter: first, or
> last?
> Last allows trap implementors to leave |proxy| off. It's also a compatible
> extension to the proposal and its prototype implementations. Putting |proxy|
> last may also steer implementors away from touching proxy, reducing the bugs
> where you infinitely diverge.
> First is more normal-order (proxy, name) and some find it more
> aesthetically pleasing.

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.

> 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.
> Conclusion: no rationale for adding a |proxy| parameter to all traps.

There are a couple of motivating goals that may have been overlooked:

- 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. <

- 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:

  get: function(receiver, name) {
    var desc = this.getPropertyDescriptor(name); // desc is not normalized
    if (desc === undefined) { return undefined; }
    if ('value' in desc) {
      return desc.value;
    } else {
      var getter = desc.get;
      if (getter === undefined) { return undefined; }
      return getter.call(receiver);

While the following does:

  get: function(name, proxy) {
    var desc = Object.getPropertyDescriptor(proxy, name);
    if (desc === undefined) { return undefined; }
    if ('value' in desc) {
      return desc.value;
    } else {
      // note: no need to store desc.get into a local var, it's guaranteed
      // to be a data property on normalized property descriptors
      if (desc.get === undefined) { return undefined; }
      return desc.get.call(proxy);

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.

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.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20110811/10ee344a/attachment.html>

More information about the es-discuss mailing list