Browse Source

Fixed external-imports. Made cjs use getInteropBlock.

gh-109
Oskar Segersvärd 10 years ago
parent
commit
70c344c448
  1. 7
      src/ExternalModule.js
  2. 22
      src/Module.js
  3. 5
      src/utils/makeLegalIdentifier.js
  4. 2
      test/form/external-imports/_expected/cjs.js
  5. 4
      test/form/external-imports/_expected/es6.js

7
src/ExternalModule.js

@ -1,18 +1,19 @@
import { blank } from './utils/object';
import makeLegalIdentifier from './utils/makeLegalIdentifier';
export default class ExternalModule { export default class ExternalModule {
constructor ( { id, bundle } ) { constructor ( { id, bundle } ) {
this.id = id; this.id = id;
// Implement `Identifier` interface. // Implement `Identifier` interface.
this.originalName = id; this.originalName = this.name = makeLegalIdentifier( id );
this.name = id;
this.module = this; this.module = this;
// Define the external module's name in the bundle scope. // Define the external module's name in the bundle scope.
bundle.scope.define( id, this ); bundle.scope.define( id, this );
this.isExternal = true; this.isExternal = true;
this.importedByBundle = []; this.importedByBundle = blank();
// Invariant: needsNamed and needsAll are never both true at once. // Invariant: needsNamed and needsAll are never both true at once.
// Because an import with both a namespace and named import is invalid: // Because an import with both a namespace and named import is invalid:

22
src/Module.js

@ -224,6 +224,7 @@ export default class Module {
if ( isNamespace ) { if ( isNamespace ) {
// If it's a namespace import, we bind the localName to the module itself. // If it's a namespace import, we bind the localName to the module itself.
module.needsAll = true; module.needsAll = true;
module.name = localName;
this.locals.bind( localName, module ); this.locals.bind( localName, module );
} else { } else {
const name = isDefault ? 'default' : specifier.imported.name; const name = isDefault ? 'default' : specifier.imported.name;
@ -237,6 +238,7 @@ export default class Module {
if ( module.isExternal && isDefault ) { if ( module.isExternal && isDefault ) {
const id = module.exports.lookup( name ); const id = module.exports.lookup( name );
module.name = id.name = localName; module.name = id.name = localName;
id.name += '__default';
} }
} }
}); });
@ -393,10 +395,16 @@ export default class Module {
mark ( name ) { mark ( name ) {
const id = this.locals.lookup( name ); const id = this.locals.lookup( name );
if ( id && id.statement ) { if ( id && id.module ) {
// Assert that statement is defined. It isn't for external modules. if ( id.module.isExternal ) {
id.isUsed = true; id.module.importedByBundle[ id.originalName ] = true;
id.statement.mark(); }
if ( id.statement ) {
// Assert that statement is defined. It isn't for external modules.
id.isUsed = true;
id.statement.mark();
}
} }
} }
@ -601,7 +609,11 @@ export default class Module {
.forEach( name => { .forEach( name => {
const id = this.locals.lookup( name ); const id = this.locals.lookup( name );
if ( id.module && id.module.isExternal ) { // We shouldn't create a replacement for `id` if
// 1. `id` is a Global, in which case it has no module property
// 2. `id.module` isn't external, which means we have direct access
// 3. `id` is its own module, in the case of namespace imports
if ( id.module && id.module.isExternal && id.module !== id ) {
replacements[ name ] = id.originalName === 'default' ? replacements[ name ] = id.originalName === 'default' ?
// default names are always directly accessed // default names are always directly accessed
id.name : id.name :

5
src/utils/makeLegalIdentifier.js

@ -8,7 +8,10 @@ reservedWords.concat( builtins ).forEach( word => blacklisted[ word ] = true );
export default function makeLegalIdentifier ( str ) { export default function makeLegalIdentifier ( str ) {
str = str.replace( /[^$_a-zA-Z0-9]/g, '_' ); str = str
.replace( /-(\w)/g, ( _, letter ) => letter.toUpperCase() )
.replace( /[^$_a-zA-Z0-9]/g, '_' );
if ( /\d/.test( str[0] ) || blacklisted[ str ] ) str = `_${str}`; if ( /\d/.test( str[0] ) || blacklisted[ str ] ) str = `_${str}`;
return str; return str;

2
test/form/external-imports/_expected/cjs.js

@ -1,10 +1,10 @@
'use strict'; 'use strict';
var factory = require('factory'); var factory = require('factory');
factory = 'default' in factory ? factory['default'] : factory;
var baz = require('baz'); var baz = require('baz');
var containers = require('shipping-port'); var containers = require('shipping-port');
var alphabet = require('alphabet'); var alphabet = require('alphabet');
factory = 'default' in factory ? factory['default'] : factory;
var alphabet__default = 'default' in alphabet ? alphabet['default'] : alphabet; var alphabet__default = 'default' in alphabet ? alphabet['default'] : alphabet;
factory( null ); factory( null );

4
test/form/external-imports/_expected/es6.js

@ -1,10 +1,10 @@
import factory from 'factory'; import factory from 'factory';
import { bar, foo } from 'baz'; import { bar, foo } from 'baz';
import * as containers from 'shipping-port'; import * as containers from 'shipping-port';
import alphabet, { a } from 'alphabet'; import alphabet__default, { a } from 'alphabet';
factory( null ); factory( null );
foo( bar ); foo( bar );
containers.forEach( console.log, console ); containers.forEach( console.log, console );
console.log( a ); console.log( a );
console.log( alphabet.length ); console.log( alphabet__default.length );

Loading…
Cancel
Save