Browse Source

fix behaviour of export { foo as default } (#1078)

gh-1008
Rich-Harris 8 years ago
parent
commit
e05bf77efc
  1. 6
      src/Module.js
  2. 44
      src/ast/nodes/ExportNamedDeclaration.js
  3. 3
      test/function/default-export-as-is-bound/_config.js
  4. 7
      test/function/default-export-as-is-bound/foo.js
  5. 6
      test/function/default-export-as-is-bound/main.js
  6. 5
      test/function/export-as-default/_config.js
  7. 3
      test/function/export-as-default/foo.js
  8. 3
      test/function/export-as-default/main.js

6
src/Module.js

@ -173,13 +173,7 @@ export default class Module {
throw new Error( `A module cannot have multiple exports with the same name ('${exportedName}')` );
}
// `export { default as foo }` – special case. We want importers
// to use the UnboundDefaultExport proxy, not the original declaration
if ( exportedName === 'default' ) {
this.exports[ exportedName ] = { localName: 'default' };
} else {
this.exports[ exportedName ] = { localName };
}
});
} else {
this.bundle.onwarn( `Module ${this.id} has an empty export declaration` );

44
src/ast/nodes/ExportNamedDeclaration.js

@ -1,54 +1,10 @@
import { find } from '../../utils/array.js';
import Node from '../Node.js';
class UnboundDefaultExport {
constructor ( original ) {
this.original = original;
this.name = original.name;
}
activate () {
if ( this.activated ) return;
this.activated = true;
this.original.activate();
}
addReference ( reference ) {
this.name = reference.name;
this.original.addReference( reference );
}
bind ( scope ) {
this.original.bind( scope );
}
gatherPossibleValues ( values ) {
this.original.gatherPossibleValues( values );
}
getName ( es ) {
if ( this.original && !this.original.isReassigned ) {
return this.original.getName( es );
}
return this.name;
}
}
export default class ExportNamedDeclaration extends Node {
initialise ( scope ) {
this.scope = scope;
this.isExportDeclaration = true;
// special case – `export { foo as default }` should not create a live binding
const defaultExport = find( this.specifiers, specifier => specifier.exported.name === 'default' );
if ( defaultExport ) {
const declaration = this.scope.findDeclaration( defaultExport.local.name );
this.defaultExport = new UnboundDefaultExport( declaration );
scope.declarations.default = this.defaultExport;
}
if ( this.declaration ) this.declaration.initialise( scope );
}

3
test/function/default-export-as-is-bound/_config.js

@ -0,0 +1,3 @@
module.exports = {
description: 'does bind export as default (#1078)'
};

7
test/function/default-export-as-is-bound/foo.js

@ -0,0 +1,7 @@
var a = 42;
export function change() {
a++;
}
export { a as default };

6
test/function/default-export-as-is-bound/main.js

@ -0,0 +1,6 @@
import a from './foo';
import { change } from './foo';
assert.equal( a, 42 );
change();
assert.equal( a, 43, 'export as default should be bound' );

5
test/function/export-as-default/_config.js

@ -1,5 +0,0 @@
var assert = require( 'assert' );
module.exports = {
description: 'export { foo as default } does not create a live binding'
};

3
test/function/export-as-default/foo.js

@ -1,3 +0,0 @@
var foo = 1;
export { foo as default };
foo = 2;

3
test/function/export-as-default/main.js

@ -1,3 +0,0 @@
import foo from './foo.js';
assert.equal( foo, 1 );
Loading…
Cancel
Save