|
|
@ -51,39 +51,6 @@ export default class Bundle { |
|
|
|
this.assumedGlobals = blank(); |
|
|
|
} |
|
|
|
|
|
|
|
fetchModule ( importee, importer ) { |
|
|
|
return Promise.resolve( this.resolveId( importee, importer, this.resolveOptions ) ) |
|
|
|
.then( id => { |
|
|
|
if ( !id ) { |
|
|
|
// external module
|
|
|
|
if ( !this.modulePromises[ importee ] ) { |
|
|
|
const module = new ExternalModule( importee ); |
|
|
|
this.externalModules.push( module ); |
|
|
|
this.modulePromises[ importee ] = Promise.resolve( module ); |
|
|
|
} |
|
|
|
|
|
|
|
return this.modulePromises[ importee ]; |
|
|
|
} |
|
|
|
|
|
|
|
if ( !this.modulePromises[ id ] ) { |
|
|
|
this.modulePromises[ id ] = Promise.resolve( this.load( id, this.loadOptions ) ) |
|
|
|
.then( source => { |
|
|
|
const module = new Module({ |
|
|
|
id, |
|
|
|
source, |
|
|
|
bundle: this |
|
|
|
}); |
|
|
|
|
|
|
|
this.modules.push( module ); |
|
|
|
|
|
|
|
return module; |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
return this.modulePromises[ id ]; |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
build () { |
|
|
|
// bring in top-level AST nodes from the entry module
|
|
|
|
return this.fetchModule( this.entry, undefined ) |
|
|
@ -213,96 +180,37 @@ export default class Bundle { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
sort () { |
|
|
|
let seen = {}; |
|
|
|
let ordered = []; |
|
|
|
let hasCycles; |
|
|
|
|
|
|
|
let strongDeps = {}; |
|
|
|
let stronglyDependsOn = {}; |
|
|
|
|
|
|
|
function visit ( module ) { |
|
|
|
seen[ module.id ] = true; |
|
|
|
|
|
|
|
const { strongDependencies, weakDependencies } = module.consolidateDependencies(); |
|
|
|
|
|
|
|
strongDeps[ module.id ] = []; |
|
|
|
stronglyDependsOn[ module.id ] = {}; |
|
|
|
|
|
|
|
keys( strongDependencies ).forEach( id => { |
|
|
|
const imported = strongDependencies[ id ]; |
|
|
|
|
|
|
|
strongDeps[ module.id ].push( imported ); |
|
|
|
|
|
|
|
if ( seen[ id ] ) { |
|
|
|
// we need to prevent an infinite loop, and note that
|
|
|
|
// we need to check for strong/weak dependency relationships
|
|
|
|
hasCycles = true; |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
visit( imported ); |
|
|
|
}); |
|
|
|
|
|
|
|
keys( weakDependencies ).forEach( id => { |
|
|
|
const imported = weakDependencies[ id ]; |
|
|
|
fetchModule ( importee, importer ) { |
|
|
|
return Promise.resolve( this.resolveId( importee, importer, this.resolveOptions ) ) |
|
|
|
.then( id => { |
|
|
|
if ( !id ) { |
|
|
|
// external module
|
|
|
|
if ( !this.modulePromises[ importee ] ) { |
|
|
|
const module = new ExternalModule( importee ); |
|
|
|
this.externalModules.push( module ); |
|
|
|
this.modulePromises[ importee ] = Promise.resolve( module ); |
|
|
|
} |
|
|
|
|
|
|
|
if ( seen[ id ] ) { |
|
|
|
// we need to prevent an infinite loop, and note that
|
|
|
|
// we need to check for strong/weak dependency relationships
|
|
|
|
hasCycles = true; |
|
|
|
return; |
|
|
|
return this.modulePromises[ importee ]; |
|
|
|
} |
|
|
|
|
|
|
|
visit( imported ); |
|
|
|
}); |
|
|
|
|
|
|
|
// add second (and third...) order dependencies
|
|
|
|
function addStrongDependencies ( dependency ) { |
|
|
|
if ( stronglyDependsOn[ module.id ][ dependency.id ] ) return; |
|
|
|
|
|
|
|
stronglyDependsOn[ module.id ][ dependency.id ] = true; |
|
|
|
strongDeps[ dependency.id ].forEach( addStrongDependencies ); |
|
|
|
} |
|
|
|
|
|
|
|
strongDeps[ module.id ].forEach( addStrongDependencies ); |
|
|
|
|
|
|
|
ordered.push( module ); |
|
|
|
} |
|
|
|
|
|
|
|
visit( this.entryModule ); |
|
|
|
|
|
|
|
if ( hasCycles ) { |
|
|
|
let unordered = ordered; |
|
|
|
ordered = []; |
|
|
|
|
|
|
|
// unordered is actually semi-ordered, as [ fewer dependencies ... more dependencies ]
|
|
|
|
unordered.forEach( module => { |
|
|
|
// ensure strong dependencies of `module` that don't strongly depend on `module` go first
|
|
|
|
strongDeps[ module.id ].forEach( place ); |
|
|
|
if ( !this.modulePromises[ id ] ) { |
|
|
|
this.modulePromises[ id ] = Promise.resolve( this.load( id, this.loadOptions ) ) |
|
|
|
.then( source => { |
|
|
|
const module = new Module({ |
|
|
|
id, |
|
|
|
source, |
|
|
|
bundle: this |
|
|
|
}); |
|
|
|
|
|
|
|
function place ( dep ) { |
|
|
|
if ( !stronglyDependsOn[ dep.id ][ module.id ] && !~ordered.indexOf( dep ) ) { |
|
|
|
strongDeps[ dep.id ].forEach( place ); |
|
|
|
ordered.push( dep ); |
|
|
|
} |
|
|
|
} |
|
|
|
this.modules.push( module ); |
|
|
|
|
|
|
|
if ( !~ordered.indexOf( module ) ) { |
|
|
|
ordered.push( module ); |
|
|
|
return module; |
|
|
|
}); |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
let statements = []; |
|
|
|
|
|
|
|
ordered.forEach( module => { |
|
|
|
module.statements.forEach( statement => { |
|
|
|
if ( statement.isIncluded ) statements.push( statement ); |
|
|
|
return this.modulePromises[ id ]; |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
return statements; |
|
|
|
} |
|
|
|
|
|
|
|
generate ( options = {} ) { |
|
|
@ -498,4 +406,96 @@ export default class Bundle { |
|
|
|
|
|
|
|
return { code, map }; |
|
|
|
} |
|
|
|
|
|
|
|
sort () { |
|
|
|
let seen = {}; |
|
|
|
let ordered = []; |
|
|
|
let hasCycles; |
|
|
|
|
|
|
|
let strongDeps = {}; |
|
|
|
let stronglyDependsOn = {}; |
|
|
|
|
|
|
|
function visit ( module ) { |
|
|
|
seen[ module.id ] = true; |
|
|
|
|
|
|
|
const { strongDependencies, weakDependencies } = module.consolidateDependencies(); |
|
|
|
|
|
|
|
strongDeps[ module.id ] = []; |
|
|
|
stronglyDependsOn[ module.id ] = {}; |
|
|
|
|
|
|
|
keys( strongDependencies ).forEach( id => { |
|
|
|
const imported = strongDependencies[ id ]; |
|
|
|
|
|
|
|
strongDeps[ module.id ].push( imported ); |
|
|
|
|
|
|
|
if ( seen[ id ] ) { |
|
|
|
// we need to prevent an infinite loop, and note that
|
|
|
|
// we need to check for strong/weak dependency relationships
|
|
|
|
hasCycles = true; |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
visit( imported ); |
|
|
|
}); |
|
|
|
|
|
|
|
keys( weakDependencies ).forEach( id => { |
|
|
|
const imported = weakDependencies[ id ]; |
|
|
|
|
|
|
|
if ( seen[ id ] ) { |
|
|
|
// we need to prevent an infinite loop, and note that
|
|
|
|
// we need to check for strong/weak dependency relationships
|
|
|
|
hasCycles = true; |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
visit( imported ); |
|
|
|
}); |
|
|
|
|
|
|
|
// add second (and third...) order dependencies
|
|
|
|
function addStrongDependencies ( dependency ) { |
|
|
|
if ( stronglyDependsOn[ module.id ][ dependency.id ] ) return; |
|
|
|
|
|
|
|
stronglyDependsOn[ module.id ][ dependency.id ] = true; |
|
|
|
strongDeps[ dependency.id ].forEach( addStrongDependencies ); |
|
|
|
} |
|
|
|
|
|
|
|
strongDeps[ module.id ].forEach( addStrongDependencies ); |
|
|
|
|
|
|
|
ordered.push( module ); |
|
|
|
} |
|
|
|
|
|
|
|
visit( this.entryModule ); |
|
|
|
|
|
|
|
if ( hasCycles ) { |
|
|
|
let unordered = ordered; |
|
|
|
ordered = []; |
|
|
|
|
|
|
|
// unordered is actually semi-ordered, as [ fewer dependencies ... more dependencies ]
|
|
|
|
unordered.forEach( module => { |
|
|
|
// ensure strong dependencies of `module` that don't strongly depend on `module` go first
|
|
|
|
strongDeps[ module.id ].forEach( place ); |
|
|
|
|
|
|
|
function place ( dep ) { |
|
|
|
if ( !stronglyDependsOn[ dep.id ][ module.id ] && !~ordered.indexOf( dep ) ) { |
|
|
|
strongDeps[ dep.id ].forEach( place ); |
|
|
|
ordered.push( dep ); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if ( !~ordered.indexOf( module ) ) { |
|
|
|
ordered.push( module ); |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
let statements = []; |
|
|
|
|
|
|
|
ordered.forEach( module => { |
|
|
|
module.statements.forEach( statement => { |
|
|
|
if ( statement.isIncluded ) statements.push( statement ); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
return statements; |
|
|
|
} |
|
|
|
} |
|
|
|