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
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to