Property descriptors as ES6 Maps
allen at wirfs-brock.com
Wed Oct 31 11:03:18 PDT 2012
Let me summarize what I think is your concern.
In ES5, property descriptor records are a specification device that is used to transport information about object properties between factored components of the ES specification. The same information can be expressed as an ES object that is produced/consumed by Object.getOwnPropertyDescriptor and Object.defineProperty. These are raising/lowering operations that move information from the specification/implication level to the reflective ES language level. One advantage of this layering is that the conversion to/from an actual object takes place once, at a well defined point in the execution sequence and any side-effects of object access occur only at that point. Once the information is represented as an internal "record" we know that all internal consistency preconditions are satisfied and that no side-effects can be associated with access to such records.
You concern seems to be that a proxy traps that deal with descriptor objects have no such guarantees and in particular strange things might happen if a descriptor object is itself a proxy.
I don't think any of this is actually a problem. First there are only a few traps that directly deal with descriptor objects.
The getOwnPropertyDescriptor trap is a lowering operation. It is called by a proxy's [[GetOwnProperty]] internal method implementation. The internal method expects to get back a property descriptor object which it must then lower (via the ToPropertyDescriptor abstract operation) into a descriptor record. ToPropertyDescriptor can throw if the descriptor object being lowered is malformed or if it misbehaves (via accessor properties or by being a Proxy itself) but that is ok because throwing is part of the specified behavior of ToPropertyDescriptor and once we are past that we know we have a well-formed internal descriptor record that is not subject to tampering. Keeping the original object around would infect the entire downstream use of the property descriptor with the possibility of side-effects.
The defineProperty trap is a raising operation. It is called by a Proxy's [[DefineOwnProperty]] internal method and starts with an internal descriptor record. The internal method converts the record to an object (via the FromPropertyDescriptor abstract operation) and passes that object to the trap. Note that this is guaranteed to be a ordinary object (not a proxy) and that the properties that describe property attributes are guaranteed to be data properties. So, defineProperty traps don't need to worry about getting passed a bogus property descriptor object as an argument.
The other possible concern would be that a trap might directly use Object.getOwnPropertyDescriptor on a proxy object and that this might provide a bogus descriptor. But it can't. Object.getOwnPropertyDescriptor may trigger a getOwnPropertyDescriptor trap but as described above this is a lowering operation that produces a well formed property descriptor record (or throws if it can not). That lowered record is immediately raised via FromPropertyDescriptor, so we know that Object.getOwnPropertyDescriptor always returns an ordinary object that is a well formed, side-effect free property descriptor object.
so, I just don't see any basis for your concern. Perhaps, you could elaborate on the nature of the problem as you perceive it.
On Oct 31, 2012, at 2:40 AM, David Bruant wrote:
> I've recently filed a spec bug  and given more thoughts about it that
> goes beyond the suggested restructuring so I'm bringing it up here. This
> posts ends up with an unresolved issue, but I hope a solution can be found.
> Let's talk about property descriptors. Currently, in the spec, property
> descriptors have their own type (with "fields" and accessing things in
> these fields). It's a type that matches very well with objects, so the
> mapping with Object.defineProperty input and
> Object.getOwnPropertyDescriptor is rather obvious.
> However, when we think about proxy traps, the proxy traps can't have
> access to an abstract data structure, so the proxy spec uses regular
> objects for trap communication.
> My bug was about making the use of objects official in the spec
> internals... until I realized that ES6 has maps.
> I'm writing to propose a change which is to make property descriptor ES6
> maps both inside the traps and to the external interface. There is no
> problem for traps (except maybe that it changes the current Firefox
> implementation...). A backward compatibility may exist for ES5 code:
> * Object.defineProperty using maps
> => For legacy reason, it would keep accepting plain old objects, but
> when passed a map, it would use the map get/set/has protocol.
> * Object.getOwnPropertyDescriptor returning maps
> => That part is a bit trickier, because current code has a ridiculous
> amount of 'desc.configurable', 'desc.enumerable', etc. in it and this
> must keep working.
> I'm not sure I have found an acceptable idea for this part. One major
> issue I see is the naming conflict between Map.prototype.get/set and the
> 'get' and 'set' attributes of property descriptors.
> In the hope it will inspire someone who'll be able to find a solution.
>  https://bugs.ecmascript.org/show_bug.cgi?id=863
>  http://wiki.ecmascript.org/doku.php?id=harmony:proxies_spec
> es-discuss mailing list
> es-discuss at mozilla.org
More information about the es-discuss