Le 20/04/2011 17:09, Tom Van Cutsem a écrit :
>
> 2011/4/18 Sean Eagan <seaneag...@gmail.com <mailto:seaneag...@gmail.com>>
>  
>
>     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.
>
>
> True, the existing Proxy.Handler API was not designed to support
> shared handlers. I'm not sure whether that is a problem that needs to
> be addressed.
>
> Overall, your proposed API is consistent and does support shared
> handlers well. The question remains whether the added complexity (i.e.
> Proxy.Constructor) is worth it.
I think that this thread has brought a use case that is different from
shared handlers and that is the idea of exposing partial internal proxy
state in order to allow programmers to dynamically change a few traps
while being able to interact (or rather "be consistent") with other
traps (which could be native as in the ForwardingHandler example or
not). Hence the thread title change.

Currently, the Handler constructor creates an object. At the own layer
is the state of the proxy ("target" property). On the prototype are the
traps.
Given a handler, if I want to change a trap, I can redefine it at the
own layer and shadowing the prototype method with the same name. But
within my trap, how can I access the proxy state? Well, by using
"this.target". So if I want to redefine the set trap, I can do the
following:
----
var h = new Proxy.Handler({});

h.set = function(rec, name, val, proxy){
    var target = this.target; // I am able to retrieve "internal" proxy
state
    /* ... */
}
----
However, this method doesn't scale well. If a proxy has several internal
properties, is it going to expose all of them with one different name
each time? My idea is to take the convention to have a unique "state"
property. This convention could be standardized by saying that the
"state" property name is reserved for people to use (no obligation
whatsoever) and warn them that any other property name could be used in
the future, so they should be careful of handler property namespace
pollution.
Now that I think about it, in the case where proxy traps are shared in
the prototype and that there is no shared handler but rather a handler
per proxy, then the state can safely be stored at the handler object own
layer. This technique won't work if we want actual shared handlers.

Sean Eagan is taking another approach that will be compatible with
shared handlers.

I'd like to say a few more words on dynamic trap change. I see two cases
with different constraints:
- Decorator pattern (logger, etc.)
In that case, redefining the trap by wrapping the default method and
decorate it should be enough. No need to access the internal proxy
state. Passing arguments and this binding should be enough. This is what
Sean did l.14-17 (https://gist.github.com/929185). He didn't extract the
actual internal state to manipulate it.
- Actual internal state manipulation
Here is the case where there is a need to access the internal proxy
state. For instance, if we want to log the result of
Object.isExtensible(target), then we need access to the target. This is
the class of use cases we are targetting here in my opinion.

> In terms of object allocation, I don't see the benefit of shared
> handlers as opposed to the current design:
> - In typical uses of the current design, for N targets, one allocates
> N virtually-empty proxies, N handler objects that contain per-instance
> state (e.g. |target|), and 1 shared handler prototype that typically
> contains all the traps.
> - In the shared-handler design, for N targets, one allocates N
> proxies, each storing a reference to each of N state objects (the
> return values from your |create| trap) and 1 shared state-free handler
> object.
Just for the sake of completeness, there is another case that hasn't
been described:
- N targets, N handler objects with new traps (new function objects
identities) for each handler object. This is the nothing-shared case.
This was the case I wanted to avoid when first thinking about shared
handlers. But I agree that the shared prototype idea is a very good
solution to that problem too. Your comparison actually convinced me that
sharing methods on the prototype and storing state at the handler object
own layer could be the way to go.

Cheers,
David
_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to