diff --git a/docs/01-command-line-reference.md b/docs/01-command-line-reference.md index e3a50604e7c..af79f3a168f 100755 --- a/docs/01-command-line-reference.md +++ b/docs/01-command-line-reference.md @@ -89,6 +89,7 @@ export default { // can be an array (for multiple inputs) dynamicImportFunction, esModule, exports, + externalLiveBindings, freeze, indent, namespaceToStringTag, @@ -214,6 +215,7 @@ Many options have command line equivalents. In those cases, any arguments passed --no-esModule Do not add __esModule property --exports Specify export mode (auto, default, named, none) --extend Extend global variable defined by --name +--no-externalLiveBindings Do not generate code to support live bindings --footer Code to insert at end of bundle (outside wrapper) --no-freeze Do not freeze namespace objects --no-indent Don't indent result diff --git a/docs/02-javascript-api.md b/docs/02-javascript-api.md index f9e1ca02dff..634638372f9 100755 --- a/docs/02-javascript-api.md +++ b/docs/02-javascript-api.md @@ -109,41 +109,42 @@ The `outputOptions` object can contain the following properties (see the [big li ```js const outputOptions = { - // core output options - dir, - file, - format, // required - globals, - name, - - // advanced output options - assetFileNames, - banner, - chunkFileNames, - compact, - entryFileNames, - extend, - footer, - interop, - intro, - outro, - paths, - sourcemap, - sourcemapExcludeSources, - sourcemapFile, - sourcemapPathTransform, - - // danger zone - amd, - dynamicImportFunction, - esModule, - exports, - freeze, - indent, - namespaceToStringTag, - noConflict, - preferConst, - strict + // core output options + dir, + file, + format, // required + globals, + name, + + // advanced output options + assetFileNames, + banner, + chunkFileNames, + compact, + entryFileNames, + extend, + externalLiveBindings, + footer, + interop, + intro, + outro, + paths, + sourcemap, + sourcemapExcludeSources, + sourcemapFile, + sourcemapPathTransform, + + // danger zone + amd, + dynamicImportFunction, + esModule, + exports, + freeze, + indent, + namespaceToStringTag, + noConflict, + preferConst, + strict }; ``` diff --git a/docs/999-big-list-of-options.md b/docs/999-big-list-of-options.md index ffb43e7fdbf..56132eb8bab 100755 --- a/docs/999-big-list-of-options.md +++ b/docs/999-big-list-of-options.md @@ -661,6 +661,45 @@ const yourMethod = require( 'your-lib' ).yourMethod; const yourLib = require( 'your-lib' ).default; ``` +#### output.externalLiveBindings +Type: `boolean`
+CLI: `--externalLiveBindings`/`--no-externalLiveBindings`
+Default: `true` + +When set to `false`, Rollup will not generate code to support live bindings for external imports but instead assume that exports do not change over time. This will enable Rollup to generate more optimized code. Note that this can cause issues when there are circular dependencies involving an external dependency. + +This will avoid most cases where Rollup generates getters in the code and can therefore be used to make code IE8 compatible in many cases. + +Example: + +```js +// input +export {x} from 'external'; + +// CJS output with externalLiveBindings: true +'use strict'; + +Object.defineProperty(exports, '__esModule', { value: true }); + +var external = require('external'); + +Object.defineProperty(exports, 'x', { + enumerable: true, + get: function () { + return external.x; + } +}); + +// CJS output with externalLiveBindings: false +'use strict'; + +Object.defineProperty(exports, '__esModule', { value: true }); + +var external = require('external'); + +exports.x = external.x; +``` + #### output.freeze Type: `boolean`
CLI: `--freeze`/`--no-freeze`
diff --git a/src/Chunk.ts b/src/Chunk.ts index c7e7127d921..f19fd9dd23e 100644 --- a/src/Chunk.ts +++ b/src/Chunk.ts @@ -851,6 +851,7 @@ export default class Chunk { let importName: string; let needsLiveBinding = false; if (exportName[0] === '*') { + needsLiveBinding = options.externalLiveBindings !== false; exportChunk = this.graph.moduleById.get(exportName.substr(1)) as ExternalModule; importName = exportName = '*'; } else { @@ -865,7 +866,7 @@ export default class Chunk { } else { exportChunk = module; importName = variable.name; - needsLiveBinding = true; + needsLiveBinding = options.externalLiveBindings !== false; } } let reexportDeclaration = reexportDeclarations.get(exportChunk); diff --git a/src/finalisers/amd.ts b/src/finalisers/amd.ts index 16ad1f93605..c0cff6626f4 100644 --- a/src/finalisers/amd.ts +++ b/src/finalisers/amd.ts @@ -75,7 +75,7 @@ export default function amd( magicString.prepend(interopBlock + n + n); } if (accessedGlobals.has(INTEROP_NAMESPACE_VARIABLE)) { - magicString.prepend(getInteropNamespace(_, n, t)); + magicString.prepend(getInteropNamespace(_, n, t, options.externalLiveBindings !== false)); } if (intro) magicString.prepend(intro); diff --git a/src/finalisers/cjs.ts b/src/finalisers/cjs.ts index de4a290f6d0..67dc2d31dd8 100644 --- a/src/finalisers/cjs.ts +++ b/src/finalisers/cjs.ts @@ -80,7 +80,7 @@ export default function cjs( `?${_}${ex}['default']${_}:${_}${ex}${options.compact ? '' : '; '}}${n}${n}`; } if (accessedGlobals.has(INTEROP_NAMESPACE_VARIABLE)) { - intro += getInteropNamespace(_, n, t); + intro += getInteropNamespace(_, n, t, options.externalLiveBindings !== false); } if (importBlock) intro += importBlock + n + n; diff --git a/src/finalisers/shared/getExportBlock.ts b/src/finalisers/shared/getExportBlock.ts index 616c592d807..679274d22ac 100644 --- a/src/finalisers/shared/getExportBlock.ts +++ b/src/finalisers/shared/getExportBlock.ts @@ -45,13 +45,19 @@ export default function getExportBlock( reexports.forEach(specifier => { if (specifier.reexported === '*') { if (!compact && exportBlock) exportBlock += '\n'; - exportBlock += - `Object.keys(${name}).forEach(function${_}(k)${_}{${n}` + - `${t}if${_}(k${_}!==${_}'default')${_}Object.defineProperty(exports,${_}k,${_}{${n}` + - `${t}${t}enumerable:${_}true,${n}` + - `${t}${t}get:${_}function${_}()${_}{${n}` + - `${t}${t}${t}return ${name}[k];${n}` + - `${t}${t}}${n}${t}});${n}});`; + if (specifier.needsLiveBinding) { + exportBlock += + `Object.keys(${name}).forEach(function${_}(k)${_}{${n}` + + `${t}if${_}(k${_}!==${_}'default')${_}Object.defineProperty(exports,${_}k,${_}{${n}` + + `${t}${t}enumerable:${_}true,${n}` + + `${t}${t}get:${_}function${_}()${_}{${n}` + + `${t}${t}${t}return ${name}[k];${n}` + + `${t}${t}}${n}${t}});${n}});`; + } else { + exportBlock += + `Object.keys(${name}).forEach(function${_}(k)${_}{${n}` + + `${t}if${_}(k${_}!==${_}'default')${_}exports[k]${_}=${_}${name}[k];${n}});`; + } } }); } diff --git a/src/finalisers/shared/getInteropNamespace.ts b/src/finalisers/shared/getInteropNamespace.ts index b5588f6a457..0199dfa15bf 100644 --- a/src/finalisers/shared/getInteropNamespace.ts +++ b/src/finalisers/shared/getInteropNamespace.ts @@ -1,22 +1,34 @@ import { INTEROP_NAMESPACE_VARIABLE } from '../../utils/variableNames'; -export function getInteropNamespace(_: string, n: string, t: string) { - return `function ${INTEROP_NAMESPACE_VARIABLE}(e)${_}{${n}` + -`${t}if${_}(e${_}&&${_}e.__esModule)${_}{${_}return e;${_}}${_}else${_}{${n}` + -`${t}${t}var n${_}=${_}{};${n}` + -`${t}${t}if${_}(e)${_}{${n}` + -`${t}${t}${t}Object.keys(e).forEach(function${_}(k)${_}{${n}` + -`${t}${t}${t}${t}var d${_}=${_}Object.getOwnPropertyDescriptor(e,${_}k);${n}` + -`${t}${t}${t}${t}Object.defineProperty(n,${_}k,${_}d.get${_}?${_}d${_}:${_}{${n}` + -`${t}${t}${t}${t}${t}enumerable:${_}true,${n}` + -`${t}${t}${t}${t}${t}get:${_}function${_}()${_}{${n}` + -`${t}${t}${t}${t}${t}${t}return e[k];${n}` + -`${t}${t}${t}${t}${t}}${n}` + -`${t}${t}${t}${t}});${n}` + -`${t}${t}${t}});${n}` + -`${t}${t}}${n}` + -`${t}${t}n['default']${_}=${_}e;${n}` + -`${t}${t}return n;${n}` + -`${t}}${n}` + -`}${n}${n}`; +function copyPropertyLiveBinding(_: string, n: string, t: string, i: string) { + return ( + `${i}var d${_}=${_}Object.getOwnPropertyDescriptor(e,${_}k);${n}` + + `${i}Object.defineProperty(n,${_}k,${_}d.get${_}?${_}d${_}:${_}{${n}` + + `${i}${t}enumerable:${_}true,${n}` + + `${i}${t}get:${_}function${_}()${_}{${n}` + + `${i}${t}${t}return e[k];${n}` + + `${i}${t}}${n}` + + `${i}});${n}` + ); +} + +function copyPropertyStatic(_: string, n: string, _t: string, i: string) { + return `${i}n[k]${_}=e${_}[k];${n}`; +} + +export function getInteropNamespace(_: string, n: string, t: string, liveBindings: boolean) { + return ( + `function ${INTEROP_NAMESPACE_VARIABLE}(e)${_}{${n}` + + `${t}if${_}(e${_}&&${_}e.__esModule)${_}{${_}return e;${_}}${_}else${_}{${n}` + + `${t}${t}var n${_}=${_}{};${n}` + + `${t}${t}if${_}(e)${_}{${n}` + + `${t}${t}${t}Object.keys(e).forEach(function${_}(k)${_}{${n}` + + (liveBindings ? copyPropertyLiveBinding : copyPropertyStatic)(_, n, t, t + t + t + t) + + `${t}${t}${t}});${n}` + + `${t}${t}}${n}` + + `${t}${t}n['default']${_}=${_}e;${n}` + + `${t}${t}return n;${n}` + + `${t}}${n}` + + `}${n}${n}` + ); } diff --git a/src/rollup/types.d.ts b/src/rollup/types.d.ts index c24a7dded59..36f5394eda6 100644 --- a/src/rollup/types.d.ts +++ b/src/rollup/types.d.ts @@ -431,6 +431,7 @@ export interface OutputOptions { esModule?: boolean; exports?: 'default' | 'named' | 'none' | 'auto'; extend?: boolean; + externalLiveBindings?: boolean; // only required for bundle.write file?: string; footer?: string | (() => string | Promise); diff --git a/src/utils/mergeOptions.ts b/src/utils/mergeOptions.ts index 5456aede10a..9f31da028db 100644 --- a/src/utils/mergeOptions.ts +++ b/src/utils/mergeOptions.ts @@ -269,6 +269,7 @@ function getOutputOptions( esModule: getOption('esModule', true), exports: getOption('exports'), extend: getOption('extend'), + externalLiveBindings: getOption('externalLiveBindings', true), file: getOption('file'), footer: getOption('footer'), format: format === 'esm' ? 'es' : format, diff --git a/test/cli/index.js b/test/cli/index.js index 124b339ae4b..1420d5db11d 100644 --- a/test/cli/index.js +++ b/test/cli/index.js @@ -25,7 +25,7 @@ runTestSuiteWithSamples( const command = 'node ' + path.resolve(__dirname, '../../bin') + path.sep + config.command; - const childProcess = exec(command, { timeout: 25000 }, (err, code, stderr) => { + const childProcess = exec(command, { timeout: 40000 }, (err, code, stderr) => { if (err && !err.killed) { if (config.error) { const shouldContinue = config.error(err); @@ -118,7 +118,7 @@ runTestSuiteWithSamples( } }); } - ).timeout(30000); + ).timeout(50000); }, () => process.chdir(cwd) ); diff --git a/test/form/samples/no-external-live-bindings-compact/_config.js b/test/form/samples/no-external-live-bindings-compact/_config.js new file mode 100644 index 00000000000..cfd914b43a6 --- /dev/null +++ b/test/form/samples/no-external-live-bindings-compact/_config.js @@ -0,0 +1,11 @@ +module.exports = { + description: 'Allows omitting the code that handles external live bindings in compact mode', + options: { + external: () => true, + output: { + compact: true, + externalLiveBindings: false, + name: 'bundle' + } + } +}; diff --git a/test/form/samples/no-external-live-bindings-compact/_expected/amd.js b/test/form/samples/no-external-live-bindings-compact/_expected/amd.js new file mode 100644 index 00000000000..d361d8fc6a4 --- /dev/null +++ b/test/form/samples/no-external-live-bindings-compact/_expected/amd.js @@ -0,0 +1 @@ +define(['require','exports','external1','external2'],function(require,exports,external1,external2){'use strict';function _interopNamespace(e){if(e&&e.__esModule){return e;}else{var n={};if(e){Object.keys(e).forEach(function(k){n[k]=e[k];});}n['default']=e;return n;}}const dynamic = new Promise(function(c,e){require(['external3'],function(m){c(_interopNamespace(m));},e)});Object.keys(external2).forEach(function(k){if(k!=='default')exports[k]=external2[k];});exports.external1=external1.external1;exports.dynamic=dynamic;Object.defineProperty(exports,'__esModule',{value:true});}); \ No newline at end of file diff --git a/test/form/samples/no-external-live-bindings-compact/_expected/cjs.js b/test/form/samples/no-external-live-bindings-compact/_expected/cjs.js new file mode 100644 index 00000000000..0ab0d9611ae --- /dev/null +++ b/test/form/samples/no-external-live-bindings-compact/_expected/cjs.js @@ -0,0 +1 @@ +'use strict';Object.defineProperty(exports,'__esModule',{value:true});function _interopNamespace(e){if(e&&e.__esModule){return e;}else{var n={};if(e){Object.keys(e).forEach(function(k){n[k]=e[k];});}n['default']=e;return n;}}var external1=require('external1'),external2=require('external2');const dynamic = new Promise(function(c){c(_interopNamespace(require('external3')));});Object.keys(external2).forEach(function(k){if(k!=='default')exports[k]=external2[k];});exports.external1=external1.external1;exports.dynamic=dynamic; \ No newline at end of file diff --git a/test/form/samples/no-external-live-bindings-compact/_expected/es.js b/test/form/samples/no-external-live-bindings-compact/_expected/es.js new file mode 100644 index 00000000000..23bc588506f --- /dev/null +++ b/test/form/samples/no-external-live-bindings-compact/_expected/es.js @@ -0,0 +1 @@ +export{external1}from'external1';export*from'external2';const dynamic = import('external3');export{dynamic}; \ No newline at end of file diff --git a/test/form/samples/no-external-live-bindings-compact/_expected/iife.js b/test/form/samples/no-external-live-bindings-compact/_expected/iife.js new file mode 100644 index 00000000000..cd8913be2b7 --- /dev/null +++ b/test/form/samples/no-external-live-bindings-compact/_expected/iife.js @@ -0,0 +1 @@ +var bundle=(function(exports,external1,external2){'use strict';const dynamic = import('external3');Object.keys(external2).forEach(function(k){if(k!=='default')exports[k]=external2[k];});exports.external1=external1.external1;exports.dynamic=dynamic;return exports;}({},external1,external2)); \ No newline at end of file diff --git a/test/form/samples/no-external-live-bindings-compact/_expected/system.js b/test/form/samples/no-external-live-bindings-compact/_expected/system.js new file mode 100644 index 00000000000..4ff778c05bf --- /dev/null +++ b/test/form/samples/no-external-live-bindings-compact/_expected/system.js @@ -0,0 +1 @@ +System.register('bundle',['external1','external2'],function(exports,module){'use strict';var _starExcludes={dynamic:1,default:1,external1:1};return{setters:[function(module){exports('external1',module.external1);},function(module){var _setter={};for(var _$pinmodule){if(!_starExcludes[_$p])_setter[_$p]=module[_$p];}exports(_setter);}],execute:function(){const dynamic = exports('dynamic', module.import('external3'));}}}); \ No newline at end of file diff --git a/test/form/samples/no-external-live-bindings-compact/_expected/umd.js b/test/form/samples/no-external-live-bindings-compact/_expected/umd.js new file mode 100644 index 00000000000..e22efd00469 --- /dev/null +++ b/test/form/samples/no-external-live-bindings-compact/_expected/umd.js @@ -0,0 +1 @@ +(function(g,f){typeof exports==='object'&&typeof module!=='undefined'?f(exports,require('external1'),require('external2')):typeof define==='function'&&define.amd?define(['exports','external1','external2'],f):(g=g||self,f(g.bundle={},g.external1,g.external2));}(this,function(exports, external1, external2){'use strict';const dynamic = import('external3');Object.keys(external2).forEach(function(k){if(k!=='default')exports[k]=external2[k];});exports.external1=external1.external1;exports.dynamic=dynamic;Object.defineProperty(exports,'__esModule',{value:true});})); \ No newline at end of file diff --git a/test/form/samples/no-external-live-bindings-compact/main.js b/test/form/samples/no-external-live-bindings-compact/main.js new file mode 100644 index 00000000000..0a04b1aa8c9 --- /dev/null +++ b/test/form/samples/no-external-live-bindings-compact/main.js @@ -0,0 +1,3 @@ +export { external1 } from 'external1'; +export * from 'external2'; +export const dynamic = import('external3'); diff --git a/test/form/samples/no-external-live-bindings/_config.js b/test/form/samples/no-external-live-bindings/_config.js new file mode 100644 index 00000000000..efd97f37756 --- /dev/null +++ b/test/form/samples/no-external-live-bindings/_config.js @@ -0,0 +1,10 @@ +module.exports = { + description: 'Allows omitting the code that handles external live bindings', + options: { + external: () => true, + output: { + externalLiveBindings: false, + name: 'bundle' + } + } +}; diff --git a/test/form/samples/no-external-live-bindings/_expected/amd.js b/test/form/samples/no-external-live-bindings/_expected/amd.js new file mode 100644 index 00000000000..b28c6a0fabb --- /dev/null +++ b/test/form/samples/no-external-live-bindings/_expected/amd.js @@ -0,0 +1,26 @@ +define(['require', 'exports', 'external1', 'external2'], function (require, exports, external1, external2) { 'use strict'; + + function _interopNamespace(e) { + if (e && e.__esModule) { return e; } else { + var n = {}; + if (e) { + Object.keys(e).forEach(function (k) { + n[k] =e [k]; + }); + } + n['default'] = e; + return n; + } + } + + const dynamic = new Promise(function (resolve, reject) { require(['external3'], function (m) { resolve(_interopNamespace(m)); }, reject) }); + + Object.keys(external2).forEach(function (k) { + if (k !== 'default') exports[k] = external2[k]; + }); + exports.external1 = external1.external1; + exports.dynamic = dynamic; + + Object.defineProperty(exports, '__esModule', { value: true }); + +}); diff --git a/test/form/samples/no-external-live-bindings/_expected/cjs.js b/test/form/samples/no-external-live-bindings/_expected/cjs.js new file mode 100644 index 00000000000..2b60227a39c --- /dev/null +++ b/test/form/samples/no-external-live-bindings/_expected/cjs.js @@ -0,0 +1,27 @@ +'use strict'; + +Object.defineProperty(exports, '__esModule', { value: true }); + +function _interopNamespace(e) { + if (e && e.__esModule) { return e; } else { + var n = {}; + if (e) { + Object.keys(e).forEach(function (k) { + n[k] =e [k]; + }); + } + n['default'] = e; + return n; + } +} + +var external1 = require('external1'); +var external2 = require('external2'); + +const dynamic = new Promise(function (resolve) { resolve(_interopNamespace(require('external3'))); }); + +Object.keys(external2).forEach(function (k) { + if (k !== 'default') exports[k] = external2[k]; +}); +exports.external1 = external1.external1; +exports.dynamic = dynamic; diff --git a/test/form/samples/no-external-live-bindings/_expected/es.js b/test/form/samples/no-external-live-bindings/_expected/es.js new file mode 100644 index 00000000000..61036a51fbb --- /dev/null +++ b/test/form/samples/no-external-live-bindings/_expected/es.js @@ -0,0 +1,6 @@ +export { external1 } from 'external1'; +export * from 'external2'; + +const dynamic = import('external3'); + +export { dynamic }; diff --git a/test/form/samples/no-external-live-bindings/_expected/iife.js b/test/form/samples/no-external-live-bindings/_expected/iife.js new file mode 100644 index 00000000000..9899e626363 --- /dev/null +++ b/test/form/samples/no-external-live-bindings/_expected/iife.js @@ -0,0 +1,14 @@ +var bundle = (function (exports, external1, external2) { + 'use strict'; + + const dynamic = import('external3'); + + Object.keys(external2).forEach(function (k) { + if (k !== 'default') exports[k] = external2[k]; + }); + exports.external1 = external1.external1; + exports.dynamic = dynamic; + + return exports; + +}({}, external1, external2)); diff --git a/test/form/samples/no-external-live-bindings/_expected/system.js b/test/form/samples/no-external-live-bindings/_expected/system.js new file mode 100644 index 00000000000..0b5739a7de3 --- /dev/null +++ b/test/form/samples/no-external-live-bindings/_expected/system.js @@ -0,0 +1,20 @@ +System.register('bundle', ['external1', 'external2'], function (exports, module) { + 'use strict'; + var _starExcludes = { dynamic: 1, default: 1, external1: 1 }; + return { + setters: [function (module) { + exports('external1', module.external1); + }, function (module) { + var _setter = {}; + for (var _$p in module) { + if (!_starExcludes[_$p]) _setter[_$p] = module[_$p]; + } + exports(_setter); + }], + execute: function () { + + const dynamic = exports('dynamic', module.import('external3')); + + } + }; +}); diff --git a/test/form/samples/no-external-live-bindings/_expected/umd.js b/test/form/samples/no-external-live-bindings/_expected/umd.js new file mode 100644 index 00000000000..9b6cab31265 --- /dev/null +++ b/test/form/samples/no-external-live-bindings/_expected/umd.js @@ -0,0 +1,17 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('external1'), require('external2')) : + typeof define === 'function' && define.amd ? define(['exports', 'external1', 'external2'], factory) : + (global = global || self, factory(global.bundle = {}, global.external1, global.external2)); +}(this, function (exports, external1, external2) { 'use strict'; + + const dynamic = import('external3'); + + Object.keys(external2).forEach(function (k) { + if (k !== 'default') exports[k] = external2[k]; + }); + exports.external1 = external1.external1; + exports.dynamic = dynamic; + + Object.defineProperty(exports, '__esModule', { value: true }); + +})); diff --git a/test/form/samples/no-external-live-bindings/main.js b/test/form/samples/no-external-live-bindings/main.js new file mode 100644 index 00000000000..0a04b1aa8c9 --- /dev/null +++ b/test/form/samples/no-external-live-bindings/main.js @@ -0,0 +1,3 @@ +export { external1 } from 'external1'; +export * from 'external2'; +export const dynamic = import('external3'); diff --git a/test/function/samples/no-external-live-bindings-compact/_config.js b/test/function/samples/no-external-live-bindings-compact/_config.js new file mode 100644 index 00000000000..39e485f7c79 --- /dev/null +++ b/test/function/samples/no-external-live-bindings-compact/_config.js @@ -0,0 +1,31 @@ +const assert = require('assert'); + +module.exports = { + description: 'Allows omitting the code that handles external live bindings', + options: { + external: () => true, + output: { + compact: true, + externalLiveBindings: false, + name: 'bundle' + } + }, + context: { + require(id) { + return { [id]: true, value: id }; + } + }, + exports(exports) { + assert.deepStrictEqual(Object.keys(exports), ['external2', 'value', 'external1', 'dynamic']); + assert.strictEqual(exports.external1, true); + assert.strictEqual(exports.external2, true); + assert.strictEqual(exports.value, 'external2'); + return exports.dynamic.then(dynamic => + assert.deepStrictEqual(dynamic, { + external3: true, + value: 'external3', + default: { external3: true, value: 'external3' } + }) + ); + } +}; diff --git a/test/function/samples/no-external-live-bindings-compact/main.js b/test/function/samples/no-external-live-bindings-compact/main.js new file mode 100644 index 00000000000..0a04b1aa8c9 --- /dev/null +++ b/test/function/samples/no-external-live-bindings-compact/main.js @@ -0,0 +1,3 @@ +export { external1 } from 'external1'; +export * from 'external2'; +export const dynamic = import('external3'); diff --git a/test/function/samples/no-external-live-bindings/_config.js b/test/function/samples/no-external-live-bindings/_config.js new file mode 100644 index 00000000000..8e91f7df93c --- /dev/null +++ b/test/function/samples/no-external-live-bindings/_config.js @@ -0,0 +1,30 @@ +const assert = require('assert'); + +module.exports = { + description: 'Allows omitting the code that handles external live bindings', + options: { + external: () => true, + output: { + externalLiveBindings: false, + name: 'bundle' + } + }, + context: { + require(id) { + return { [id]: true, value: id }; + } + }, + exports(exports) { + assert.deepStrictEqual(Object.keys(exports), ['external2', 'value', 'external1', 'dynamic']); + assert.strictEqual(exports.external1, true); + assert.strictEqual(exports.external2, true); + assert.strictEqual(exports.value, 'external2'); + return exports.dynamic.then(dynamic => + assert.deepStrictEqual(dynamic, { + external3: true, + value: 'external3', + default: { external3: true, value: 'external3' } + }) + ); + } +}; diff --git a/test/function/samples/no-external-live-bindings/main.js b/test/function/samples/no-external-live-bindings/main.js new file mode 100644 index 00000000000..0a04b1aa8c9 --- /dev/null +++ b/test/function/samples/no-external-live-bindings/main.js @@ -0,0 +1,3 @@ +export { external1 } from 'external1'; +export * from 'external2'; +export const dynamic = import('external3'); diff --git a/test/misc/optionList.js b/test/misc/optionList.js index 535fa3471a8..4a28a584e70 100644 --- a/test/misc/optionList.js +++ b/test/misc/optionList.js @@ -1,3 +1,3 @@ exports.input = 'acorn, acornInjectPlugins, cache, chunkGroupingSize, context, experimentalCacheExpiry, experimentalOptimizeChunks, experimentalTopLevelAwait, external, inlineDynamicImports, input, manualChunks, moduleContext, onwarn, perf, plugins, preserveModules, preserveSymlinks, shimMissingExports, strictDeprecations, treeshake, watch'; -exports.flags = 'acorn, acornInjectPlugins, amd, assetFileNames, banner, c, cache, chunkFileNames, chunkGroupingSize, compact, config, context, d, dir, dynamicImportFunction, e, entryFileNames, environment, esModule, experimentalCacheExpiry, experimentalOptimizeChunks, experimentalTopLevelAwait, exports, extend, external, f, file, footer, format, freeze, g, globals, h, i, indent, inlineDynamicImports, input, interop, intro, m, manualChunks, moduleContext, n, name, namespaceToStringTag, noConflict, o, onwarn, outro, paths, perf, plugins, preferConst, preserveModules, preserveSymlinks, shimMissingExports, silent, sourcemap, sourcemapExcludeSources, sourcemapFile, strict, strictDeprecations, treeshake, v, w, watch'; -exports.output = 'amd, assetFileNames, banner, chunkFileNames, compact, dir, dynamicImportFunction, entryFileNames, esModule, exports, extend, file, footer, format, freeze, globals, indent, interop, intro, name, namespaceToStringTag, noConflict, outro, paths, preferConst, sourcemap, sourcemapExcludeSources, sourcemapFile, sourcemapPathTransform, strict'; +exports.flags = 'acorn, acornInjectPlugins, amd, assetFileNames, banner, c, cache, chunkFileNames, chunkGroupingSize, compact, config, context, d, dir, dynamicImportFunction, e, entryFileNames, environment, esModule, experimentalCacheExpiry, experimentalOptimizeChunks, experimentalTopLevelAwait, exports, extend, external, externalLiveBindings, f, file, footer, format, freeze, g, globals, h, i, indent, inlineDynamicImports, input, interop, intro, m, manualChunks, moduleContext, n, name, namespaceToStringTag, noConflict, o, onwarn, outro, paths, perf, plugins, preferConst, preserveModules, preserveSymlinks, shimMissingExports, silent, sourcemap, sourcemapExcludeSources, sourcemapFile, strict, strictDeprecations, treeshake, v, w, watch'; +exports.output = 'amd, assetFileNames, banner, chunkFileNames, compact, dir, dynamicImportFunction, entryFileNames, esModule, exports, extend, externalLiveBindings, file, footer, format, freeze, globals, indent, interop, intro, name, namespaceToStringTag, noConflict, outro, paths, preferConst, sourcemap, sourcemapExcludeSources, sourcemapFile, sourcemapPathTransform, strict';