[Harmony proxies] Revisiting the forwarding proxy pattern

David Bruant david.bruant at labri.fr
Wed Mar 23 05:24:05 PDT 2011

Le 23/03/2011 11:03, Tom Van Cutsem a écrit :
> Hi David,
> As I understand it, the difference between the two patterns you
> presented is not so much in using a "full" forwarding handler versus
> an "own" forwarding handler, but in the fact that you pass different
> initial prototypes.
> Consider:
> var p = Proxy.create(fullForwardingHandler(target),
> Object.getPrototypeOf(target));
> Here, p and target also refer to the same prototype, it's orthogonal
> to specifying a "full" or "own" handler. Regardless of the kind of
> forwarding handler, inheritance will work just fine. I understand they
> work fine for different reasons, but is the difference really worth
> complicating the API by introducing two kinds of forwarding handlers?
Yes sorry, I was a bit drafty. The concerns are orthogonal, I agree. And
I forgot to say it, but my point was not to standardize the
ownForwardingHandler. I just used the notation as a shortcut.
I just wanted to discuss forwarding patterns when it comes to
inheritance because the current forwarding proxy doesn't discuss the
point and when it comes to fixing the proxy, surprising results could
arise (since inheritance changes because target and proxy prototypes
aren't the same object). Actually, if forwarding handlers were part of
the spec, would it make sense to fix them? shouldn't "return undefined;"
be the default fix trap?
(just the default, of course, the user can change it anytime)

> To be clear: I'm not opposed to your idea of distinguishing "own" from
> "full" forwarding handlers, but since the former can easily be defined
> in terms of the latter (delete all derived traps)
I would like to point out that "hasOwn" and "keys" are both own and
derived traps, so you can get from a full handler to a own handler by
removing all proto-climbing traps. Even if very close from each other,
"own"VS"proto-climbing" traps is different from "fundamental"VS"derived"
(even if getPrototypeNames and getPropertyDescriptor becomes derived)

> , the question becomes: should we standardize both or should we
> standardize just the minimum features, and allow developers to build
> other useful abstractions on top?
I do not have a definite opinion on the question yet, but since there is
already a strawman on maybe cutting the forwarding handler into two
I thought it would be a good idea to mention that other concerns may
affect the decision.

The concern that led my discussion was that the current proposal since
to consider that "forwarding proxy" has a unique definition which is
"forward everything to the target". So my question is: what is a
"forwarding proxy"?
- something forwarding all operations (own and inherited) to a target
object? (including the case where the target is itself a proxy)
- something forwarding own-layer operations and "delegating inheritance
to the engine"?
- something forwarding own-layer operations and refering to its own
prototype chain for inheritance?

I agree with you that the current definition allows all 3 to be
achieved. But since I have pointed different definitions of what a
forwarding proxy is, other people may think about it differently too.

I'm sorry for being a bit drafty sometimes. I think I should have
started with the following question:
What is a "forwarding proxy"? And my concerns aren't really about what
to spec yet, but rather to discuss on what different "forwarding proxy"
patterns people could expect and make sure the spec first address them
(it will certainly always be the case) and second, can the spec help out
if some cases are common or make sense.



> Cheers,
> Tom
> 2011/3/22 David Bruant <david.bruant at labri.fr
> <mailto:david.bruant at labri.fr>>
>     Hi,
>     I'd like to discuss forwarding proxy patterns. I'll call "full
>     handler"
>     a handler with all current traps and "own handler" a handler with just
>     the own properties layer traps.
>     The current forwarding proxy pattern is:
>     ---
>     var p = Proxy.create(fullForwardingHandler(target));
>     ---
>     Any interaction with p is delegated to target.
>     To visualize the prototype chain, we have:
>     -------
>     p --> null
>     target --> Object.getPrototypeOf(target) --> ... --> null
>     -------
>     Notably, all prototype-climbing calls are delegated to the target
>     prototype chain regardless of what p prototype is (I'll get back
>     to that
>     later)
>     We have seen a limitation of providing a full forwarding handler
>     systematically
>     (http://wiki.ecmascript.org/doku.php?id=strawman:derived_traps_forwarding_handler).
>     Regardless of what is decided on the strawman, some people may want to
>     only provide own traps. One "lighter" way to provide the same
>     forwarding
>     handler would be to do:
>     var p = Proxy.create(ownForwardingHandler(target),
>     Object.getPrototypeOf(target));
>     Which would visualize as:
>     ---
>     p -----------
>                 \
>     target --> Object.getPrototypeOf(target) --> ... --> null
>     ---
>     So at the own layer, p and target act exactly the same. They also act
>     the same when it comes to inheritance but not thanks to prototype
>     climbing traps. They do so because they natively delegate to the same
>     prototype object and use the default trap behavior. So, they are also
>     consistent with instanceof and Object.getPrototypeOf (and the
>     prototype
>     is correct when the proxy is fixed which is a consistent side-effect.
>     This doesn't happen with current full forwarding and null prototype).
>     Ok, now that we are able to be in sync only at the own layer, one
>     interesting pattern is the following
>     ---
>     p --> Object.getPrototypeOf(p) --> ... --> null
>     target --> Object.getPrototypeOf(target) --> ... --> null
>     ---
>     with p and target in sync at the own layer. For all own operations, p
>     would forward to target, however, for all proto-climbing operations p
>     would use its own properties. Actually, this works without any effort
>     with the OwnForwardingHandler since its default derived traps delegate
>     to the correct prototype by default.
>     This pattern could be used for a new prototype inheritance pattern
>     where
>     o1 could inherit from p, o2 from target. They would both feel they
>     inherit from the same object (since p and target are in sync)
>     while, one
>     step further inheriting from completely different objects.
>     All of this is just a discussion on the forwarding proxy pattern.
>     But I
>     think it was worth pointing the potential limitations of how this
>     pattern is currently presented (limitations which are different
>     from the
>     one previously noticed which led to
>     strawman:derived_traps_forwarding_handler).
>     David
>     _______________________________________________
>     es-discuss mailing list
>     es-discuss at mozilla.org <mailto:es-discuss at mozilla.org>
>     https://mail.mozilla.org/listinfo/es-discuss

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20110323/269beb76/attachment-0001.html>

More information about the es-discuss mailing list