Browse Source

Started on default exports.

gh-109
Oskar Segersvärd 10 years ago
parent
commit
510a75ae69
  1. 62
      src/Module.js
  2. 4
      src/Statement.js

62
src/Module.js

@ -102,24 +102,24 @@ export default class Module {
node.declaration.name : node.declaration.name :
null; null;
if ( identifier ) { // Always define a new `Identifier` for the default export.
// If the default export has an identifier, bind to it. this.exports.define( 'default', {
this.exports.bind( 'default', this.locals.reference( identifier ) ); originalName: this.name,
} else { name: this.name,
this.exports.define( 'default', {
originalName: this.name, module: this,
name: this.name, statement,
localName: 'default',
identifier,
isDeclaration,
isAnonymous,
isModified: false // in case of `export default foo; foo = somethingElse`
});
module: this, // If it was assigned by an identifier, remember which one, in case it doesn't get modified.
statement, if ( identifier ) {
localName: 'default', this.defaultIdentifier = identifier;
identifier,
isDeclaration,
isAnonymous,
isModified: false // in case of `export default foo; foo = somethingElse`
});
} }
} }
// export { foo, bar, baz } // export { foo, bar, baz }
@ -253,12 +253,22 @@ export default class Module {
}); });
keys( statement.dependsOn ).forEach( name => { keys( statement.dependsOn ).forEach( name => {
// 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 ) ) { if ( !this.locals.inScope( name ) ) {
this.bundle.globals.define( name ); this.bundle.globals.define( name );
this.locals.bind( name, this.bundle.globals.reference( name ) ); this.locals.bind( name, this.bundle.globals.reference( name ) );
} }
}); });
}); });
// OPTIMIZATION!
// If we have a default export and it's value is never modified,
// bind to it directly.
const def = this.exports.lookup( 'default' );
if ( def && !def.isModified && this.defaultIdentifier ) {
this.exports.bind( 'default', this.locals.reference( this.defaultIdentifier ) );
}
} }
// Returns the set of imported module ids by going through all import/exports statements. // Returns the set of imported module ids by going through all import/exports statements.
@ -344,6 +354,7 @@ export default class Module {
if ( id && id.statement ) { if ( id && id.statement ) {
// Assert that statement is defined. It isn't for external modules. // Assert that statement is defined. It isn't for external modules.
id.isUsed = true;
id.statement.mark(); id.statement.mark();
} }
} }
@ -371,6 +382,11 @@ export default class Module {
// include everything else // include everything else
else { else {
// Be sure to mark the default export for the entry module.
if ( isEntryModule && statement.node.type === 'ExportDefaultDeclaration' ) {
this.markExport( 'default', null, this );
}
statement.mark(); statement.mark();
} }
}); });
@ -386,6 +402,8 @@ export default class Module {
const id = this.exports.lookup( name ); const id = this.exports.lookup( name );
if ( id ) { if ( id ) {
id.isUsed = true;
// Assert that statement is defined. It isn't for external modules. // Assert that statement is defined. It isn't for external modules.
if ( id.statement ) id.statement.mark(); if ( id.statement ) id.statement.mark();
@ -396,6 +414,8 @@ export default class Module {
const id = module.exports.lookup( name ); const id = module.exports.lookup( name );
if ( id ) { if ( id ) {
id.isUsed = true;
// Assert that statement is defined. It isn't for external modules. // Assert that statement is defined. It isn't for external modules.
if ( id.statement ) id.statement.mark(); if ( id.statement ) id.statement.mark();
@ -576,25 +596,25 @@ export default class Module {
} }
else if ( statement.node.type === 'ExportDefaultDeclaration' ) { else if ( statement.node.type === 'ExportDefaultDeclaration' ) {
const canonicalName = this.defaultName(); const def = this.exports.lookup( 'default' );
// FIXME: dunno what to do here yet. // FIXME: dunno what to do here yet.
if ( statement.node.declaration.type === 'Identifier' && canonicalName === ( replacements[ statement.node.declaration.name ] || statement.node.declaration.name ) ) { if ( statement.node.declaration.type === 'Identifier' && def.name === ( replacements[ statement.node.declaration.name ] || statement.node.declaration.name ) ) {
magicString.remove( statement.start, statement.next ); magicString.remove( statement.start, statement.next );
return; return;
} }
// prevent `var undefined = sideEffectyDefault(foo)` // prevent `var undefined = sideEffectyDefault(foo)`
if ( canonicalName === undefined ) { if ( !def.isUsed ) {
magicString.remove( statement.start, statement.node.declaration.start ); magicString.remove( statement.start, statement.node.declaration.start );
return; return;
} }
// anonymous functions should be converted into declarations // anonymous functions should be converted into declarations
if ( statement.node.declaration.type === 'FunctionExpression' ) { if ( statement.node.declaration.type === 'FunctionExpression' ) {
magicString.overwrite( statement.node.start, statement.node.declaration.start + 8, `function ${canonicalName}` ); magicString.overwrite( statement.node.start, statement.node.declaration.start + 8, `function ${def.name}` );
} else { } else {
magicString.overwrite( statement.node.start, statement.node.declaration.start, `var ${canonicalName} = ` ); magicString.overwrite( statement.node.start, statement.node.declaration.start, `var ${def.name} = ` );
} }
} }

4
src/Statement.js

@ -208,7 +208,7 @@ export default class Statement {
// need to assign a new variable so that the exported // need to assign a new variable so that the exported
// value is not updated by the second statement // value is not updated by the second statement
const def = this.module.exports.lookup( 'default' ); const def = this.module.exports.lookup( 'default' );
if ( def && depth === 0 && def.identifier === node.name ) { if ( def && depth === 0 && def.name === node.name ) {
// but only if this is a) inside a function body or // but only if this is a) inside a function body or
// b) after the export declaration // b) after the export declaration
if ( !!scope.parent || node.start > def.statement.node.start ) { if ( !!scope.parent || node.start > def.statement.node.start ) {
@ -266,7 +266,7 @@ export default class Statement {
const otherModule = this.module.getModule( this.node.source.value ); const otherModule = this.module.getModule( this.node.source.value );
this.node.specifiers.forEach( specifier => { this.node.specifiers.forEach( specifier => {
otherModule.exports.lookup( specifier.local.name ).statement.mark(); otherModule.markExport( specifier.local.name, null, this.module );
}); });
return; return;

Loading…
Cancel
Save