What are the rules for JavaScript's automatic semicolon insertion (ASI)?
automatic-semicolon-insertion, javascript
Solution
First of all you should know which statements are affected by the automatic semicolon insertion (also known as ASI for brevity):
- empty statement
- `var` statement
- expression statement
- `do-while` statement
- `continue` statement
- `break` statement
- `return` statement
- `throw` statement
The concrete rules of ASI, are described in the specification §11.9.1 Rules of Automatic Semicolon Insertion
Three cases are described:
- When an offending token is encountered that is not allowed by the grammar, a semicolon is inserted before it if:
- The token is separated from the previous token by at least one `LineTerminator`.
- The token is `}`
e.g.:
{ 1
2 } 3
is transformed to
{ 1
;2 ;} 3;
The `NumericLiteral` `1` meets the first condition, the following token is a line terminator. The `2` meets the second condition, the following token is `}`.
- When the end of the input stream of tokens is encountered and the parser is unable to parse the input token stream as a single complete Program, then a semicolon is automatically inserted at the end of the input stream.
e.g.:
a = b
++c
is transformed to:
a = b;
++c;
- This case occurs when a token is allowed by some production of the grammar, but the production is a restricted production, a semicolon is automatically inserted before the restricted token.
Restricted productions:
UpdateExpression :
LeftHandSideExpression [no LineTerminator here] ++
LeftHandSideExpression [no LineTerminator here] --
ContinueStatement :
continue ;
continue [no LineTerminator here] LabelIdentifier ;
BreakStatement :
break ;
break [no LineTerminator here] LabelIdentifier ;
ReturnStatement :
return ;
return [no LineTerminator here] Expression ;
ThrowStatement :
throw [no LineTerminator here] Expression ;
ArrowFunction :
ArrowParameters [no LineTerminator here] => ConciseBody
YieldExpression :
yield [no LineTerminator here] * AssignmentExpression
yield [no LineTerminator here] AssignmentExpression
The classic example, with the `ReturnStatement`:
return
"something";
is transformed to
return;
"something";
Problem
Well, first I should probably ask if this is browser dependent. I've read that if an invalid token is found, but the section of code is valid until that invalid token, a semicolon is inserted before the token if it is preceded by a line break. However, the common example cited for bugs caused by semicolon insertion is: ``` return _a+b; ``` ..which doesn't seem to follow this rule, since _a would be a valid token. On the other hand, breaking up call chains works as expected: ``` $('#myButton') .click(function(){alert("Hello!")}); ``` Does anyone have a more in-depth description of the rules?