Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is "throw" a restricted production for automatic semicolon insertion?

Part of JavaScript's automatic semicolon insertion algorithm is so-called "restricted productions". These are syntactical forms which forbid a newline character from occurring at a certain point. To quote the ECMAScript 2015 specification:

If the phrase “[no LineTerminator here]” appears in the right-hand side of a production of the syntactic grammar, it indicates that the production is a restricted production: it may not be used if a LineTerminator occurs in the input stream at the indicated position.

There are 10 restricted productions in the ECMAScript 2015 specification:

  • PostfixExpression[Yield]: LeftHandSideExpression[?Yield] [no LineTerminator here] ++
  • PostfixExpression[Yield]: LeftHandSideExpression[?Yield] [no LineTerminator here] --
  • ContinueStatement[Yield]: continue [no LineTerminator here] LabelIdentifier[?Yield];
  • BreakStatement[Yield]: break [no LineTerminator here] LabelIdentifier[?Yield];
  • ReturnStatement[Yield]: return [no LineTerminator here] Expression ;
  • ReturnStatement[Yield]: return [no LineTerminator here] Expression[In, ?Yield];
  • ThrowStatement[Yield]: throw [no LineTerminator here] Expression[In, ?Yield];
  • ArrowFunction[In, Yield]: ArrowParameters[?Yield] [no LineTerminator here] => ConciseBody[?In]
  • YieldExpression[In]: yield [no LineTerminator here] * AssignmentExpression[?In, Yield]
  • YieldExpression[In]: yield [no LineTerminator here] AssignmentExpression[?In, Yield]

Of these productions, I understand the choice to make most of them restricted. The production for PostfixExpression is restricted to prevent parsing ambiguity with PrefixExpression. ContinueStatement, BreakStatement, and ReturnStatement have restricted productions because there are corresponding productions where break and continue do not take labels and return does not take an expression. I can't say that I know enough about arrow functions or yield expressions to know why they are restricted, but I assume it is to prevent some sort of similar parsing ambiguity.

The production which I don't understand is ThrowExpression. As far as I can tell, there is no parsing ambiguity involved in using throw like there is when using break, return, and continue: after all, throw; is not valid JavaScript. I thought that it might be for historical reasons, but as far as I can tell throw; has never been allowed in any JavaScript specification.

The practical consequence of this is that much like with return, you can't put the expression being thrown on the next line, e.g. this is wrong:

throw
new Error("some error");

However, unlike return, this doesn't have different behavior than putting the new Error() on the same line. It's just a syntax error: Chrome reports it as

Uncaught SyntaxError: Illegal newline after throw

Is the production for ThrowExpression restricted just to maintain consistency with similar contstructs? Or is there some ambiguity I'm not seeing?

like image 438
Rose Kunkel Avatar asked Jul 11 '16 15:07

Rose Kunkel


1 Answers

When throw was added to the language in 1998 or so, there was a discussion about whether the throw statement required an expression or not. (The alternative would be that a throw without an expression rethrows the current exception object, as in certain other languages.)

I can't find any record of this discussion, or of the final resolution -- although we know what the resolution was -- but it is mentioned in the TC39 meeting notes for the meeting of February 19, 1998. I suppose that the intent of the restriction was to leave the syntactic space open in case someday the decision were changed.

like image 56
rici Avatar answered Oct 22 '22 22:10

rici