Converting an existing object to a proxy

David Bruant david.bruant at labri.fr
Fri May 27 02:26:53 PDT 2011


Le 27/05/2011 04:13, Mark S. Miller a écrit :
> On Thu, May 26, 2011 at 5:04 PM, Cormac Flanagan <cormac at cs.ucsc.edu 
> <mailto:cormac at cs.ucsc.edu>> wrote:
>
>     [documenting/expanding some ideas briefly discussed at today's
>     meeting]
>
>     The current proxy proposal has a method to create a new proxy:
>
>     var proxy = Proxy.create(handler, proto);
>
>     We could extend this proposal to allow an existing object to be
>     converted to a proxy, via:
>
>     var proxy = Proxy.createFrom(object, handler, proto);
>
I am surprised by this proposal since a design goal of proxies was to 
not be able to turn existing objects into proxies.
4th "driving force" of the proxy proposal:
"security: avoid enabling arbitrary ES objects to be able to intercept 
the properties of another object"

The API itself (Proxy.create, Proxy.createFunction) seems to have been 
design with this in mind.


>
>     Here, the return value 'proxy' is the same address as the argument
>     'object'.
>     The original object thus becomes a proxy. Any state of the
>     original object
>     is discarded.
>
The notion of object "state" is not defined anywhere in the ES5 spec. 
What is your definition of an "object state" ?

>
>     This extension appears to support additional applications, such as
>     registering an observer on an existing object. The target object would
>     first be cloned, then the target object would be converted into a
>     proxy that
>     dispatches to the cloned object, but which also notifies observers
>     about
>     accesses/updates to the (now proxified) object.
>
Is this the only use case?
If so, would it rather make sense to provide a specific Object event API 
for existing objects? It would allow to observe accesses/updates without 
turning the object into a proxy with arbitrary handler methods.


>
>     There are a number of open issues relating to security etc:
>     In particular, what objects can be proxified in this way - perhaps not
>     frozen object,
>     or objects with non-configurable properties or with unique names.
>
>
> In today's meeting, I made two suggestions along these lines:
>
> * Given the current proxy semantics, we should allow this only if the 
> object-to-be-proxified is extensible and has no non-configurable own 
> properties.
> * We have on occasion discussed modifying the proxy proposal so that 
> individual properties could be fixed rather than just the proxy as a 
> whole. (Note: I am not in favor of such a change, but it could be done 
> soundly.) Given that this change to proxies were done, then we should 
> allow proxification only if the object-to-be-proxified is extensible, 
> period.
>
> In both cases, as you state, one effect of the operation is to remove 
> all configurable own properties from the object. In both cases, we can 
> adopt the rationale that the object-to-be-proxified could not have 
> taken any action inconsistent with it always having been a proxy.
>
> In both cases, we need the further restriction that it is a kind of 
> object that can be emulated by a proxy. Today, this is technically 
> only objects of [[Class]] "Object" or "Function", but we're talking 
> about relaxing that in any case.
>
>
>     A design goal is that for any object that could be proxified,
>     we can replace it with a proxy in a way that is semantically
>     transparent.
>
If you provide the ability to put any functions in the handler object, 
there in no such thing as "semantically transparent". The handler 
methods can do whatever they wants; they are functions. Moreover with an 
API like Proxy.createFrom(object, handler, proto), the handler methods 
would need some help to initialize their internal proxy state in order 
to align with the object passed as argument.

Maybe that what you were suggesting was to use a forwarding handler by 
default as handler and to put the handler argument as "this.target"?

Even in this case, if creating proxies, an external user of the same 
object has no guarantee whatsoever of seeing no semantic difference 
since, for instance, any handler trap could throw an error when called.

My very first (mis)understanding of proxies was that they were an object 
access/update event API and that the handler functions were nice event 
handler. They are not. They are much more powerful. They are not an 
/addition/ to regular internal object methods. They are a /replacement/ 
of it.

However, I agree that an object event API is a valid use case (I have 
actually had a need for that a couple of days ago), but I don't think it 
should be a proxy extension. In my opinion, it should be its own 
library/API. Maybe implementable/standardizable with proxies + "become" 
internal function (see slide 56 at [1]), but its own thing.

I would be much more in favor of something like:
----
Object.observe(o, observers);
----
Observers would be an object that looks like a proxy handler called on 
every object interactions, but wouldn't be able to interact with the 
object internal methods. It would just be an addition to internal 
methods rather than a replacement as it's the case with proxies.
There wouldn't be any restriction based on property attributes 
(enumerable, configurable, get, set...) or extensibility.
One question to discuss is to know if they should be called before or 
after (or one observer method for each?) internal calls.

Of course, if there is another use case than object access/update 
events, maybe that turning existing objects into proxies is a good idea, 
but if there isn't, I think that a specific API may be safer.

David

[1] http://www.slideshare.net/BrendanEich/metaprog-5303821?from=ss_embed
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20110527/6bbd8700/attachment-0001.html>


More information about the es-discuss mailing list