diff --git a/src/Module.js b/src/Module.js index ce59dee..746a96d 100644 --- a/src/Module.js +++ b/src/Module.js @@ -324,7 +324,10 @@ export default class Module { }); this.exportAllModules.forEach( module => { - if ( module.isExternal ) return; // TODO + if ( module.isExternal ) { + exports[ `*${module.id}` ] = true; + return; + } module.getExports().forEach( name => { if ( name !== 'default' ) exports[ name ] = true; diff --git a/src/finalisers/amd.js b/src/finalisers/amd.js index efe1a8e..55ca3e5 100644 --- a/src/finalisers/amd.js +++ b/src/finalisers/amd.js @@ -27,7 +27,7 @@ export default function amd ( bundle, magicString, { exportMode, indentString, i if ( intro ) magicString.prepend( intro ); - const exportBlock = getExportBlock( bundle.entryModule, exportMode ); + const exportBlock = getExportBlock( bundle, exportMode ); if ( exportBlock ) magicString.append( '\n\n' + exportBlock ); if ( exportMode === 'named' && options.legacy !== true ) magicString.append( `\n\n${esModuleExport}` ); if ( outro ) magicString.append( outro ); diff --git a/src/finalisers/cjs.js b/src/finalisers/cjs.js index 17036e9..cb571c2 100644 --- a/src/finalisers/cjs.js +++ b/src/finalisers/cjs.js @@ -48,7 +48,7 @@ export default function cjs ( bundle, magicString, { exportMode, intro, outro }, magicString.prepend( intro ); - const exportBlock = getExportBlock( bundle.entryModule, exportMode, 'module.exports =' ); + const exportBlock = getExportBlock( bundle, exportMode, 'module.exports =' ); if ( exportBlock ) magicString.append( '\n\n' + exportBlock ); if ( outro ) magicString.append( outro ); diff --git a/src/finalisers/es.js b/src/finalisers/es.js index b2123bb..319d398 100644 --- a/src/finalisers/es.js +++ b/src/finalisers/es.js @@ -6,6 +6,10 @@ function notDefault ( name ) { export default function es ( bundle, magicString, { intro, outro } ) { const importBlock = bundle.externalModules + .filter( module => { + const imported = keys( module.declarations ); + return imported.length !== 1 || imported[0][0] !== '*'; + }) .map( module => { const specifiers = []; const specifiersList = [specifiers]; @@ -13,11 +17,16 @@ export default function es ( bundle, magicString, { intro, outro } ) { .filter( name => name !== '*' && name !== 'default' ) .filter( name => module.declarations[ name ].activated ) .map( name => { + if ( name[0] === '*' ) { + return `* as ${module.name}`; + } + const declaration = module.declarations[ name ]; if ( declaration.name === declaration.safeName ) return declaration.name; return `${declaration.name} as ${declaration.safeName}`; - }); + }) + .filter( Boolean ); if ( module.declarations.default ) { if ( module.exportsNamespace ) { @@ -55,14 +64,25 @@ export default function es ( bundle, magicString, { intro, outro } ) { const module = bundle.entryModule; - const specifiers = module.getExports().filter( notDefault ).map( name => { - const declaration = module.traceExport( name ); - const rendered = declaration.getName( true ); + const exportAllDeclarations = []; + + const specifiers = module.getExports() + .filter( notDefault ) + .map( name => { + const declaration = module.traceExport( name ); + const rendered = declaration.getName( true ); - return rendered === name ? - name : - `${rendered} as ${name}`; - }); + if ( name[0] === '*' ) { + // export * from 'external' + exportAllDeclarations.push( `export * from '${name.slice( 1 )}';` ); + return; + } + + return rendered === name ? + name : + `${rendered} as ${name}`; + }) + .filter( Boolean ); let exportBlock = specifiers.length ? `export { ${specifiers.join(', ')} };` : ''; @@ -72,6 +92,7 @@ export default function es ( bundle, magicString, { intro, outro } ) { } if ( exportBlock ) magicString.append( '\n\n' + exportBlock.trim() ); + if ( exportAllDeclarations.length ) magicString.append( '\n\n' + exportAllDeclarations.join( '\n' ).trim() ); if ( outro ) magicString.append( outro ); return magicString.trim(); diff --git a/src/finalisers/iife.js b/src/finalisers/iife.js index f2c6902..239cdb5 100644 --- a/src/finalisers/iife.js +++ b/src/finalisers/iife.js @@ -65,7 +65,7 @@ export default function iife ( bundle, magicString, { exportMode, indentString, if ( intro ) magicString.prepend( intro ); - const exportBlock = getExportBlock( bundle.entryModule, exportMode ); + const exportBlock = getExportBlock( bundle, exportMode ); if ( exportBlock ) magicString.append( '\n\n' + exportBlock ); if ( outro ) magicString.append( outro ); diff --git a/src/finalisers/shared/getExportBlock.js b/src/finalisers/shared/getExportBlock.js index 5a7f34f..0345dd6 100644 --- a/src/finalisers/shared/getExportBlock.js +++ b/src/finalisers/shared/getExportBlock.js @@ -1,10 +1,20 @@ -export default function getExportBlock ( entryModule, exportMode, mechanism = 'return' ) { +export default function getExportBlock ( bundle, exportMode, mechanism = 'return' ) { + const entryModule = bundle.entryModule; + if ( exportMode === 'default' ) { return `${mechanism} ${entryModule.traceExport( 'default' ).getName( false )};`; } return entryModule.getExports() .map( name => { + if ( name[0] === '*' ) { + // export all from external + const id = name.slice( 1 ); + const module = bundle.moduleById.get( id ); + + return `Object.keys(${module.name}).forEach(function (key) { exports[key] = ${module.name}[key]; });`; + } + const prop = name === 'default' ? `['default']` : `.${name}`; const declaration = entryModule.traceExport( name ); diff --git a/src/finalisers/umd.js b/src/finalisers/umd.js index 5102e2b..0a93e03 100644 --- a/src/finalisers/umd.js +++ b/src/finalisers/umd.js @@ -86,7 +86,7 @@ export default function umd ( bundle, magicString, { exportMode, indentString, i if ( intro ) magicString.prepend( intro ); - const exportBlock = getExportBlock( bundle.entryModule, exportMode ); + const exportBlock = getExportBlock( bundle, exportMode ); if ( exportBlock ) magicString.append( '\n\n' + exportBlock ); if ( exportMode === 'named' && options.legacy !== true ) magicString.append( `\n\n${esModuleExport}` ); if ( outro ) magicString.append( outro ); diff --git a/test/form/reexports-from-external/_config.js b/test/form/reexports-from-external/_config.js new file mode 100644 index 0000000..58c5eff --- /dev/null +++ b/test/form/reexports-from-external/_config.js @@ -0,0 +1,9 @@ +const assert = require( 'assert' ); + +module.exports = { + description: 're-exports * from external module (#791)', + options: { + external: [ 'external' ], + moduleName: 'myBundle' + } +}; diff --git a/test/form/reexports-from-external/_expected/amd.js b/test/form/reexports-from-external/_expected/amd.js new file mode 100644 index 0000000..ae628ce --- /dev/null +++ b/test/form/reexports-from-external/_expected/amd.js @@ -0,0 +1,9 @@ +define(['exports', 'external'], function (exports, external) { 'use strict'; + + + + Object.keys(external).forEach(function (key) { exports[key] = external[key]; }); + + Object.defineProperty(exports, '__esModule', { value: true }); + +}); diff --git a/test/form/reexports-from-external/_expected/cjs.js b/test/form/reexports-from-external/_expected/cjs.js new file mode 100644 index 0000000..8fe0297 --- /dev/null +++ b/test/form/reexports-from-external/_expected/cjs.js @@ -0,0 +1,9 @@ +'use strict'; + +Object.defineProperty(exports, '__esModule', { value: true }); + +var external = require('external'); + + + +Object.keys(external).forEach(function (key) { exports[key] = external[key]; }); diff --git a/test/form/reexports-from-external/_expected/es.js b/test/form/reexports-from-external/_expected/es.js new file mode 100644 index 0000000..4953eb6 --- /dev/null +++ b/test/form/reexports-from-external/_expected/es.js @@ -0,0 +1 @@ +export * from 'external'; diff --git a/test/form/reexports-from-external/_expected/iife.js b/test/form/reexports-from-external/_expected/iife.js new file mode 100644 index 0000000..6ce8e60 --- /dev/null +++ b/test/form/reexports-from-external/_expected/iife.js @@ -0,0 +1,8 @@ +(function (exports,external) { + 'use strict'; + + + + Object.keys(external).forEach(function (key) { exports[key] = external[key]; }); + +}((this.myBundle = this.myBundle || {}),external)); diff --git a/test/form/reexports-from-external/_expected/umd.js b/test/form/reexports-from-external/_expected/umd.js new file mode 100644 index 0000000..554df0d --- /dev/null +++ b/test/form/reexports-from-external/_expected/umd.js @@ -0,0 +1,11 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('external')) : + typeof define === 'function' && define.amd ? define(['exports', 'external'], factory) : + (factory((global.myBundle = global.myBundle || {}),global.external)); +}(this, (function (exports,external) { 'use strict'; + + Object.keys(external).forEach(function (key) { exports[key] = external[key]; }); + + Object.defineProperty(exports, '__esModule', { value: true }); + +}))); diff --git a/test/form/reexports-from-external/main.js b/test/form/reexports-from-external/main.js new file mode 100644 index 0000000..4953eb6 --- /dev/null +++ b/test/form/reexports-from-external/main.js @@ -0,0 +1 @@ +export * from 'external'; diff --git a/test/function/reexports-from-external/_config.js b/test/function/reexports-from-external/_config.js new file mode 100644 index 0000000..c61fdfc --- /dev/null +++ b/test/function/reexports-from-external/_config.js @@ -0,0 +1,22 @@ +const assert = require( 'assert' ); + +module.exports = { + description: 're-exports * from external module (#791)', + options: { + external: [ 'external' ] + }, + context: { + require ( id ) { + if ( id === 'external' ) { + return { + foo: 1, + bar: 2 + }; + } + } + }, + exports: exports => { + assert.equal( exports.foo, 1 ); + assert.equal( exports.bar, 2 ); + } +}; diff --git a/test/function/reexports-from-external/main.js b/test/function/reexports-from-external/main.js new file mode 100644 index 0000000..4953eb6 --- /dev/null +++ b/test/function/reexports-from-external/main.js @@ -0,0 +1 @@ +export * from 'external';