Browse Source

more efficient dependency fetching

contingency-plan
Rich-Harris 10 years ago
parent
commit
477324e753
  1. 27
      src/Bundle.js
  2. 50
      src/Module.js

27
src/Bundle.js

@ -197,29 +197,23 @@ export default class Bundle {
this.modules.push( module ); this.modules.push( module );
this.moduleById[ id ] = module; this.moduleById[ id ] = module;
const promises = this.fetchAllModules( module, module.imports ) return this.fetchAllDependencies( module ).then( () => module );
.concat( this.fetchAllModules( module, module.reexports ) );
return Promise.all( promises ).then( () => module );
}); });
} }
fetchAllModules ( module, specifiers ) { fetchAllDependencies ( module ) {
return keys( specifiers ) const promises = module.dependencies.map( source => {
.map( name => { return Promise.resolve( this.resolveId( source, module.id, this.resolveOptions ) )
const specifier = specifiers[ name ];
return Promise.resolve( this.resolveId( specifier.source, module.id, this.resolveOptions ) )
.then( resolvedId => { .then( resolvedId => {
module.resolvedIds[ source ] = resolvedId || source;
// external module // external module
if ( !resolvedId ) { if ( !resolvedId ) {
if ( !this.moduleById[ specifier.source ] ) { if ( !this.moduleById[ source ] ) {
const module = new ExternalModule( specifier.source ); const module = new ExternalModule( source );
this.externalModules.push( module ); this.externalModules.push( module );
this.moduleById[ specifier.source ] = module; this.moduleById[ source ] = module;
} }
specifier.module = this.moduleById[ specifier.source ];
} }
else if ( resolvedId === module.id ) { else if ( resolvedId === module.id ) {
@ -227,11 +221,12 @@ export default class Bundle {
} }
else { else {
specifier.id = resolvedId;
return this.fetchModule( resolvedId ); return this.fetchModule( resolvedId );
} }
}); });
}); });
return Promise.all( promises );
} }
markAllModifierStatements () { markAllModifierStatements () {

50
src/Module.js

@ -52,7 +52,12 @@ export default class Module {
this.statements = this.parse( ast ); this.statements = this.parse( ast );
// imports and exports, indexed by ID // all dependencies
this.dependencies = [];
this.resolvedIds = blank();
this.boundImportSpecifiers = false;
// imports and exports, indexed by local name
this.imports = blank(); this.imports = blank();
this.exports = blank(); this.exports = blank();
this.reexports = blank(); this.reexports = blank();
@ -80,6 +85,8 @@ export default class Module {
// export { name } from './other' // export { name } from './other'
if ( source ) { if ( source ) {
if ( !~this.dependencies.indexOf( source ) ) this.dependencies.push( source );
if ( node.type === 'ExportAllDeclaration' ) { if ( node.type === 'ExportAllDeclaration' ) {
// Store `export * from '...'` statements in an array of delegates. // Store `export * from '...'` statements in an array of delegates.
// When an unknown import is encountered, we see if one of them can satisfy it. // When an unknown import is encountered, we see if one of them can satisfy it.
@ -168,6 +175,8 @@ export default class Module {
const node = statement.node; const node = statement.node;
const source = node.source.value; const source = node.source.value;
if ( !~this.dependencies.indexOf( source ) ) this.dependencies.push( source );
node.specifiers.forEach( specifier => { node.specifiers.forEach( specifier => {
const isDefault = specifier.type === 'ImportDefaultSpecifier'; const isDefault = specifier.type === 'ImportDefaultSpecifier';
const isNamespace = specifier.type === 'ImportNamespaceSpecifier'; const isNamespace = specifier.type === 'ImportNamespaceSpecifier';
@ -226,16 +235,26 @@ export default class Module {
} }
bindImportSpecifiers () { bindImportSpecifiers () {
if ( this.boundImportSpecifiers ) return;
this.boundImportSpecifiers = true;
[ this.imports, this.reexports ].forEach( specifiers => { [ this.imports, this.reexports ].forEach( specifiers => {
keys( specifiers ).forEach( name => { keys( specifiers ).forEach( name => {
const specifier = specifiers[ name ]; const specifier = specifiers[ name ];
if ( specifier.module ) return; if ( specifier.module ) return;
specifier.module = this.bundle.moduleById[ specifier.id ]; const id = this.resolvedIds[ specifier.source ];
specifier.module.bindImportSpecifiers(); specifier.module = this.bundle.moduleById[ id ];
}); });
}); });
this.dependencies.forEach( source => {
const id = this.resolvedIds[ source ];
const module = this.bundle.moduleById[ id ];
if ( !module.isExternal ) module.bindImportSpecifiers();
});
} }
consolidateDependencies () { consolidateDependencies () {
@ -249,9 +268,12 @@ export default class Module {
} }
this.statements.forEach( statement => { this.statements.forEach( statement => {
if ( statement.isImportDeclaration && !statement.node.specifiers.length && !statement.module.isExternal ) { if ( statement.isImportDeclaration && !statement.node.specifiers.length ) {
// include module for its side-effects // include module for its side-effects
strongDependencies[ statement.module.id ] = statement.module; // TODO is this right? `statement.module` should be `this`, surely? const id = this.resolvedIds[ statement.node.source.value ];
const module = this.bundle.moduleById[ id ];
if ( !module.isExternal ) strongDependencies[ module.id ] = module;
} }
else if ( statement.isReexportDeclaration ) { else if ( statement.isReexportDeclaration ) {
@ -390,20 +412,12 @@ export default class Module {
if ( statement.isImportDeclaration ) { if ( statement.isImportDeclaration ) {
// ...unless they're empty, in which case assume we're importing them for the side-effects // ...unless they're empty, in which case assume we're importing them for the side-effects
// THIS IS NOT FOOLPROOF. Probably need /*rollup: include */ or similar // THIS IS NOT FOOLPROOF. Probably need /*rollup: include */ or similar
if ( !statement.node.specifiers.length ) {
const id = this.resolvedIds[ statement.node.source.value ];
const otherModule = this.bundle.moduleById[ id ];
// TODO... if ( !otherModule.isExternal ) otherModule.markAllStatements();
// if ( !statement.node.specifiers.length ) { }
// return this.bundle.fetchModule( statement.node.source.value, this.id )
// .then( module => {
// statement.module = module;
// if ( module.isExternal ) {
// return;
// }
// return module.markAllStatements();
// });
// }
//
// return;
} }
// skip `export { foo, bar, baz }`... // skip `export { foo, bar, baz }`...

Loading…
Cancel
Save