[Proxies] Refactoring prototype climbing in the spec

Allen Wirfs-Brock allen at wirfs-brock.com
Thu Nov 10 09:09:33 PST 2011

On Nov 10, 2011, at 3:28 AM, David Bruant wrote:

> Le 09/11/2011 12:17, Tom Van Cutsem a écrit :
>> 2011/11/8 Allen Wirfs-Brock <allen at wirfs-brock.com>
>> More generally, I think there should be a 1::1 correspondence between the internal methods in listed in ES5 Table 8 and fundamental proxy traps.
>> I absolutely agree we should strive to achieve this.
> I disagree.
> First of all, Table 8 is incomplete:
> * It lacks a function for property enumeration and proxies need a trap for that (for-in loops, Object.getOwnPropertyNames, Object.keys).
> * There is no method for passing [[Extensible]] from true to false, though this behavior is used and needs a ("fundamental") trap as well. The reason for this is certainly that this action can be described in one spec algorithm step, so there was no need from a     specification perspective to consider this as an internal method, but it's still a fundamental operation you can perform on an object.
> (I may be missing others)

I agree that Table 8 is incomplete (and has unnecessary items in it). The point is that Table 8 should define the fundamental Object semantic API that is used by all clients, including the specifications of language feature semantics, the specification of built-in functions,  and the semantics that are reified via the Proxy and Object reflection API.  One consistent set of object semantics operations, used by everybody.

> A second point I disagree on is the idea of "fundamental trap". This notion existed on the original proxy proposal. I think it was more for the purpose of writing traps more easily. With the direct proxies proposal, the notion of fundamental and derived traps disappears (and hopefully, direct proxies will be promoted during the next TC-39 meeting).

I was using "fundamental"  to mean what i just stated above.  I agree that only these fundamental object operations need to be reflected in the Proxy API.

> Regardless of Table 8 being incomplete, I think that proxy traps have another factor to take into account which is the relationship with surface syntax. When someone writes "let a = o.a;", the intention is to call the "get" operation regardless of whether the "a" property is on o or somewhere on its prototype chain. This is another thing that I like in the [[Get]] refactoring: when the prototype is the proxy, its get trap gets called and not its getOwnPropertyDescriptor trap. It makes proxy traps more in line with the object clients requests.

The surface syntax perspective is exactly how I conceptualize the "Table 8" level of the specification. It is the interface between the runtime object model and the surface features of the language.  

However, there were some practical engineering considerations that went into the ES5 factoring of the internal methods. For example, [[Put]] calls [[DefineOwnProperty]] to set a property's value because it made it easier to specify Array behavior.  Creating an array indexed property (possibly via [[Put]]) and letting the value of the "length" property both have side-effects.  There are multiple ways that such values can be set, including using Object.defineProperty.  By making the default implementation of [[Put]] delegate to [[DefineOwnProperty]] I only needed to over-ride [[DefineOwnProperty]] for array instances to specify their semantics.  If I hand't done this, I would have had to consistently over-ridden both [[DefineOwnProperty]] and [[Put]].

As long, as the "internal methods" were just specification devices, this sort of refactoring could be done as a convenience.  But as soon as the reify them via traps we have to thing about the broader and permanent impacts of such refactoring.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20111110/e28402e6/attachment.html>

More information about the es-discuss mailing list