Browse Source

order methods alphabetically. easier to find what youre looking for

contingency-plan
Rich Harris 10 years ago
parent
commit
33effb4b3b
  1. 230
      src/Bundle.js
  2. 8
      src/ExternalModule.js
  3. 138
      src/Module.js
  4. 10
      src/ast/Scope.js

230
src/Bundle.js

@ -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;
}
}

8
src/ExternalModule.js

@ -15,6 +15,10 @@ export default class ExternalModule {
this.needsNamed = false;
}
findDefiningStatement () {
return null;
}
getCanonicalName ( name ) {
if ( name === 'default' ) {
return this.needsNamed ? `${this.name}__default` : this.name;
@ -37,8 +41,4 @@ export default class ExternalModule {
this.suggestedNames[ exportName ] = suggestion;
}
}
findDefiningStatement () {
return null;
}
}

138
src/Module.js

@ -271,75 +271,6 @@ export default class Module {
return { strongDependencies, weakDependencies };
}
findDeclaration ( localName ) {
const importDeclaration = this.imports[ localName ];
// name was defined by another module
if ( importDeclaration ) {
const module = importDeclaration.module;
if ( module.isExternal ) return null;
const exportDeclaration = module.exports[ importDeclaration.name ];
return module.findDeclaration( exportDeclaration.localName );
}
// name was defined by this module, if any
let i = this.statements.length;
while ( i-- ) {
const declaration = this.statements[i].scope.declarations[ localName ];
if ( declaration ) {
return declaration;
}
}
return null;
}
getCanonicalName ( localName ) {
// Special case
if ( localName === 'default' && ( this.exports.default.isModified || !this.suggestedNames.default ) ) {
let canonicalName = makeLegalIdentifier( this.id.replace( dirname( this.bundle.entryModule.id ) + '/', '' ).replace( /\.js$/, '' ) );
return deconflict( canonicalName, this.definitions );
}
if ( this.suggestedNames[ localName ] ) {
localName = this.suggestedNames[ localName ];
}
if ( !this.canonicalNames[ localName ] ) {
let canonicalName;
if ( this.imports[ localName ] ) {
const importDeclaration = this.imports[ localName ];
const module = importDeclaration.module;
if ( importDeclaration.name === '*' ) {
canonicalName = module.suggestedNames[ '*' ];
} else {
let exporterLocalName;
if ( module.isExternal ) {
exporterLocalName = importDeclaration.name;
} else {
const exportDeclaration = module.exports[ importDeclaration.name ];
exporterLocalName = exportDeclaration.localName;
}
canonicalName = module.getCanonicalName( exporterLocalName );
}
}
else {
canonicalName = localName;
}
this.canonicalNames[ localName ] = canonicalName;
}
return this.canonicalNames[ localName ];
}
define ( name ) {
// shortcut cycles. TODO this won't work everywhere...
if ( this.definitionPromises[ name ] ) {
@ -507,6 +438,75 @@ export default class Module {
});
}
findDeclaration ( localName ) {
const importDeclaration = this.imports[ localName ];
// name was defined by another module
if ( importDeclaration ) {
const module = importDeclaration.module;
if ( module.isExternal ) return null;
const exportDeclaration = module.exports[ importDeclaration.name ];
return module.findDeclaration( exportDeclaration.localName );
}
// name was defined by this module, if any
let i = this.statements.length;
while ( i-- ) {
const declaration = this.statements[i].scope.declarations[ localName ];
if ( declaration ) {
return declaration;
}
}
return null;
}
getCanonicalName ( localName ) {
// Special case
if ( localName === 'default' && ( this.exports.default.isModified || !this.suggestedNames.default ) ) {
let canonicalName = makeLegalIdentifier( this.id.replace( dirname( this.bundle.entryModule.id ) + '/', '' ).replace( /\.js$/, '' ) );
return deconflict( canonicalName, this.definitions );
}
if ( this.suggestedNames[ localName ] ) {
localName = this.suggestedNames[ localName ];
}
if ( !this.canonicalNames[ localName ] ) {
let canonicalName;
if ( this.imports[ localName ] ) {
const importDeclaration = this.imports[ localName ];
const module = importDeclaration.module;
if ( importDeclaration.name === '*' ) {
canonicalName = module.suggestedNames[ '*' ];
} else {
let exporterLocalName;
if ( module.isExternal ) {
exporterLocalName = importDeclaration.name;
} else {
const exportDeclaration = module.exports[ importDeclaration.name ];
exporterLocalName = exportDeclaration.localName;
}
canonicalName = module.getCanonicalName( exporterLocalName );
}
}
else {
canonicalName = localName;
}
this.canonicalNames[ localName ] = canonicalName;
}
return this.canonicalNames[ localName ];
}
rename ( name, replacement ) {
this.canonicalNames[ name ] = replacement;
}

10
src/ast/Scope.js

@ -43,11 +43,6 @@ export default class Scope {
}
}
getDeclaration ( name ) {
return this.declarations[ name ] ||
this.parent && this.parent.getDeclaration( name );
}
contains ( name ) {
return !!this.getDeclaration( name );
}
@ -63,4 +58,9 @@ export default class Scope {
return null;
}
getDeclaration ( name ) {
return this.declarations[ name ] ||
this.parent && this.parent.getDeclaration( name );
}
}

Loading…
Cancel
Save