Browse Source

Added `mark()` method to identifiers.

* Removed Module's `mark( name )` and `markExport( name, module )`
* Added `mark()` to Modules
gh-109
Oskar Segersvärd 9 years ago
parent
commit
616a5ce306
  1. 11
      src/ExternalModule.js
  2. 70
      src/Module.js
  3. 38
      src/Statement.js

11
src/ExternalModule.js

@ -39,7 +39,10 @@ export default class ExternalModule {
originalName: name,
name,
module: this
module: this,
mark: () => {
this.importedByBundle[ name ] = true;
}
});
}
@ -47,5 +50,9 @@ export default class ExternalModule {
};
}
markExport () {}
// External modules are always marked for inclusion in the bundle.
// Marking an external module signals its use as a namespace.
mark () {
this.needsAll = true;
}
}

70
src/Module.js

@ -144,10 +144,14 @@ export default class Module {
// Always define a new `Identifier` for the default export.
this.exports.define( 'default', {
originalName: name,
originalName: 'default',
name,
module: this,
mark () {
this.isUsed = true;
this.statement.mark();
},
statement,
// Keep the identifier name, if one exists.
@ -194,6 +198,10 @@ export default class Module {
name,
module: this,
mark () {
this.isUsed = true;
this.statement.mark();
},
statement,
localName: name,
expression: declaration
@ -259,7 +267,11 @@ export default class Module {
name,
statement,
module: this
module: this,
mark () {
this.isUsed = true;
this.statement.mark();
}
});
});
@ -296,7 +308,11 @@ export default class Module {
// For each name we depend on that isn't in scope,
// add a new global and bind the local name to it.
if ( !this.locals.inScope( name ) ) {
this.bundle.globals.define( name );
this.bundle.globals.define( name, {
originalName: name,
name,
mark () {}
});
this.locals.bind( name, this.bundle.globals.reference( name ) );
}
});
@ -383,6 +399,8 @@ export default class Module {
// Enforce dynamic access of the module's properties.
dynamicAccess () {
if ( this.needsDynamicAccess ) return;
this.needsDynamicAccess = true;
this.markAllExportStatements();
@ -395,20 +413,8 @@ export default class Module {
return this.bundle.moduleById[ this.resolvedIds[ source ] ];
}
mark ( name ) {
const id = this.locals.lookup( name );
if ( id && id.module ) {
if ( id.module.isExternal ) {
id.module.importedByBundle[ id.originalName ] = true;
}
if ( id.statement ) {
// Assert that statement is defined. It isn't for external modules.
id.isUsed = true;
id.statement.mark();
}
}
mark () {
this.dynamicAccess();
}
markAllStatements ( isEntryModule ) {
@ -436,7 +442,7 @@ export default class Module {
else {
// Be sure to mark the default export for the entry module.
if ( isEntryModule && statement.node.type === 'ExportDefaultDeclaration' ) {
this.markExport( 'default', this );
this.exports.lookup( 'default' ).mark();
}
statement.mark();
@ -450,34 +456,6 @@ export default class Module {
});
}
markExport ( name, importer ) {
const id = this.exports.lookup( name );
if ( id ) {
id.isUsed = true;
// Assert that statement is defined. It isn't for external modules.
if ( id.statement ) id.statement.mark();
return;
}
for ( const module of this.exportAlls ) {
const id = module.exports.lookup( name );
if ( id ) {
id.isUsed = true;
// Assert that statement is defined. It isn't for external modules.
if ( id.statement ) id.statement.mark();
return;
}
}
throw new Error( `Module ${this.id} does not export ${name} (imported by ${importer.id})` );
}
parse ( ast ) {
// The ast can be supplied programmatically (but usually won't be)
if ( !ast ) {

38
src/Statement.js

@ -151,6 +151,7 @@ export default class Statement {
if ( node._scope ) scope = scope.parent;
// Optimize namespace lookups, which manifests as MemberExpressions.
if ( node.type === 'MemberExpression' && ( !currentMemberExpression || node.object === currentMemberExpression ) ) {
currentMemberExpression = node;
@ -162,9 +163,20 @@ export default class Statement {
namespace = id;
}
const name = node.property.name || ( node.property.type === 'Literal' ? node.property.value : null );
// Extract the name of the accessed property, from and Identifier or Literal.
// Any eventual Literal value is converted to a string.
const name = node.property.name ||
( node.property.type === 'Literal' ? String( node.property.value ) : null );
if ( !name ) {
// If we can't resolve the name being accessed,
// we require the namespace to be dynamically accessible.
//
// // resolvable
// console.log( javascript.keywords[ 6 ] )
//
// // unresolvable
// console.log( javascript.keywords[ 1 + 5 ] )
if ( name === null ) {
namespace.dynamicAccess();
namespace = null;
@ -312,31 +324,21 @@ export default class Statement {
// `export { name } from './other'` is a special case
if ( this.isReexportDeclaration ) {
const otherModule = this.module.getModule( this.node.source.value );
// TODO: If we add the specifiers to `dependantIds`,
// we can remove this special case.
this.node.specifiers.forEach( specifier => {
otherModule.markExport( specifier.local.name, this.module );
this.module.exports.lookup( specifier.exported.name ).mark();
});
return;
}
this.dependantIds.forEach( id => {
// FIXME: what should be done about modules?
if ( id.isModule ) {
if ( id.isExternal ) {
} else {
}
}
id.module && id.module.markExport( id.originalName, this.module );
});
this.dependantIds.forEach( id => id.mark() );
// TODO: perhaps these could also be added?
keys( this.dependsOn ).forEach( name => {
if ( this.defines[ name ] ) return; // TODO maybe exclude from `this.dependsOn` in the first place?
this.module.mark( name );
this.module.locals.lookup( name ).mark();
});
}

Loading…
Cancel
Save