Browse Source

mark side-effecty statements (call expressions and assignments to globals) - fixes #112

gh-109
Rich-Harris 9 years ago
parent
commit
25ca424c2a
  1. 5
      src/Bundle.js
  2. 6
      src/Module.js
  3. 19
      src/Statement.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 => {
if ( statement.hasSideEffects ) statement.mark();
});
}
markAllStatements ( isEntryModule ) {
this.statements.forEach( statement => {
if ( statement.isIncluded ) return; // TODO can this happen? probably not...

19
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;
}
@ -47,6 +52,7 @@ export default class Statement {
this.dependantIds = [];
this.namespaceReplacements = [];
this.hasSideEffects = false;
this.isIncluded = false;
this.isImportDeclaration = node.type === 'ImportDeclaration';
@ -167,6 +173,19 @@ export default class Statement {
if ( isFunctionDeclaration( node, parent ) ) writeDepth += 1;
if ( /Function/.test( node.type ) && !isIife( node, parent ) ) readDepth += 1;
// If this is a top-level call expression, or an assignment to a global,
// this statement will need to be marked
if ( !readDepth ) {
if ( node.type === 'CallExpression' ) {
this.hasSideEffects = true;
} else if ( node.type in modifierNodes ) {
let subject = node[ modifierNodes[ node.type ] ];
while ( subject.type === 'MemberExpression' ) subject = subject.object;
if ( !this.module.locals.defines( subject.name ) ) this.hasSideEffects = true;
}
}
if ( node._scope ) scope = node._scope;
this.checkForReads( scope, node, parent, !readDepth );

Loading…
Cancel
Save