We generally claim that ECMAScript uses a left-to-right evaluation order and in
ES5 we even fixed what was consider a bug in the ES3 spec (second item ES5
Annex D) regarding evaluation order of relational operators. Consider:
var a={valueOf: function () {alert(" a valueOf");return 1}};
var b={valueOf: function () {alert(" b valueOf");return 2}};
a<=b;
A strict implementation of the ES3 spec. would alert: "b valueOf" followed by
"a valueOf" indicating what appears to be a right-to-left evaluation order.
Chrome actually does this while at least IE and FF alert "a valueOf" followed
by "b valueOf". The ES5 changes say that "a valueOf" should occur first as
this is consistent with the general left-to-right rule.
However, when accessor properties were added to the specification we did not
consider the observable ordering interaction between accessor get functions
with side-effects and ToPrimitive operations (ie valueOf) with side-effects. A
typical binary operator algorithm from section 11 looks like:
1. Let left be the result of evaluating MultiplicativeExpression.
2. Let leftValue be GetValue(left).
3. Let right be the result of evaluating UnaryExpression.
4. Let rightValue be GetValue(right).
5. Let leftNum be ToNumber(leftValue).
6. Let rightNum be ToNumber(rightValue).
7. Return the result of applying the specified operation (*, /, or
%) to leftNum and rightNum. See the Notes below 11.5.1, 11.5.2, 11.5.3.
Note that the two calls to GetValue precede the two calls to ToNumber.
Generally in ES3 GetValue doesn't have side-effects so left-to-right order is
maintained (however the ordering is observable if the right argument throws a
ReferenceError). The interweaved evaluation order is much easier to observe if
accessor properties are implemented. Consider executing the following in the
context of the declarations of a and b above:
var o={get a() {alert("get a");return a}, get b() {alert ("get b");return b}};
o.a*o.b;
GetValue calls the accessor get functions, so based upon the above algorithm,
you would expect to see the alert sequence: "get a", "get b", "a valueOf", "b
valueOf". This is exactly what happens for existing getter/setter
implementations in at least FF and Chrome.
So, the ES5 specification of operators is consistent with existing
implementations of accessor properties. However, this is not a strict
left-to-right order of evaluation order. We don't have many options at this
point. Here are the alternatives I see:
1. Abandon the idea that ECMAScript does strict left-to-right evaluation (it
never really did, anyway) and be content with the story that it generally
evaluates left to right with assorted special case exceptions to this rule.
2. Consider all existing violation of strict left-to-right evaluation as
specification bugs and make a big note of that in the errata. Maybe they can
be fixed in the ISO version of the ES5 spec.
It would take substantial work to fix this throughout the specification and
actual implementation of the strict left-to-right rule would introduce numerous
potentially observable changes to existing implementations. Based upon this, I
suspect that we have to choose alternative #1 although I would personally be
open to considering alternative #2.
Thoughts?
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss