ASI: Why are control flow statements and the postfix operator restricted?

I can see why ArrowFunction and async-related productions are restricted:

  • For ArrowFunction, the restrictions are needed to resolve ambiguity with headless arrow functions (which was a proposed feature).
  • For async-related productions, the restrictions are needed to resolve ambiguity with async identifier references in code written prior to the introduction of the async keyword.

Question: But there isn't any syntactic ambiguity in the case of control flow statements (return, break, continue, yield and throw) and postfix operators, so why are they restricted?

The only justification I can think of is that someone who relies on ASI might write something like if (condition) return \n function foo() {} and expect ASI to insert a ; after the return keyword. So the [no LT here] restriction might be needed to trigger ASI in such cases where there is an expectation of newline significance.

But I'm not sure if this is the reason given that ASI is an error correction procedure and shouldn't be relied upon as a "universal significant-newline rule", i.e. the grammar isn't required to care about "expectations" of newline significance.

“Not required to care” doesn’t mean “should not care”. Since code is usually written by humans before being consumed by machines, it is perfectly reasonable for grammar to care about expectations.

(Also, as the expression of “error correction procedure” might be misinterpreted, it is worthwhile to note that it is a technical term, not a moral one.)

The case of return is here from the dawn of JS, at a time where ASI was thought as a worthwhile feature by the designer of the language. (Otherwise, there would have been no ASI, just flat syntax errors.) Therefore, he did care about expectations.

For break and continue, it might be either by design, or for the sake of BC, (or both,) as the two first editions of ECMAScript did not include the form break label;, just break;, so that the following code did have an implicit semicolon after break:

break
something;

My wild guess is that the cases of throw and yield are here for consistency with return. (Note that yield has appeared in SpiderMonkey long before it appeared in ECMAScript.)

The rule was not extended to await. (I think it was a minor error, and it should have been added for consistency, but this is just my opinion.) But this construct was added much later, and, in the meantime, the general feeling of language designers towards ASI had evolved.

1 Like

Yes, I think I was misconstruing it as "user error" instead of "parsing error".

That makes sense. Mr Eich talks about 'restricted productions' (here) and 'expectation of newline significance' (here). In the first link, he says:

If we eliminate restricted productions by requiring semicolon after return, break, continue, throw [...], and postfix ++/--, is it better to go all the way and eliminate the syntactic error correction part of ASI?

...which seems to imply that the control flow / postfix restrictions are in place simply to satisfy the expectation of newline significance. Would you agree with my reading?

Good point about BC, I wouldn't have picked up on that.

Thank you for your help @claudepache. Also, I apologise if my post comes across as too pedantic. I personally don't rely on ASI but have still been bitten by the return restriction in the past, so it helps to understand where it's coming from.