Proxies with State
There are two problems with this initial idea.
- One downside is that there are problems when attempting to proxify a proxy.
- Second, accesses to Proxy.untrappedGetOwnPropertyDescriptor(proxy, name), etc. are verbose and ugly.
A possible workaround is
- each object has an ordered list of proxies (allowing multiple proxies on an object)
- each handler is passes a 'backing object' o -- essentially a temporary proxy that provides convenient access (via o.x etc) to the state of the underlying object, or to the 'view' of that object as provided by the next proxy in the proxy chain.
More complex that the current proxy proposal, certainly, but potentially with a smaller space footprint.
On May 31, 2011, at 4:57 PM, Cormac Flanagan wrote:
One possible concern with proxies is the overhead of separate proxy and handler objects, and trap methods that likely close over a backing object.
Or weakmap proxies to backing objects.
This concern would be exacerbated in the case of value proxies, where we might want millions of complex number proxies, and also came up in the discussion of the Observer use case last week.
The strawman at strawman:value_proxies addresses this by specifying a Proxy.createValue function taking a strawman:binary_data StructType descriptor as its last argument.
This is a targeted API, not for all use-cases but specifically for the one you cite: primitive values with efficiently packed structured binary data representations and operator methods.
It seems it would be nice to allow proxy objects to have some state.
I think Proxies hit a sweet spot by isolating handler and proxy apart from the introduction in Proxy.create{,Function}. Trying to overload them to handle state (especially efficient, co-allocated binary data) is too much.
Le 01/06/2011 01:57, Cormac Flanagan a écrit :
One possible concern with proxies is the overhead of separate proxy and handler objects, and trap methods that likely close over a backing object. This concern would be exacerbated in the case of value proxies, where we might want millions of complex number proxies, and also came up in the discussion of the Observer use case last week.
It seems it would be nice to allow proxy objects to have some state. Since accesses to the proxy would trap to the handler, we need an alternative way for the handler to access the proxy state, perhaps Proxy.untrappedGetOwnPropertyDescriptor(proxy, name), etc.
In a previous discussion [1] (that I forked at [2]), we've been discussing how proxy state could be handled to be made available. One interesting idea (actually it was in Tom and Mark proposal [3] all along) was that the handler could have all methods in its prototype and its state at the "own properties level". Providing a direct access to this own level could be a way to achieve what you want.
I am under the impression that your understanding of "state" is that it is a (regular) object. It is not necessarily. Proxies provide an abstraction of something that looks like an object but may not behave like so. See my experiment at [4]. The proxy state is not an object in the ECMAScript sense. It's in the proxy core design to trap operations without the ability to "bypass" the traps. However, as said above, you, as a library writer, can provide access to your internal proxy state. But it must be your decision, not something proxy users should be able to do natively.
This might allow us to proxify existing objects to attach an Observer without introducing much additional, per-object overhead.
As said in the previous thread about Observers, proxies may not be the right thing to implement them (even though it's perfectly possible). A dedicated API would be much more efficient (in terms of performance) and relevant in my opinion. There wouldn't be any overhead.
David
[1] esdiscuss/2011-April/013725 [2] esdiscuss/2011-April/013909 [3] harmony:proxy_defaulthandler [4] DavidBruant/PropStackObjects
Here's one possible implementation strategy for proxies that does not require any changes to the language semantics yet still could deal with the space overhead concern of having separate proxy + handler objects. This idea is very preliminary, and may have holes...
Normally, a call to Proxy.create(handler) creates a proxy object that has a reference to the handler, resulting in two objects (the proxy and the handler), both of which may be long-lived.
Alternatively, we could
- copy the bits of the handler state into the proxy object
- convert the original handler in to a "forwarding object" that accesses/updates the corresponding bits of the proxy object
- two forwarding objects are considered equal if the forward to the same proxy objects. This change in representation should not result in observably different behavior.
Once this representation change is accomplished, the forwarding objects have no state or identity. So there is no need for the proxy to maintain a reference to the handler forwarding object - it can instead recreate an equivalent forwarding object each time a proxy trap is called. These reallocated forwarding objects are likely to be short-lived, and live only for the duration of the trap call.
Clearly, there is some additional implementation complexity here, but something like this might allow us to represent a proxy/handler pair using only one long-lived object, rather than two, while avoiding any additional language complexity.
One possible concern with proxies is the overhead of separate proxy and handler objects, and trap methods that likely close over a backing object. This concern would be exacerbated in the case of value proxies, where we might want millions of complex number proxies, and also came up in the discussion of the Observer use case last week.
It seems it would be nice to allow proxy objects to have some state. Since accesses to the proxy would trap to the handler, we need an alternative way for the handler to access the proxy state, perhaps Proxy.untrappedGetOwnPropertyDescriptor(proxy, name), etc.
This might allow us to proxify existing objects to attach an Observer without introducing much additional, per-object overhead.