7.9 Automatic semicolon insertion

2010-04-13

An Ecmascript Program always contains semicolons. The only exception to this rule is the empty Program. However, you could write a perfectly legal large program and not use a single semicolon. Even then the first statement still holds.

Ecmascript implements a feature called “Automatic Semicolon Insertion”. This feature was born to make Ecmascript easier to learn for beginning programmers. However, it can have some unexpecting and undesirable side effects.

The rules for insertion are as follows. When parsing a Program, a semicolon is inserted into the source when:
- When parsing source, the next token cannot be parsed by any production of the grammar, but only if one of the following holds;
- - The next token is separated by the previous by at least one LineTerminator
- - The next token is a }
- The end of the source has been reached and does not parse as Program as is
- When a restricted token (like ReturnStatement) is being parsed and there is at least one LineTerminator between the restricted token and the next token.

However, a semicolon is never automatically inserted if
- It would produce an empty statement
- It would be one of the two semicolons in the header of a for statement

There are only five restricted productions: PostfixExpression, ContinueStatement, BreakStatement, ReturnStatement and ThrowStatement.

This means that you can not have only a LineTerminator (and other whitespace) between return/throw and your return value, or between break/continue and the targeted identifier (label). This also goes for x++ and x--.

Examples given in the specification:

Code: (JS)

{ 1 2 } 3 // invalid, none of the rules apply because there is no line terminator

{ 1
2 } 3 // invalid as is, but valid because it is transformed to

{1;
2;}3; // valid

for (a; b) … // invalid, no semicolon for the header of a for

function(){
return
5+5;
} // valid, but the return value is undefined, it is equal to

function(){
Return;
5+5;
}

a = b
++c // valid “as expected”, but only because there’s a line terminator after b

a = b;
++c;

if (a>b)
else c=d // invalid, a semicolon would result in an empty statement after if

if (a>b);
else c=d;

a = b + c
(d + e).print() // valid, but parsed as

a = b + c(d + e).print(); // no semicolon because there is no offending token to be found…

It is generally accepted as a best practice to always terminator your statements with a semicolon. It adds to readability and it prevents you from falling into traps like above. Keep in mind that function _expressions_ should also get a semi-colon. Only named functions with no LeftHandExpression are actually a FunctionStatement! Any other occurrence is an expression and should be explicitly terminated by a semicolon.