Unresolved 3.1 issue: statements and substatements

Allen Wirfs-Brock Allen.Wirfs-Brock at microsoft.com
Sun Nov 9 14:08:30 PST 2008

The ES3 specification has a single grammar production Statement that specifies what can occur in nested statement contexts such as if statement then and else clauses.  This allows for some strange looking but valid code such as:

If (foo)
   var bar = "baz";
   var bar = "bam";

for (var i=0;  i<10) var i=i++;

switch (i) {
   case 0 : var s = "one"; break;
   case 1:  var s = "two"; break;
  default: var s = "other";

ES3.1 drafts have split statement into separate Statement and SubStatement productions.  SubStatement excludes VariableStatment (and for a while,  when we had them, function and const statements) and is used in most nested contexts such as the above. In the revised grammar, nested Statement productions only occur as the body of blocks and as function bodies.  The motivation for this split was twofold.  The primary reason was in support of blocks introducing nested lexical declaration environments. There was discussion regarding whether or not such nested declarations without explicit block braces should be considered to be in an implicit lexical block.  In particular, some of us didn't want to further propagate to const and let the var-like possibility of multiple declarations within a lexical block of the same entity. For example, the thinking was that:

If (foo)
   const bar = "baz";
   const bar = "bam

should either be illegal or  useless (each const would be in a separate implicit lexical block and would disappear immediately at completion of the block).  The "illegal" possibility was preferred and SubStatement was created as a way to specify that.

The second motivation of the split was a hygienic objection to the occurrence of var  (or any new declarations) in such positions. The belief was that most users who might code such things probably don't understand the actual semantics  involved and may or may not get the result they expected. If this is the case, it is probably better to forbid it.

The exclusion of var from SubStatement is a breaking change to ES3.  Some potentially existing valid ES3 programs that used var in these sorts of nested scenarios would not be valid ES3.1 programs. However, at the time, the combination of the two motivations seemed to carry enough weight to justify the change.

However, we have not included lexical blocks or any new lexical declarations in 3.1 and while we will eventually have them it seems unlikely that var will ever have block local scope. So the first argument doesn't really apply in the context of 3.1. The hygiene based argument is of the sort that we have generally only applied to strict mode restrictions. Strict mode is opt-in so minor breaking changes can be tolerated in strict code.

Recommendation #1:  For non-strict mode code, ES3's support of VariableStatement in nested contexts remains in place. The above code examples remain valid non-strict ES3.1 code. However, ES3.1 strict mode will disallow such usage of VariableStatement. Whether this is accomplished via some variant of the current draft's Statement/SubStatement grammar or via prose restrictions for strict mode is a specification detail that can be resolved after we make this decision.

Assuming we follow that recommendation (or if we don't and continue to apply the restriction to all code) there is still another open question about the strict mode semantics.  It is, can a VariableStatement occur as the Statement of a LabelledStatement.  For example, the following is currently allowed in ES3:

   var i,j,k,l,m,n;
    var A$,B$, C$;

Odd, but valid in ES3.  More generally, ES3 allows any statement to have a label including all non-compound statements that can't possibly contain a break or continue.

Strict mode could restrict such usages and this is probably a good idea if you believe that one of the purposes of strict mode is to enable early flagging of code whose meaning is likely not to be what a programmer intended.

My opinion (but not a recommendation) is that we should probably just leave LabelledStatment alone for ES3.1, even in strict mode. However, we certainly could specify some strict mode restrictions for it  if there is a consensus that they are desirable. So:

Feedback Request:  Should we restrict usage of LabelledStatment in strict mode or leave it as specified in ES3.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20081109/1eeb596f/attachment.html>

More information about the Es-discuss mailing list