Browse Source

more fixes

declarations-and-references
Rich-Harris 9 years ago
parent
commit
e44d83df4d
  1. 75
      src/Bundle.js
  2. 38
      src/Module.js
  3. 8
      src/Statement.js
  4. 8
      src/finalisers/es6.js
  5. 11
      src/finalisers/shared/getExportBlock.js
  6. 3
      test/form/exports-at-end-if-possible/_config.js

75
src/Bundle.js

@ -49,6 +49,8 @@ export default class Bundle {
return Promise.resolve( this.resolveId( this.entry, undefined, this.resolveOptions ) ) return Promise.resolve( this.resolveId( this.entry, undefined, this.resolveOptions ) )
.then( id => this.fetchModule( id ) ) .then( id => this.fetchModule( id ) )
.then( entryModule => { .then( entryModule => {
this.entryModule = entryModule;
this.modules.forEach( module => { this.modules.forEach( module => {
module.bindImportSpecifiers(); module.bindImportSpecifiers();
module.bindReferences(); module.bindReferences();
@ -58,39 +60,8 @@ export default class Bundle {
module.markAllSideEffects(); module.markAllSideEffects();
}); });
const defaultExport = entryModule.exports.default; this.entryModule.markAllExportStatements();
this.entryModule = entryModule;
if ( defaultExport ) {
entryModule.needsDefault = true;
// `export default function foo () {...}` -
// use the declared name for the export
if ( defaultExport.identifier ) {
entryModule.suggestName( 'default', defaultExport.identifier );
}
// `export default a + b` - generate an export name
// based on the id of the entry module
else {
let defaultExportName = this.entryModule.basename();
// deconflict
let topLevelNames = [];
entryModule.statements.forEach( statement => {
keys( statement.defines ).forEach( name => topLevelNames.push( name ) );
});
while ( ~topLevelNames.indexOf( defaultExportName ) ) {
defaultExportName = `_${defaultExportName}`;
}
entryModule.suggestName( 'default', defaultExportName );
}
}
entryModule.markAllStatements( true );
this.markAllModifierStatements(); this.markAllModifierStatements();
this.orderedModules = this.sort(); this.orderedModules = this.sort();
@ -216,7 +187,7 @@ export default class Bundle {
throw new Error( `You must specify an output type - valid options are ${keys( finalisers ).join( ', ' )}` ); throw new Error( `You must specify an output type - valid options are ${keys( finalisers ).join( ', ' )}` );
} }
this.toExport = []; // TODO this.toExport = this.entryModule.getExports(); // TODO
magicString = finalise( this, magicString.trim(), { exportMode, indentString }, options ); magicString = finalise( this, magicString.trim(), { exportMode, indentString }, options );
if ( options.banner ) magicString.prepend( options.banner + '\n' ); if ( options.banner ) magicString.prepend( options.banner + '\n' );
@ -322,42 +293,4 @@ export default class Bundle {
return ordered; return ordered;
} }
trace ( module, localName, es6 ) {
const importDeclaration = module.imports[ localName ];
// defined in this module
if ( !importDeclaration ) return module.replacements[ localName ] || localName;
// defined elsewhere
return this.traceExport( importDeclaration.module, importDeclaration.name, es6 );
}
traceExport ( module, name, es6 ) {
if ( module.isExternal ) {
if ( name === 'default' ) return module.needsNamed && !es6 ? `${module.name}__default` : module.name;
if ( name === '*' ) return module.name;
return es6 ? name : `${module.name}.${name}`;
}
const reexportDeclaration = module.reexports[ name ];
if ( reexportDeclaration ) {
return this.traceExport( reexportDeclaration.module, reexportDeclaration.localName );
}
if ( name === '*' ) return module.replacements[ '*' ];
if ( name === 'default' ) return module.defaultName();
const exportDeclaration = module.exports[ name ];
if ( exportDeclaration ) return this.trace( module, exportDeclaration.localName );
for ( let i = 0; i < module.exportAlls.length; i += 1 ) {
const declaration = module.exportAlls[i];
if ( declaration.module.exports[ name ] ) {
return this.traceExport( declaration.module, name, es6 );
}
}
throw new Error( `Could not trace binding '${name}' from ${module.id}` );
}
} }

38
src/Module.js

@ -247,9 +247,9 @@ export default class Module {
const name = defaultExport.identifier && !defaultExport.isModified ? const name = defaultExport.identifier && !defaultExport.isModified ?
defaultExport.identifier : defaultExport.identifier :
this.replacements.default; this.basename(); // TODO should be deconflictable
return this.replacements[ name ] || name; return name;
} }
getExports () { getExports () {
@ -514,39 +514,45 @@ export default class Module {
this.statements.forEach( statement => { this.statements.forEach( statement => {
if ( !statement.isIncluded ) { if ( !statement.isIncluded ) {
magicString.remove( statement.start, statement.next ); magicString.remove( statement.start, statement.next );
return;
} }
statement.references.forEach( reference => { statement.references.forEach( reference => {
const declaration = reference.declaration; const declaration = reference.declaration;
if ( reference.declaration ) { if ( reference.declaration ) {
const { start, end } = reference.node; const { start } = reference.node;
const name = ( !es6 && declaration.isExternal ) ? const name = ( !es6 && declaration.isExternal ) ?
`${declaration.module.name}.${declaration.name}` : `${declaration.module.name}.${declaration.name}` :
declaration.name; declaration.name;
magicString.overwrite( start, end, name ); magicString.overwrite( start, start + reference.name.length, name );
} }
}); });
// modify exports as necessary // modify exports as necessary
if ( statement.isExportDeclaration ) { if ( statement.isExportDeclaration ) {
// remove `export` from `export var foo = 42`
if ( statement.node.type === 'ExportNamedDeclaration' && statement.node.declaration.type === 'VariableDeclaration' ) {
magicString.remove( statement.node.start, statement.node.declaration.start );
}
// remove `export` from `export class Foo {...}` or `export default Foo` // remove `export` from `export class Foo {...}` or `export default Foo`
// TODO default exports need different treatment // TODO default exports need different treatment
if ( statement.node.declaration.id ) { else if ( statement.node.declaration.id ) {
magicString.remove( statement.node.start, statement.node.declaration.start ); magicString.remove( statement.node.start, statement.node.declaration.start );
} }
// else if ( statement.node.type === 'ExportDefaultDeclaration' ) { else if ( statement.node.type === 'ExportDefaultDeclaration' ) {
// const defaultExport = this.exports.default; const defaultExport = this.exports.default;
//
// // 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 ${defaultExport.name}` ); magicString.overwrite( statement.node.start, statement.node.declaration.start + 8, `function ${this.defaultName()}` );
// } else { } else {
// magicString.overwrite( statement.node.start, statement.node.declaration.start, `var ${defaultExport.name} = ` ); magicString.overwrite( statement.node.start, statement.node.declaration.start, `var ${this.defaultName()} = ` );
// } }
// } }
else { else {
throw new Error( 'Unhandled export' ); throw new Error( 'Unhandled export' );
@ -586,7 +592,7 @@ export default class Module {
throw new Error( 'TODO default expression exports' ); throw new Error( 'TODO default expression exports' );
} }
return this.trace( exportDeclaration.name ); return this.trace( exportDeclaration.localName );
} }
// TODO export * // TODO export *

8
src/Statement.js

@ -123,7 +123,7 @@ export default class Statement {
// If this is a top-level call expression, or an assignment to a global, // If this is a top-level call expression, or an assignment to a global,
// this statement will need to be marked // this statement will need to be marked
if ( node.type === 'CallExpression' ) { if ( node.type === 'CallExpression' || node.type === 'NewExpression' ) {
statement.mark(); statement.mark();
} }
@ -131,10 +131,10 @@ export default class Statement {
let subject = node[ modifierNodes[ node.type ] ]; let subject = node[ modifierNodes[ node.type ] ];
while ( subject.type === 'MemberExpression' ) subject = subject.object; while ( subject.type === 'MemberExpression' ) subject = subject.object;
const bundle = statement.module.bundle; const declaration = statement.module.trace( subject.name );
const canonicalName = bundle.trace( statement.module, subject.name );
if ( bundle.assumedGlobals[ canonicalName ] ) statement.mark(); // global
if ( !declaration ) statement.mark();
} }
} }
}); });

8
src/finalisers/es6.js

@ -47,18 +47,18 @@ export default function es6 ( bundle, magicString ) {
const module = bundle.entryModule; const module = bundle.entryModule;
const specifiers = bundle.toExport.filter( notDefault ).map( name => { const specifiers = bundle.toExport.filter( notDefault ).map( name => {
const canonicalName = bundle.traceExport( module, name ); const declaration = module.traceExport( name );
return canonicalName === name ? return declaration.name === name ?
name : name :
`${canonicalName} as ${name}`; `${declaration.name} as ${name}`;
}); });
let exportBlock = specifiers.length ? `export { ${specifiers.join(', ')} };` : ''; let exportBlock = specifiers.length ? `export { ${specifiers.join(', ')} };` : '';
const defaultExport = module.exports.default || module.reexports.default; const defaultExport = module.exports.default || module.reexports.default;
if ( defaultExport ) { if ( defaultExport ) {
exportBlock += `export default ${bundle.traceExport(module,'default')};`; exportBlock += `export default ${module.traceExport( 'default' ).name};`;
} }
if ( exportBlock ) { if ( exportBlock ) {

11
src/finalisers/shared/getExportBlock.js

@ -1,18 +1,13 @@
export default function getExportBlock ( bundle, exportMode, mechanism = 'return' ) { export default function getExportBlock ( bundle, exportMode, mechanism = 'return' ) {
if ( exportMode === 'default' ) { if ( exportMode === 'default' ) {
const defaultExport = bundle.entryModule.exports.default; return `${mechanism} ${bundle.entryModule.defaultName()};`;
const defaultExportName = bundle.entryModule.replacements.default ||
defaultExport.identifier;
return `${mechanism} ${defaultExportName};`;
} }
return bundle.toExport return bundle.toExport
.map( name => { .map( name => {
const prop = name === 'default' ? `['default']` : `.${name}`; const prop = name === 'default' ? `['default']` : `.${name}`;
name = bundle.traceExport( bundle.entryModule, name ); const declaration = bundle.entryModule.traceExport( name );
return `exports${prop} = ${name};`; return `exports${prop} = ${declaration.name};`;
}) })
.join( '\n' ); .join( '\n' );
} }

3
test/form/exports-at-end-if-possible/_config.js

@ -2,6 +2,5 @@ module.exports = {
description: 'exports variables at end, if possible', description: 'exports variables at end, if possible',
options: { options: {
moduleName: 'myBundle' moduleName: 'myBundle'
}, }
// solo: true
}; };

Loading…
Cancel
Save