Reflection of global bindings

David Bruant bruant.d at gmail.com
Sun Dec 16 03:45:57 PST 2012


Hi Allen,

I don't think we're circling. I think we're doing a spiral (which may 
give the impression that we're circling while we're moving forward).

More answers inline.

Le 15/12/2012 22:52, Allen Wirfs-Brock a écrit :
> (...)
>
> In ES5, we added reflection operations that allow ES code to inspect and modify the attributes of any property of any object.  We also reinterpreted DontDelete as [[Configurarable]]:false.  In the early drafts of what became ES5, that was all we did.  The attributes still were used to describe the semantics. of various ES operations.  In ES5, that set of operations expanded to include the reflection operations for  modifying attributes.  For example, [[Configurable]]: false prevented the Object.defineProperty operation from being used to change the attribute values of a property.  However, that was as far as the original ES5 draft changes went.  Host objects (and ES extensions) were still allowed to do pretty much anything they wanted.
I wish to note here that to some extent, it makes Table 5 and 6 of 8.6.1 
not-that-normative since they only describe the semantics of ECMAScript 
spec objects, not host objects. For instance, host objects aren't 
required to anything regarding "enumerable".
Since host objects are given all freedom, property descriptor attributes 
do not have a semantics. The semantic is only provided by the algorithms 
(8.12, 15.4.5.1, etc. or the host object semantics, etc.) manipulating 
these attributes.
The invariants of the ES5 algorithms can be documented to make them more 
easily understandable, but it doesn't make them invariants for any 
object because host objects are free to have any semantics.

As soon as ES5 decided that host objects had all freedom, it withdrew 
its own right to define a specific semantics for attributes.
ES5 still defines the semantics for its own objects through the 
algorithms, but withdrew its right to say "when you meet such attribute 
with such value on *any* object, then, you know X, Y, Z"

> Fairly late in the development of ES5 (by my recollection) MarkM championed the position that the property attribute values exposed via Object.getOwnPropertyDescritor were more than just specification control points.  His position was that they exposed certain absolute invariants to which all objects, including host objets, must conform.  This led to a small set of invariants being include in section 8.6.2 of ES5.  This included the invariant that if a property can observably disappear, its [[Configurable]] internal property must observably have a value of true.  MarkM also consistently emphasized that the required invariants did not imply that their converse was also an invariant.  For example, the fact that a property was observably configurable did not imply that the delete operation could actually be used to remove that property from its object.
ES5 withdrew its own right to define the full semantics of attributes, 
but defensive programming can't work with no semantics.
Invariants are the bare minimum to be expected from any object. I'd like 
to point out that the door might be open to add new semantics here.

> We added something and lost some by introducing those invariants.  We added some certainty about whether a few specific kinds of observable state transitions are allowed or not.  However, in the spec. we have essentially lost the ability to use the attribute values as control points for some of the specification algorithms.  For example, if a property may be non-deletable, even though its [[Configurable]] attribute is true, then the delete operation can't use the value of the [[Configurable]] attribute to determine whether or not it is allowed to  actually remove the property and whether it should return true or false as its result.
The ES5 spec does use attributes as control points, so it wasn't fully lost.

> So, to me, it sounds like that to continue down this path we should really add new non-reflected properties attributes that are the real control points for the ES semantics. Eg, we may need [[RealReadOnly]], [[RealDeletable]], and [[RealReconfigurable]] attributes to describe all the states and state transitions that are actually exist within the legacy DOM (and the pure ES global declaration semantics).
I agree with this analysis.

> As these attributes would not be reflected by Object.getOwnPropertyDescriptor/Object.defineProperty they would have to set in some other internal manner when object instances are created.
I may disagree here. Although ES5 has lost its right to define what 
attributes exactly mean (beyond the invariants), it may make sense for 
each object to communicate its state via custom attributes.
In a way, enumerable can be considered as such an attribute. It has 
exactly zero official semantics for host objects, but per spec, if you 
create your own object with {} or [], and play with enumerable and 
configurable, you know exactly what to expect.
Because host objects can do anything, the semantics to expect from *any* 
object is limited to invariants. However, for spec objects, there are 
strong expectations that can be expected from using 
Object.getOwnPropertyDescriptor/Object.defineProperty. Creating new 
attributes may be a way for *some* objects acquired in predefined 
conditions to communicate their intent.

If ECMAScript can't dictate what each attribute exactly mean, it still 
has a role to play to create conventions (like with "enumerable" and it 
worked).
ES5 paved the cowpath for existing spec objects, defined the bare 
minimum of semantics to expect from all objects and created the 
"enumerable" convention. Maybe it's time to explore how different 
objects can express their own semantics (in cases where it can be useful).


> Tis also means that Proxy based object implementations would also need to have some mechanism for emulating these "Real" attributes.
Being able to express any behavior using an independent function for 
each trap is more than enough power I think.

> So, it feels to me like we are circling about to the a place similar to where we were prior to ES5.
Now, we have a way for objects to describe a couple of properties 
(non-deletable, constant property, non-extensible) and assuming they 
follow conventions, to say whether a given property is enumerable. 
That's better than prior ES5.

> We need specification/implementation layer control points (ie, hidden attributes) that are not directly observable or controllable by ES code   (except for Proxy handlers).
That's a necessary consequence of host objects being allowed to do 
whatever they want.

> Plus now we also have a set of different reflectable attributes that have some non-obvious relationship to those hidden attributes.  I'm not sure that this is actual progress.
I think that is progress, but the road hadn't been fully traversed yet. 
Using only a couple of reflectable attributes to fully represent the 
internal state of objects was a fantasy. One I wish was realistic too, 
but clearly isn't with what WindowProxy constraints to.

The way forward from ES3 to ES5 was to expose some internal properties 
to be able to understand how any object works internally (+ the 
"enumerable" convention). The way forward is probably to add more 
finer-grained attributes that work only on some objects, but are 
irrelevant to others, create other conventions.

David


More information about the es-discuss mailing list