Andreas Rossberg <mailto:[email protected]>
January 23, 2012 5:54 AM
On 22 January 2012 23:46, Gavin Barraclough<[email protected]> wrote:
On Jan 20, 2012, at 4:23 PM, Allen Wirfs-Brock wrote:
I'm not yet convinced that you need to publicly expose such global object
properties accessor properties. I think it is possible to hide the
mechanisms.
I'm strongly inclined to agree with this sentiment – engine implementors
might choose internally to utilize accessors in their implementations, but
from a user perspective it seems to make much more sense that these remain
as regular data properties. It is worth bearing in mind that 'const' is
already available outside of strict mode and we need to be considerate of
any breaking changes we make to existing semantics.
Sigh. This may be exactly the reason why I am deeply sceptical that
backporting ES6 features to classic mode is a wise move. Now we don't
just have to stay backwards compatible with broken ES5 features, we
even have to stay backwards compatible with broken ES5 non-features?
Even in strict mode?
Harmony was supposed to be based on strict mode for a reason.
Hang on -- I think Gavin may have stated things in a way that set the
cat among pigeons unnecessarily. We agreed (at least Gavin and I) at the
f2f to try to bring our const and function-in-block implementations in
line with non-strict ES6 in the version-free opt-in model toward which
we're striving.
In this light I do not think we should preemptively concede anything to
breaking changes of existing *implementation* semantics.
OTOH the rest of Gavin's mail invoked existing implementations (Firefox
in particular) more for intuitive non-strict appeal than as binding
precedent, if I read Gavin right.
On *how* to implement the suggested semantics, I do see disagreement.
Indeed I hope we do not need to introduce not-yet-defined as a value
state in the object model. But the user-facing non-strict semantics
should be separable.
(We could define
incompatible semantics for strict-mode only, but this would likely lead to a
confusing divergence in semantics for users – it could be horribly confusing
if const variables in non-strict code were to be implemented as data
properties whilst those in strict code were defined as accessor properties).
alert('value' in Object.getOwnPropertyDescriptor(this, 'x'));
alert(Object.getOwnPropertyDescriptor(this, 'x').writable === true);
alert(Object.getOwnPropertyDescriptor(this, 'x').value);
x = 1;
alert(Object.getOwnPropertyDescriptor(this, 'x').value);
const x = 2;
alert(Object.getOwnPropertyDescriptor(this, 'x').value);
x = 3;
alert(Object.getOwnPropertyDescriptor(this, 'x').value);
This script tests the presence and writability of a property on the global
object, and the effect of attempting to assign to it in non-strict code. It
demonstrates a non-const var behaving as a regular non-writable property in
non-strict code.
On FireFox the above script outputs "true, false, undefined, undefined, 2,
2", which to my mind makes a lot of sense. It perfectly matches, as far as
one can test, any other regular non writable property that you could create
on an object (of course there it not normally the opportunity to split
creation and initialization of a non-writable property).
I disagree completely. This is the current V8 semantics as well, but
it does _not_ make sense.
You observe that the value of a const is changing in the middle of
your program. That fundamentally violates const semantics, and is
incompatible with the idea of guards on let as well.
Yes, we agree to all that for strict code (ES5 or above), but this is
non-strict code. In non-strict code, implementations have already
violated const semantics, and we have not added guards yet.
Furthermore, the property descriptor tells you that the property is a
writable data property,
No -- false is the second value alerted.
but you cannot write it (e.g. replacing "x =
1" with "this.x = 1"). That violates the object model.
In other words, the current behaviour breaks both scoping and objects semantics.
Non-strict or really pre-strict implementations broke scoping semantics
-- no temporal dead zone. Whether we can retroactively force the new
semantics on any JS that worked with the old scoping semantics remains
to be seen.
Object semantics, I think you misread the alert output. Or did I?
This behaviour is also sensibly consistent with that for let and var.
Running the above script, changing 'const' to 'var'
outputs "true, true, undefined, 1, 2, 3" (indicating the property is
writable, and all assignments succeed), and for 'let' currently also
outputs "true, true, undefined, 1, 2, 3" on FireFox. To my mind this
behaviour should probably change slightly. With a temporal dead zone
implemented I would expect an attempt to [[DefineOwnProperty]] to an
uninitialized value to be rejected (though I would not expect an exception
to be thrown from non-strict code) so I would expect the output for 'let' to
be "true, true, undefined, undefined, 2, 3" (the assignment of 'a' silently
fails leaving the value unchanged).
More importantly, an attempt to [[Get]] an uninitialized property also
has to be rejected. Both requires proliferating the entire notion of
being uninitialized into the object model. To be coherent, you'd also
have to be able to reflect on it through property descriptors, make it
available to proxies, and so on. I see no good reason why we should go
there.
Agreed. And for non-strict code if we choose to keep the non-throwing
behavior, we do not have to. We do however therefore have to allow a
const to be read before initialized, with value undefined -- but only
for non-strict code.
This is future-hostile to guards, or really, we kick the can down the
road a bit and evangelize strict mode. If and when we add guards, we can
either break scoping semantics backward compatibility, or require strict
opt in.
/be
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss