[Harmony proxies][Terminology] "fixed" state of a proxy

# David Bruant (15 years ago)

I would like to discuss the terminology of the proposal and the two states of a proxy: trapping or fixed. In order to discuss, here is a little example:

var o = {}; var p = Proxy.create( forwardingHandler(o) ); p.a = 1; o.b = 2; p.c = 3; o.d = 4; /* For all x in [a,b,c,d], we have (p[x] === o[x]) and (p.hasOwnProperty(x) iff o.hasOwnProperty(x)) */

Object.preventExtension(p); // The "proxy" becomes "fixed"

delete o.a; delete p.b; // o is like {b:2, c:3, d:4} while p is like {a:1, c:3, d:4} // o and p have lost "synchronicity". p is an object with its own independent life.

After the Object.preventExtension|seal|freeze call, p isn't a proxy anymore. It becomes a regular object. None of what used to be p's traps when it /was/ a proxy is going to be called anymore through p surface-syntax iteraction. After the call to a succeeding (non-throwing) fix trap, what we have falls under the definition of an Object as known in ES5 (and previously). Another way to put it is that there is no way for an external program to distinguish if p is a proxy or an object (unless this external program had overriden Proxy.create beforehand).

The way I see it, a proxy is trapping and that's it. What is "fixed" is an object, because the proxy has lost all its "magic" (and cannot get it back by design).

In my opinion, we should stop talking of proxies as "fixed" and stop using this terminology because it may cause confusion. If there is an agreement on this, I'd suggestto renamethe Proxy.isTrapping method as Proxy.isProxy since as I understand it, saying that a proxy is trapping is a tautology.

What's your opinion?

# Brendan Eich (15 years ago)

I buy it.

I also cringe a little at Array.isArray, and therefore at Proxy.isProxy, in the pre-modules world ES5 and the proxies proposal inhabit. These seem like tautological predicates, and Object.isArray is prettier and more fitting in my view. But this is a tiny nit to pick. If you buy it, then Object.isProxy would be the predicate.

OTOH, with modules we would not put isProxy on poor old Object, and one would want isProxy to be an export, along with create, createFunction, Handler, etc., from the standard Proxy module. So at this point I don't propose Object.isProxy.

Whee, naming.

# David Bruant (15 years ago)

I personnally don't have any strong conviction on the matter (which object should carry the function if any). But as I wanted to get rid of a part of the terminology that had been used in a method name (harmony:proxies#detecting_proxy_objects) I just thought it would be fair to mention it and propose a solution to it. There is no emergency though. In the proposal is written "The current consensus is not to provide this method as it directly breaks "transparent" virtualization of objects".

David

Le 13/03/2011 21:32, Brendan Eich a écrit :

# Andreas Gal (15 years ago)

There is a little twist to this. You can create a proxy that has separate implementations of [[Call]] and [[Construct]], and by fixing it, it converts to a regular functions. However, this "regular" function is different from any other non-host function: it behaves different w.r.t. to f() and new f(). At the implementation level this is reflected by the fact that we use a different internal class for these "function" objects. It also maintains all the other behaviors of the original proxy [[Call]] and [[Construct]] hooks, i.e. new f() can return "5". I am not sure whether this difference warrants talking about fixed proxies, but I wanted to point it out.

# Brendan Eich (15 years ago)

On Mar 13, 2011, at 3:42 PM, David Bruant wrote:

I personnally don't have any strong conviction on the matter (which object should carry the function if any). But as I wanted to get rid of a part of the terminology that had been used in a method name (harmony:proxies#detecting_proxy_objects) I just thought it would be fair to mention it and propose a solution to it. There is no emergency though. In the proposal is written "The current consensus is not to provide this method as it directly breaks “transparent” virtualization of objects".

Right, Proxy.isTrapping is not spec'ed, and not prototype-implemented in Firefox 4.

But the minor terminology issue remains (see Andreas's followup). Would be great to hear from Tom Van Cutsem on this.

# David Bruant (15 years ago)

That's a very interesting point. But there is indeed a subtle difference between call/construct traps and the rest of the handler. These traps are actually more of the "internal property setting" kinds (like the prototype argument in Proxy.create). I think that it is the reason why these things are separated from the handler object; they are more like "direct static setting".

When reading the semantics of [[Prototype]], [[Call]] and [[Construct]], one can notice that there is no external dependency. The proxy contains references to what has been passed as an argument (and their own internal properties) and uses them without being disturbed. All the other internal method semantics have a dependency on the handler object (the internal method is reified as the handler trap dynamically not as the value at initialisation time). This is one difference.

Another difference is that the main goal of turning the proxy into an object after preventExtension is to prevent the proxy from breaking invariants. Among these invariants, the fake-object shouldn't be able to be added properties to, so property-adding (defineProperty/set) traps should be shutdown. Another invariant is that two consecutive calls to property introspection traps shouldn't allow you to pretend that properties have been added. So property-introspection traps (all remaining except delete and fix) should be removed. And shutting down some traps wouldn't really make sense without removing them all I think (I do not feel 100% strong on this).

The way I see it, after the fix trap, the proxy isn't trapping anything. For function proxies, I would consider the case as: what remains is a function with user-defined [[Call]] and [[Construct]] internal methods. It wouldn't actually be very far from what we could expect from a Function.create(call, constr) method which I would see as some sort of equivalent of the Object.create(prototype).

David

Le 13/03/2011 21:50, Andreas Gal a écrit :

# Tom Van Cutsem (15 years ago)

David,

I agree that Proxy.isProxy (or Object.isProxy) is strictly a better name than Proxy.isTrapping. I also agree that in developer-facing documentation, using the terms "proxy" vs "regular object" instead of "trapping" vs "fixed" proxy is better.

On the other hand, for spec. and implementation purposes, it does make sense to have terminology for "an object formerly known as a proxy". As Andreas points out, fixed function proxies may still behave observably different from regular functions.

Also, there's still the "fix()" trap. Are you suggesting to rename this one as well? It doesn't seem necessary to me. One could state that by fixing a proxy, the proxy becomes a regular object.

I'll make a note of your Proxy.isProxy suggestion, should this method ever be spec'ed.

2011/3/13 David Bruant <bruant at enseirb-matmeca.fr>

# David Bruant (15 years ago)

Le 16/03/2011 08:59, Tom Van Cutsem a écrit :

David,

I agree that Proxy.isProxy (or Object.isProxy) is strictly a better name than Proxy.isTrapping. I also agree that in developer-facing documentation, using the terms "proxy" vs "regular object" instead of "trapping" vs "fixed" proxy is better.

I'll change the MDN documentation soon, unless someone has an objection.

On the other hand, for spec. and implementation purposes, it does make sense to have terminology for "an object formerly known as a proxy". As Andreas points out, fixed function proxies may still behave observably different from regular functions.

Also, there's still the "fix()" trap. Are you suggesting to rename this one as well?

no no, I am not. I was just talking about the proxy "state" terminology.