Browse Source

Merge pull request #124 from rollup/gh-112

Include statements with side-effects
gh-109
Rich Harris 9 years ago
parent
commit
59c6da9abf
  1. 5
      src/Bundle.js
  2. 6
      src/Module.js
  3. 28
      src/Statement.js
  4. 3
      test/form/unused-side-effect/_config.js
  5. 7
      test/form/unused-side-effect/_expected/amd.js
  6. 5
      test/form/unused-side-effect/_expected/cjs.js
  7. 3
      test/form/unused-side-effect/_expected/es6.js
  8. 7
      test/form/unused-side-effect/_expected/iife.js
  9. 11
      test/form/unused-side-effect/_expected/umd.js
  10. 13
      test/form/unused-side-effect/foo.js
  11. 2
      test/form/unused-side-effect/main.js
  12. 3
      test/function/globally-called-modifying-function/_config.js
  13. 3
      test/function/globally-called-modifying-function/main.js
  14. 17
      test/function/globally-called-modifying-function/module.js
  15. 14
      test/function/modify-assumed-global/_config.js
  16. 3
      test/function/modify-assumed-global/main.js
  17. 15
      test/function/modify-assumed-global/math.js

5
src/Bundle.js

@ -67,6 +67,11 @@ export default class Bundle {
entryModule.markAllStatements( true );
entryModule.markAllExports();
// Include all side-effects
this.modules.forEach( module => {
module.markAllSideEffects();
});
// Sort the modules.
this.orderedModules = this.sort();

6
src/Module.js

@ -437,6 +437,12 @@ export default class Module {
this.markAllExports();
}
markAllSideEffects () {
this.statements.forEach( statement => {
statement.markSideEffect();
});
}
markAllStatements ( isEntryModule ) {
this.statements.forEach( statement => {
if ( statement.isIncluded ) return; // TODO can this happen? probably not...

28
src/Statement.js

@ -8,6 +8,11 @@ const blockDeclarations = {
'let': true
};
const modifierNodes = {
AssignmentExpression: 'left',
UpdateExpression: 'argument'
};
function isIife ( node, parent ) {
return parent && parent.type === 'CallExpression' && node === parent.callee;
}
@ -392,6 +397,29 @@ export default class Statement {
});
}
markSideEffect () {
const statement = this;
walk( this.node, {
enter ( node, parent ) {
if ( /Function/.test( node.type ) && !isIife( node, parent ) ) return this.skip();
// If this is a top-level call expression, or an assignment to a global,
// this statement will need to be marked
if ( node.type === 'CallExpression' ) {
statement.mark();
}
else if ( node.type in modifierNodes ) {
let subject = node[ modifierNodes[ node.type ] ];
while ( subject.type === 'MemberExpression' ) subject = subject.object;
if ( statement.module.bundle.globals.defines( subject.name ) ) statement.mark();
}
}
});
}
replaceIdentifiers ( magicString, names, bundleExports ) {
const statement = this;

3
test/form/unused-side-effect/_config.js

@ -0,0 +1,3 @@
module.exports = {
description: 'side-effects to non-globals are not blindly included'
};

7
test/form/unused-side-effect/_expected/amd.js

@ -0,0 +1,7 @@
define(function () { 'use strict';
var foo = 42;
assert.equal( foo, 42 );
});

5
test/form/unused-side-effect/_expected/cjs.js

@ -0,0 +1,5 @@
'use strict';
var foo = 42;
assert.equal( foo, 42 );

3
test/form/unused-side-effect/_expected/es6.js

@ -0,0 +1,3 @@
var foo = 42;
assert.equal( foo, 42 );

7
test/form/unused-side-effect/_expected/iife.js

@ -0,0 +1,7 @@
(function () { 'use strict';
var foo = 42;
assert.equal( foo, 42 );
})();

11
test/form/unused-side-effect/_expected/umd.js

@ -0,0 +1,11 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory() :
typeof define === 'function' && define.amd ? define(factory) :
factory();
}(this, function () { 'use strict';
var foo = 42;
assert.equal( foo, 42 );
}));

13
test/form/unused-side-effect/foo.js

@ -0,0 +1,13 @@
var uid = 0;
uid = 1;
uid += 1;
uid++;
// ensure identifiers aren't treated as globals just because
// var declaration hasn't been encountered yet...
uid2 = 1;
uid2 += 1;
uid2++;
var uid2;
export var foo = 42;

2
test/form/unused-side-effect/main.js

@ -0,0 +1,2 @@
import { foo } from './foo';
assert.equal( foo, 42 );

3
test/function/globally-called-modifying-function/_config.js

@ -0,0 +1,3 @@
module.exports = {
description: 'globally called function should be included if it modifies an exported value (#112)'
};

3
test/function/globally-called-modifying-function/main.js

@ -0,0 +1,3 @@
import value from './module.js';
assert.equal( value, 3 );

17
test/function/globally-called-modifying-function/module.js

@ -0,0 +1,17 @@
var value = 1;
function change () {
value = 2;
}
function changeAgain () {
value += 1;
}
change();
if ( true ) {
changeAgain();
}
export default value;

14
test/function/modify-assumed-global/_config.js

@ -0,0 +1,14 @@
var assert = require( 'assert' );
var Math = {};
module.exports = {
description: 'side-effects to assumed globals are included',
context: {
Math: Math
},
exports: function ( exports ) {
assert.equal( Math.square( 3 ), 9 );
assert.equal( Math.cube( 3 ), 27 );
}
};

3
test/function/modify-assumed-global/main.js

@ -0,0 +1,3 @@
import { square } from './math';
assert.equal( square( 2 ), 4 );

15
test/function/modify-assumed-global/math.js

@ -0,0 +1,15 @@
function square ( x ) {
return x * x;
}
function cube ( x ) {
return x * x * x;
}
Math.square = square;
if ( true ) {
Math.cube = cube;
}
export { square };
Loading…
Cancel
Save