diff --git a/src/Bundle.js b/src/Bundle.js index 1b9834e..8800cd1 100644 --- a/src/Bundle.js +++ b/src/Bundle.js @@ -51,6 +51,7 @@ export default class Bundle { this.entryModule = entryModule; this.modules.forEach( module => module.bindImportSpecifiers() ); + this.modules.forEach( module => module.bindAliases() ); this.modules.forEach( module => module.bindReferences() ); // mark all export statements diff --git a/src/ExternalModule.js b/src/ExternalModule.js index f0d3408..48d0160 100644 --- a/src/ExternalModule.js +++ b/src/ExternalModule.js @@ -8,6 +8,10 @@ class ExternalDeclaration { this.isExternal = true; } + addAlias () { + // noop + } + addReference ( reference ) { reference.declaration = this; diff --git a/src/Module.js b/src/Module.js index e6961a2..dbadbbf 100644 --- a/src/Module.js +++ b/src/Module.js @@ -16,6 +16,11 @@ class SyntheticDefaultDeclaration { this.original = null; this.isExported = false; + this.aliases = []; + } + + addAlias ( declaration ) { + this.aliases.push( declaration ); } addReference ( reference ) { @@ -36,6 +41,8 @@ class SyntheticDefaultDeclaration { use () { this.isUsed = true; this.statement.mark(); + + this.aliases.forEach( alias => alias.use() ); } } @@ -45,6 +52,7 @@ class SyntheticNamespaceDeclaration { this.name = null; this.needsNamespaceBlock = false; + this.aliases = []; this.originals = blank(); module.getExports().forEach( name => { @@ -52,6 +60,10 @@ class SyntheticNamespaceDeclaration { }); } + addAlias ( declaration ) { + this.aliases.push( declaration ); + } + addReference ( reference ) { // if we have e.g. `foo.bar`, we can optimise // the reference by pointing directly to `bar` @@ -102,7 +114,8 @@ class SyntheticNamespaceDeclaration { } use () { - // noop + // noop? + this.aliases.forEach( alias => alias.use() ); } } @@ -287,6 +300,21 @@ export default class Module { return makeLegalIdentifier( basename( this.id ).slice( 0, -extname( this.id ).length ) ); } + bindAliases () { + keys( this.declarations ).forEach( name => { + const declaration = this.declarations[ name ]; + const statement = declaration.statement; + if ( statement.node.type !== 'VariableDeclaration' ) return; + + statement.references.forEach( reference => { + if ( reference.name === name || !reference.isImmediatelyUsed ) return; + + const otherDeclaration = this.trace( reference.name ); + if ( otherDeclaration ) otherDeclaration.addAlias( declaration ); + }); + }); + } + bindImportSpecifiers () { [ this.imports, this.reexports ].forEach( specifiers => { keys( specifiers ).forEach( name => { diff --git a/src/ast/Scope.js b/src/ast/Scope.js index 64c90be..b32bbb6 100644 --- a/src/ast/Scope.js +++ b/src/ast/Scope.js @@ -39,6 +39,11 @@ class Declaration { this.name = null; this.isReassigned = false; + this.aliases = []; + } + + addAlias ( declaration ) { + this.aliases.push( declaration ); } addReference ( reference ) { @@ -58,6 +63,8 @@ class Declaration { use () { this.isUsed = true; if ( this.statement ) this.statement.mark(); + + this.aliases.forEach( alias => alias.use() ); } } diff --git a/test/function/tracks-alias-mutations/_config.js b/test/function/tracks-alias-mutations/_config.js index c3a0619..f2faaad 100644 --- a/test/function/tracks-alias-mutations/_config.js +++ b/test/function/tracks-alias-mutations/_config.js @@ -1,4 +1,3 @@ module.exports = { - description: 'tracks mutations of aliased objects', - skip: true + description: 'tracks mutations of aliased objects' };