diff --git a/src/ast/Node.js b/src/ast/Node.js index 4f65871..6a80ede 100644 --- a/src/ast/Node.js +++ b/src/ast/Node.js @@ -66,6 +66,12 @@ export default class Node { this.eachChild( child => child.initialise( this.scope || scope ) ); } + insertSemicolon ( code ) { + if ( code.original[ this.end - 1 ] !== ';' ) { + code.insertLeft( this.end, ';' ); + } + } + locate () { // useful for debugging const location = getLocation( this.module.code, this.start ); diff --git a/src/ast/nodes/ExpressionStatement.js b/src/ast/nodes/ExpressionStatement.js index 237441a..7198541 100644 --- a/src/ast/nodes/ExpressionStatement.js +++ b/src/ast/nodes/ExpressionStatement.js @@ -1,5 +1,8 @@ import Statement from './shared/Statement.js'; export default class ExpressionStatement extends Statement { - + render ( code, es ) { + super.render( code, es ); + if ( this.shouldInclude ) this.insertSemicolon( code ); + } } diff --git a/src/ast/nodes/VariableDeclaration.js b/src/ast/nodes/VariableDeclaration.js index e1be1a0..77f4433 100644 --- a/src/ast/nodes/VariableDeclaration.js +++ b/src/ast/nodes/VariableDeclaration.js @@ -14,7 +14,7 @@ function getSeparator ( code, start ) { return `;\n${lineStart}`; } -const forStatement = /^For(?:Of|In)Statement/; +const forStatement = /^For(?:Of|In)?Statement/; export default class VariableDeclaration extends Node { initialise ( scope ) { @@ -92,9 +92,16 @@ export default class VariableDeclaration extends Node { if ( treeshake && empty ) { code.remove( this.leadingCommentStart || this.start, this.next || this.end ); - } else if ( this.end > c ) { - const hasSemicolon = code.original[ this.end - 1 ] === ';'; - code.overwrite( c, this.end, hasSemicolon ? ';' : '' ); + } else { + // always include a semi-colon (https://github.com/rollup/rollup/pull/1013), + // unless it's a var declaration in a loop head + const needsSemicolon = !forStatement.test( this.parent.type ); + + if ( this.end > c ) { + code.overwrite( c, this.end, needsSemicolon ? ';' : '' ); + } else if ( needsSemicolon ) { + this.insertSemicolon( code ); + } } } } diff --git a/test/function/adds-semicolons-if-necessary-b/_config.js b/test/function/adds-semicolons-if-necessary-b/_config.js new file mode 100644 index 0000000..bb17123 --- /dev/null +++ b/test/function/adds-semicolons-if-necessary-b/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'adds semi-colons if necessary' +}; diff --git a/test/function/adds-semicolons-if-necessary-b/foo.js b/test/function/adds-semicolons-if-necessary-b/foo.js new file mode 100644 index 0000000..b2602d2 --- /dev/null +++ b/test/function/adds-semicolons-if-necessary-b/foo.js @@ -0,0 +1 @@ +assert.ok( true ) diff --git a/test/function/adds-semicolons-if-necessary-b/main.js b/test/function/adds-semicolons-if-necessary-b/main.js new file mode 100644 index 0000000..c6ddba4 --- /dev/null +++ b/test/function/adds-semicolons-if-necessary-b/main.js @@ -0,0 +1,3 @@ +import './foo.js'; + +(function bar() {})(); diff --git a/test/function/adds-semicolons-if-necessary/_config.js b/test/function/adds-semicolons-if-necessary/_config.js new file mode 100644 index 0000000..bb17123 --- /dev/null +++ b/test/function/adds-semicolons-if-necessary/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'adds semi-colons if necessary' +}; diff --git a/test/function/adds-semicolons-if-necessary/foo.js b/test/function/adds-semicolons-if-necessary/foo.js new file mode 100644 index 0000000..14d0105 --- /dev/null +++ b/test/function/adds-semicolons-if-necessary/foo.js @@ -0,0 +1,3 @@ +export var foo = function () { + return 42; +} diff --git a/test/function/adds-semicolons-if-necessary/main.js b/test/function/adds-semicolons-if-necessary/main.js new file mode 100644 index 0000000..2a031e5 --- /dev/null +++ b/test/function/adds-semicolons-if-necessary/main.js @@ -0,0 +1,7 @@ +import { foo } from './foo.js'; + +(function bar() { + assert.ok( true ); +})(); + +assert.equal( foo(), 42 );