Question
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?
Answer
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
statementcontinue
statementbreak
statementreturn
statementthrow
statement
The concrete rules of ASI, are described in the specification [§11.9.1 Rules of Automatic Semicolon Insertion](http://www.ecma- international.org/ecma-262/7.0/index.html#sec-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";