> I don't think the traps take that many arguments that they merit a
> keyword-arguments API.

Agreed, the quantity of arguments, even if one were to be added, is
manageable without keyword arguments.  However, if any arguments need
to be selectively added to certain traps in the future, then the proxy
would no longer be the last argument to all traps, which could make
the parameter lists difficult to remember.

> The cached getPrototypeOf trap behavior falls prone to the same source of
> confusion that caused us to steer away from defining call and construct as
> separate traps (cf. the other discussion thread on the uniform proxy API).

Note that it is not the "getPrototypeOf" trap that is cached (as I was
proposing for the "call" and "construct" trap in the other thread),
but rather its return value, and that the only reason for that is to
match current (and AFAIK future) behavior that an object's
[[Prototype]] is immutable, in order to not break proxy transparency.
If mutable prototypes were allowed in the future, a "getPrototypeOf"
trap would be needed, but would be, at that point, very difficult to
add since the prototype argument would probably want to be removed
from Proxy.create / Proxy.createFunction, which would involve breaking
existing code.

> I agree with David that the use cases of shared proxy handlers are not
> sufficiently explored to merit the addition of customizable "internal proxy
> state".

Agreed, which is why I took some time to start exploring it further
:).  Here are my findings up to this point...

Storing proxy instance state directly within handlers:
==============================================================

Trap namespace pollution:

The default handler, Proxy.Handler, stores proxy instance state
directly in each handler's "target" property.  Notice that this
immediately prevents a "target" trap from being added in the future,
which of course isn't so bad as it is an unlikely future trap name.
However, as soon as proxies are standardized and start to be used, if
user defined proxy instance state is allowed (and even strongly
encouraged by implementing Proxy.Handler this way) to be stored in
handlers, the entire remainder of the trap namespace will be open to
pollution, and thus prevent *any* new traps from being added in the
future without the likelihood of breaking existing code.  Beyond proxy
instance state, users may also add helper methods including perceived
"missing" traps, which may directly correlate to traps that would be
wanted to be added in the future.  Thus, it seems to me that storing
anything in handlers besides existing traps is likely to cause future
headaches, and should be avoided.

Extra inheritance chain step when resolving traps:

Just a minor observation that, if proxy instance state is stored in
the own properties of a handler, and traps are inherited (as with
Proxy.Handler created handlers), then all traps are at least one step
up the inheritance chain.  With shared handlers, traps would be on
average about one less step up the inheritance chain.  I realize
prototype chain walking is highly optimized, but proxies allow for
transparent non-optimized user defined inheritance.

Existing default handler useless to shared handlers:
==============================================================

The existing Proxy.Handler.prototype and all of its traps are useless
to a shared handler because they all have a reference to
"this.target".  This could be resolved by replacing these references
with "this.getTarget(proxy)", but that again starts to pollute the
trap namespace.  Conversely, with a share-able Proxy.Handler,
handler-per-instance use cases could be accommodated simply by
wrapping a singleton pattern around a handler.


Thanks,
Sean Eagan
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to