Skip to content

Commit

Permalink
default exports are not bound. fixes #15
Browse files Browse the repository at this point in the history
  • Loading branch information
Rich-Harris committed Jun 5, 2015
1 parent f60120b commit c0a7640
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 5 deletions.
7 changes: 7 additions & 0 deletions src/Bundle.js
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,13 @@ export default class Bundle {
let previousIndex = -1;
let previousMargin = 0;

// within a module, statements should preserve their original order
// TODO is this foolproof?
this.statements.sort( ( a, b ) => {
if ( a.module !== b.module ) return -1; // no change
return a.index - b.index;
});

this.statements.forEach( statement => {
// skip `export { foo, bar, baz }`
if ( statement.node.type === 'ExportNamedDeclaration' && statement.node.specifiers.length ) {
Expand Down
17 changes: 15 additions & 2 deletions src/Module.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,16 @@ export default class Module {
if ( node.type === 'ExportDefaultDeclaration' ) {
const isDeclaration = /Declaration$/.test( node.declaration.type );
const declaredName = isDeclaration && node.declaration.id.name;
const identifier = node.declaration.type === 'Identifier' && node.declaration.name;

this.exports.default = {
statement,
name: 'default',
localName: declaredName || 'default',
declaredName,
isDeclaration
identifier,
isDeclaration,
isModified: false // in case of `export default foo; foo = somethingElse`
};
}

Expand Down Expand Up @@ -207,6 +210,16 @@ export default class Module {
}

getCanonicalName ( localName ) {
// Special case
if ( localName === 'default' && this.exports.default && this.exports.default.isModified ) {
let canonicalName = makeLegalIdentifier( this.path.replace( this.bundle.base + '/', '' ).replace( /\.js$/, '' ) );
while ( this.definitions[ canonicalName ] ) {
canonicalName = `_${canonicalName}`;
}

return canonicalName;
}

if ( this.suggestedNames[ localName ] ) {
localName = this.suggestedNames[ localName ];
}
Expand Down Expand Up @@ -358,7 +371,7 @@ export default class Module {
if ( !statement.node.specifiers.length ) {
return this.bundle.fetchModule( statement.node.source.value, this.path )
.then( module => {
statement.module = module; // TODO what is this for? what does it do? why not _module?
statement.module = module;
return module.expandAllStatements();
})
.then( statements => {
Expand Down
11 changes: 11 additions & 0 deletions src/Statement.js
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,17 @@ export default class Statement {
return;
}

// special case = `export default foo; foo += 1;` - we'll
// need to assign a new variable so that the exported
// value is not updated by the second statement
if ( this.module.exports.default && this.module.exports.default.identifier === node.name ) {
// but only if this is a) inside a function body or
// b) after the export declaration
if ( !!scope.parent || node.start > this.module.exports.default.statement.node.start ) {
this.module.exports.default.isModified = true;
}
}

this.modifies[ node.name ] = true;
};

Expand Down
3 changes: 1 addition & 2 deletions test/function/default-export-is-not-bound/_config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
module.exports = {
description: 'does not bind default exports',
skip: true
description: 'does not bind default exports'
};

// test copied from https://github.com/esnext/es6-module-transpiler/tree/master/test/examples/export-default
2 changes: 1 addition & 1 deletion test/function/default-export-is-not-bound/main.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import value from './foo';
import { change } from './foo';

assert.equal(value, 42);
assert.equal( value, 42 );
change();
assert.equal( value, 42, 'default export should not be bound' );

0 comments on commit c0a7640

Please sign in to comment.