Property descriptors as ES6 Maps

Tom Van Cutsem tomvc.be at gmail.com
Thu Nov 1 02:37:06 PDT 2012


Hi,

David, I think I see where you are going: property descriptors are
basically "bags" of key/value properties, and maps are a more direct
representation of this concept than objects.

On the other hand, as so carefully explained by Allen, there currently
isn't really an issue with the mapping between property descriptors and
objects: at all the boundary points, we make sure to properly convert
descriptors into well-behaved objects and vice versa.

As you point out yourself, making the change from objects to maps implies a
bunch of backwards compat. issues. My position is that doing the
object->map refactoring at this stage would entail a lot of work for very
little gain.

Finally, remember that property descriptors-as-objects really leverage the
object literal notation (i.e. I can create a property descriptor by just
writing "{value:42,writable:true}". I don't think there is a corresponding
sweet syntax for literal maps? In any case, Object.defineProperty will need
to continue accepting such literal objects as its third argument, so why
not keep the story simple and not widen the type to object | map.

Cheers,
Tom

2012/10/31 Allen Wirfs-Brock <allen at wirfs-brock.com>

> 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.
>
> Allen
>
>
>
>
>
>
>
> On Oct 31, 2012, at 2:40 AM, David Bruant wrote:
>
> > Hi,
> >
> > I've recently filed a spec bug [1] 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.
> >
> > David
> >
> > [1] https://bugs.ecmascript.org/show_bug.cgi?id=863
> > [2] http://wiki.ecmascript.org/doku.php?id=harmony:proxies_spec
> > _______________________________________________
> > es-discuss mailing list
> > es-discuss at mozilla.org
> > https://mail.mozilla.org/listinfo/es-discuss
> >
>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20121101/454d593f/attachment.html>


More information about the es-discuss mailing list