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