On Mon, Apr 18, 2011 at 7:38 PM, David Bruant <[email protected]> wrote:
>> Thus, it seems to me that storing
>> anything in handlers besides existing traps is likely to cause future
>> headaches, and should be avoided.
> That's an excellent point. It sounds to be a safe idea to consider the
> handler as a namespace used for traps and that anything internal
> state-related should be captured.
> On the other hand, the main advantage of having "this.target" is that
> anyone can replace one trap with user JS code (to add a logger for
> instance) and have a way to access the target anyway. This would be
> impossible if the target was encapsulated and only accessible within
> built-in traps scopes. This advantage extends to any proxy library that
> would decide to expose its handler and partial internal state by
> exposing the partial state on the handler object.
None of this is an issue in the API I am proposing, since the state is
passed to each trap, not captured from the scope.
> As a side note, I'd like to say that, in my opinion, Proxy.Handler is a
> misleading name. It seems to imply that all handlers must/should/had
> better be a forwarding handler. I agree that it is certainly (one of)
> the most important use case, nevertheless, it is a restricting view of
> proxies which internal state has no reason to be reduced to a unique
> object. I would be more in favor of Proxy.ForwardingHandler, even if
> it's a bit long, I admit.
+1
Don't want to get too far off topic, but let me quickly dive into the
use case I alluded to above. If the proxy API can provide hooks that
map back to the ES object spec (traps map to internal object methods,
internal proxy state maps to internal object properties), then at some
point in the future objects can be executably spec'ed using the proxy
API. Each native constructor would have a handler which could even be
extended to support custom {Array,Function, etc} use cases. A
prerequisite for this would be primitives for each type for
"bootstrapping" purposes, such as records, dicts, tuples (+ a mutable
version), and primitive functions (i.e. only callable, no property
access).
> The JS code in harmony:proxy_defaulthandler is given for illustration
> purposes. All of this will be native code, so there should be no
> performance issues.
To get to that native code though you still need to take an extra step
up the inheritance chain since currently Proxy.Handler based handlers'
own properties hold proxy instance state as opposed to traps.
> Unless we consider generalizing "this.getTarget" to any use case by
> having a "this.getState" method (it's not a trap) on handlers. It would
> be used when there is a need to standardize the state of the proxy
> library (like the "target" for forwarding proxies). It would be reserved
> for proxy library authors who would like to expose their handlers with
> in mind the idea that people would change traps while still being able
> to access partial internal state. Actually a |this.state| weak map
> should be enough.
Here are the reasons why I believe the API I am proposing is superior
to a weak map implementation:
Code simplicity:
Can reference proxy state via |state| which is much shorter than
|this.state.get(proxy)| or |this.getState(proxy)|
No proxy-assocation code needed, so avoids the complexities of
"ForwardingPair" from your example.
Interoperability:
Standardized and abstract proxy-state association mechanism,
handlers do not need to coordinate how to do this.
Safety:
No "state" or "getState" property needed on handler, so completely
avoids trap namespace pollution
Less infinite recursion hazard as there is no need to use the proxy
reference to get to the state
Performance:
Avoid weak map lookups, derived traps and traps that call inherited
traps could have arbitrarily many of these as there is no mechanism to
pass state to traps
Also, if for any reason a given handler author did not want to use the
native proxy state support, preferring to implement this on their own
(such as by using WeakMap's), then we could potentially provide an opt
out mechanism of just not defining a "create" trap. For these
handlers, the implementation would not store any proxy state, and
could even omit the state argument when calling its traps (or just
pass undefined).
> This constraint would change the way forwarding proxies are created
> since the proxy object identity would need to be known before
> initializing the state.
This is not an issue in the API I am proposing, as it abstracts the
proxy-state association process via the "create" trap.
> Hence we would probably need to do something
> like: https://gist.github.com/926581
Here's what the same functionality would look like in the API I am proposing:
https://gist.github.com/929185
>> Conversely, with a share-able Proxy.Handler,
>> handler-per-instance use cases could be accommodated simply by
>> wrapping a singleton pattern around a handler.
> I did not understand this point. Could you provide an example or a code
> snippet?
Sure, in the API I'm proposing you could simply do...
let handlersOnlyProxy =
(function(){
let handler = new Proxy.ForwardingHandler;
// customize |handler| as desired here
return new (Proxy.Constructor(handler))(...createArgs);
})();
Thanks,
Sean Eagan
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss