diff --git a/packages/commonjs/src/index.js b/packages/commonjs/src/index.js index 07ed83dfc..6c624ca9e 100644 --- a/packages/commonjs/src/index.js +++ b/packages/commonjs/src/index.js @@ -36,12 +36,23 @@ import { export default function commonjs(options = {}) { const extensions = options.extensions || ['.js']; const filter = createFilter(options.include, options.exclude); - // TODO Lukas document values: true, 'preferred', 'auto', false - const { ignoreGlobal, requireReturnsDefault: requireReturnsDefaultOption } = options; + // TODO Lukas document esmExternals + const { + ignoreGlobal, + requireReturnsDefault: requireReturnsDefaultOption, + esmExternals + } = options; const getRequireReturnsDefault = typeof requireReturnsDefaultOption === 'function' ? requireReturnsDefaultOption : () => requireReturnsDefaultOption; + let esmExternalIds; + const isEsmExternal = + typeof esmExternals === 'function' + ? esmExternals + : Array.isArray(esmExternals) + ? ((esmExternalIds = new Set(esmExternals)), (id) => esmExternalIds.has(id)) + : () => esmExternals; const { dynamicRequireModuleSet, dynamicRequireModuleDirPaths } = getDynamicRequirePaths( options.dynamicRequireTargets @@ -137,7 +148,10 @@ export default function commonjs(options = {}) { if (id.endsWith(EXTERNAL_SUFFIX)) { const actualId = getIdFromExternalProxyId(id); - return getUnknownRequireProxy(actualId, getRequireReturnsDefault(actualId)); + return getUnknownRequireProxy( + actualId, + isEsmExternal(actualId) ? getRequireReturnsDefault(actualId) : true + ); } if (id === DYNAMIC_PACKAGES_ID) { diff --git a/packages/commonjs/test/fixtures/function/esm-externals-false/_config.js b/packages/commonjs/test/fixtures/function/esm-externals-false/_config.js new file mode 100644 index 000000000..fece1fe53 --- /dev/null +++ b/packages/commonjs/test/fixtures/function/esm-externals-false/_config.js @@ -0,0 +1,15 @@ +module.exports = { + description: 'always uses the default export when esmExternals is not used', + options: { + external: [ + 'external-cjs-exports', + 'external-cjs-module-exports', + 'external-esm-named', + 'external-esm-mixed', + 'external-esm-default' + ] + }, + pluginOptions: { + esmExternals: false + } +}; diff --git a/packages/commonjs/test/fixtures/function/esm-externals-false/main.js b/packages/commonjs/test/fixtures/function/esm-externals-false/main.js new file mode 100644 index 000000000..d1a5156cf --- /dev/null +++ b/packages/commonjs/test/fixtures/function/esm-externals-false/main.js @@ -0,0 +1,11 @@ +const externalExports = require('external-cjs-exports'); +const externalModuleExports = require('external-cjs-module-exports'); +const externalNamed = require('external-esm-named'); +const externalMixed = require('external-esm-mixed'); +const externalDefault = require('external-esm-default'); + +t.deepEqual(externalExports, { foo: 'foo' }, 'external exports'); +t.deepEqual(externalModuleExports, 'bar', 'external module exports'); +t.deepEqual(externalNamed, { foo: 'foo' }, 'external named'); +t.deepEqual(externalMixed, 'bar', 'external mixed'); +t.deepEqual(externalDefault, 'bar', 'external default'); diff --git a/packages/commonjs/test/fixtures/function/esm-externals-function/_config.js b/packages/commonjs/test/fixtures/function/esm-externals-function/_config.js new file mode 100644 index 000000000..990ca06e7 --- /dev/null +++ b/packages/commonjs/test/fixtures/function/esm-externals-function/_config.js @@ -0,0 +1,36 @@ +const assert = require('assert'); + +const called = {}; + +module.exports = { + description: 'always uses the default export when esmExternals is not used', + options: { + external: [ + 'external-cjs-exports', + 'external-cjs-module-exports', + 'external-esm-named', + 'external-esm-mixed', + 'external-esm-default' + ], + plugins: [ + { + name: 'test-plugin', + buildEnd() { + assert.deepStrictEqual(called, { + 'external-cjs-exports': 1, + 'external-cjs-module-exports': 1, + 'external-esm-named': 1, + 'external-esm-mixed': 1, + 'external-esm-default': 1 + }); + } + } + ] + }, + pluginOptions: { + esmExternals: (id) => { + called[id] = (called[id] || 0) + 1; + return id === 'external-esm-default'; + } + } +}; diff --git a/packages/commonjs/test/fixtures/function/esm-externals-function/main.js b/packages/commonjs/test/fixtures/function/esm-externals-function/main.js new file mode 100644 index 000000000..88aa332ec --- /dev/null +++ b/packages/commonjs/test/fixtures/function/esm-externals-function/main.js @@ -0,0 +1,11 @@ +const externalExports = require('external-cjs-exports'); +const externalModuleExports = require('external-cjs-module-exports'); +const externalNamed = require('external-esm-named'); +const externalMixed = require('external-esm-mixed'); +const externalDefault = require('external-esm-default'); + +t.deepEqual(externalExports, { foo: 'foo' }, 'external exports'); +t.deepEqual(externalModuleExports, 'bar', 'external module exports'); +t.deepEqual(externalNamed, { foo: 'foo' }, 'external named'); +t.deepEqual(externalMixed, 'bar', 'external mixed'); +t.deepEqual(externalDefault, { default: 'bar' }, 'external default'); diff --git a/packages/commonjs/test/fixtures/function/esm-externals-list/_config.js b/packages/commonjs/test/fixtures/function/esm-externals-list/_config.js new file mode 100644 index 000000000..dac64cda6 --- /dev/null +++ b/packages/commonjs/test/fixtures/function/esm-externals-list/_config.js @@ -0,0 +1,15 @@ +module.exports = { + description: 'always uses the default export when esmExternals is not used', + options: { + external: [ + 'external-cjs-exports', + 'external-cjs-module-exports', + 'external-esm-named', + 'external-esm-mixed', + 'external-esm-default' + ] + }, + pluginOptions: { + esmExternals: ['external-esm-default'] + } +}; diff --git a/packages/commonjs/test/fixtures/function/esm-externals-list/main.js b/packages/commonjs/test/fixtures/function/esm-externals-list/main.js new file mode 100644 index 000000000..88aa332ec --- /dev/null +++ b/packages/commonjs/test/fixtures/function/esm-externals-list/main.js @@ -0,0 +1,11 @@ +const externalExports = require('external-cjs-exports'); +const externalModuleExports = require('external-cjs-module-exports'); +const externalNamed = require('external-esm-named'); +const externalMixed = require('external-esm-mixed'); +const externalDefault = require('external-esm-default'); + +t.deepEqual(externalExports, { foo: 'foo' }, 'external exports'); +t.deepEqual(externalModuleExports, 'bar', 'external module exports'); +t.deepEqual(externalNamed, { foo: 'foo' }, 'external named'); +t.deepEqual(externalMixed, 'bar', 'external mixed'); +t.deepEqual(externalDefault, { default: 'bar' }, 'external default'); diff --git a/packages/commonjs/test/fixtures/function/esm-externals-true/_config.js b/packages/commonjs/test/fixtures/function/esm-externals-true/_config.js new file mode 100644 index 000000000..608ac5468 --- /dev/null +++ b/packages/commonjs/test/fixtures/function/esm-externals-true/_config.js @@ -0,0 +1,15 @@ +module.exports = { + description: 'always uses the default export when esmExternals is not used', + options: { + external: [ + 'external-cjs-exports', + 'external-cjs-module-exports', + 'external-esm-named', + 'external-esm-mixed', + 'external-esm-default' + ] + }, + pluginOptions: { + esmExternals: true + } +}; diff --git a/packages/commonjs/test/fixtures/function/esm-externals-true/main.js b/packages/commonjs/test/fixtures/function/esm-externals-true/main.js new file mode 100644 index 000000000..ca7736577 --- /dev/null +++ b/packages/commonjs/test/fixtures/function/esm-externals-true/main.js @@ -0,0 +1,11 @@ +const externalExports = require('external-cjs-exports'); +const externalModuleExports = require('external-cjs-module-exports'); +const externalNamed = require('external-esm-named'); +const externalMixed = require('external-esm-mixed'); +const externalDefault = require('external-esm-default'); + +t.deepEqual(externalExports, { foo: 'foo' }, 'external exports'); +t.deepEqual(externalModuleExports, 'bar', 'external module exports'); +t.deepEqual(externalNamed, { foo: 'foo' }, 'external named'); +t.deepEqual(externalMixed, { default: 'bar', foo: 'foo' }, 'external mixed'); +t.deepEqual(externalDefault, { default: 'bar' }, 'external default'); diff --git a/packages/commonjs/test/fixtures/function/esm-externals-undefined/_config.js b/packages/commonjs/test/fixtures/function/esm-externals-undefined/_config.js new file mode 100644 index 000000000..8415861e7 --- /dev/null +++ b/packages/commonjs/test/fixtures/function/esm-externals-undefined/_config.js @@ -0,0 +1,12 @@ +module.exports = { + description: 'always uses the default export when esmExternals is not used', + options: { + external: [ + 'external-cjs-exports', + 'external-cjs-module-exports', + 'external-esm-named', + 'external-esm-mixed', + 'external-esm-default' + ] + } +}; diff --git a/packages/commonjs/test/fixtures/function/esm-externals-undefined/main.js b/packages/commonjs/test/fixtures/function/esm-externals-undefined/main.js new file mode 100644 index 000000000..d1a5156cf --- /dev/null +++ b/packages/commonjs/test/fixtures/function/esm-externals-undefined/main.js @@ -0,0 +1,11 @@ +const externalExports = require('external-cjs-exports'); +const externalModuleExports = require('external-cjs-module-exports'); +const externalNamed = require('external-esm-named'); +const externalMixed = require('external-esm-mixed'); +const externalDefault = require('external-esm-default'); + +t.deepEqual(externalExports, { foo: 'foo' }, 'external exports'); +t.deepEqual(externalModuleExports, 'bar', 'external module exports'); +t.deepEqual(externalNamed, { foo: 'foo' }, 'external named'); +t.deepEqual(externalMixed, 'bar', 'external mixed'); +t.deepEqual(externalDefault, 'bar', 'external default'); diff --git a/packages/commonjs/test/fixtures/function/import-esm-require-returns-default-auto/_config.js b/packages/commonjs/test/fixtures/function/import-esm-require-returns-default-auto/_config.js index 29635f5c6..49dbcbf2c 100644 --- a/packages/commonjs/test/fixtures/function/import-esm-require-returns-default-auto/_config.js +++ b/packages/commonjs/test/fixtures/function/import-esm-require-returns-default-auto/_config.js @@ -5,6 +5,7 @@ module.exports = { external: ['external-esm-named', 'external-esm-mixed', 'external-esm-default'] }, pluginOptions: { - requireReturnsDefault: 'auto' + requireReturnsDefault: 'auto', + esmExternals: true } }; diff --git a/packages/commonjs/test/fixtures/function/import-esm-require-returns-default-false/_config.js b/packages/commonjs/test/fixtures/function/import-esm-require-returns-default-false/_config.js index 601675af8..ee92ea3f7 100644 --- a/packages/commonjs/test/fixtures/function/import-esm-require-returns-default-false/_config.js +++ b/packages/commonjs/test/fixtures/function/import-esm-require-returns-default-false/_config.js @@ -5,6 +5,7 @@ module.exports = { external: ['external-esm-named', 'external-esm-mixed', 'external-esm-default'] }, pluginOptions: { - requireReturnsDefault: false + requireReturnsDefault: false, + esmExternals: true } }; diff --git a/packages/commonjs/test/fixtures/function/import-esm-require-returns-default-function-called-once/_config.js b/packages/commonjs/test/fixtures/function/import-esm-require-returns-default-function-called-once/_config.js index 7c2aaee85..69cd937f2 100644 --- a/packages/commonjs/test/fixtures/function/import-esm-require-returns-default-function-called-once/_config.js +++ b/packages/commonjs/test/fixtures/function/import-esm-require-returns-default-function-called-once/_config.js @@ -1,10 +1,6 @@ const assert = require('assert'); -const called = { - 'main.js': 0, - 'both.js': 0, - 'other.js': 0 -}; +const called = {}; module.exports = { description: 'only calls a requireReturnsDefault function once per id', @@ -37,7 +33,7 @@ module.exports = { requireReturnsDefault: (id) => { const [prefix, name] = id.split('_'); if (prefix === 'dep') { - called[name] += 1; + called[name] = (called[name] || 0) + 1; return 'preferred'; } return false; diff --git a/packages/commonjs/test/fixtures/function/import-esm-require-returns-default-function-external/_config.js b/packages/commonjs/test/fixtures/function/import-esm-require-returns-default-function-external/_config.js index 5c408d55b..7433b2b61 100644 --- a/packages/commonjs/test/fixtures/function/import-esm-require-returns-default-function-external/_config.js +++ b/packages/commonjs/test/fixtures/function/import-esm-require-returns-default-function-external/_config.js @@ -8,6 +8,7 @@ module.exports = { if (id === 'external-esm-mixed') return true; if (id === 'external-esm-default') return false; return 'auto'; - } + }, + esmExternals: true } }; diff --git a/packages/commonjs/test/fixtures/function/import-esm-require-returns-default-preferred/_config.js b/packages/commonjs/test/fixtures/function/import-esm-require-returns-default-preferred/_config.js index b3f986fd0..6cec5f85f 100644 --- a/packages/commonjs/test/fixtures/function/import-esm-require-returns-default-preferred/_config.js +++ b/packages/commonjs/test/fixtures/function/import-esm-require-returns-default-preferred/_config.js @@ -5,6 +5,7 @@ module.exports = { external: ['external-esm-named', 'external-esm-mixed', 'external-esm-default'] }, pluginOptions: { - requireReturnsDefault: 'preferred' + requireReturnsDefault: 'preferred', + esmExternals: true } }; diff --git a/packages/commonjs/test/fixtures/function/import-esm-require-returns-default-true/_config.js b/packages/commonjs/test/fixtures/function/import-esm-require-returns-default-true/_config.js index 157a33919..a65484de0 100644 --- a/packages/commonjs/test/fixtures/function/import-esm-require-returns-default-true/_config.js +++ b/packages/commonjs/test/fixtures/function/import-esm-require-returns-default-true/_config.js @@ -5,6 +5,7 @@ module.exports = { external: ['external-esm-named', 'external-esm-mixed', 'external-esm-default'] }, pluginOptions: { - requireReturnsDefault: true + requireReturnsDefault: true, + esmExternals: true } }; diff --git a/packages/commonjs/test/fixtures/function/import-esm-require-returns-default-undefined/_config.js b/packages/commonjs/test/fixtures/function/import-esm-require-returns-default-undefined/_config.js index 2a9b1188d..66dd8481d 100644 --- a/packages/commonjs/test/fixtures/function/import-esm-require-returns-default-undefined/_config.js +++ b/packages/commonjs/test/fixtures/function/import-esm-require-returns-default-undefined/_config.js @@ -3,5 +3,8 @@ module.exports = { 'returns the namespace when requiring an ES module and requireReturnsDefault is missing', options: { external: ['external-esm-named', 'external-esm-mixed', 'external-esm-default'] + }, + pluginOptions: { + esmExternals: true } }; diff --git a/packages/commonjs/test/snapshots/function.js.md b/packages/commonjs/test/snapshots/function.js.md index af858ea6a..b4aa0def7 100644 --- a/packages/commonjs/test/snapshots/function.js.md +++ b/packages/commonjs/test/snapshots/function.js.md @@ -778,7 +778,9 @@ Generated by [AVA](https://ava.li). { 'main.js': `'use strict';␊ ␊ - var path = require('path');␊ + function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }␊ + ␊ + var Path = _interopDefault(require('path'));␊ ␊ var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};␊ ␊ @@ -929,7 +931,7 @@ Generated by [AVA](https://ava.li). ␊ const basePath = `${process.cwd()}/fixtures/function/dynamic-require-absolute-paths`;␊ ␊ - t.is(commonjsRequire(path.resolve(`${basePath}/submodule.js`),"/$$rollup_base$$/fixtures/function/dynamic-require-absolute-paths"), 'submodule');␊ + t.is(commonjsRequire(Path.resolve(`${basePath}/submodule.js`),"/$$rollup_base$$/fixtures/function/dynamic-require-absolute-paths"), 'submodule');␊ ␊ var main = {␊ ␊ @@ -2777,6 +2779,149 @@ Generated by [AVA](https://ava.li). `, } +## esm-externals-false + +> Snapshot 1 + + { + 'main.js': `'use strict';␊ + ␊ + function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }␊ + ␊ + var externalExports = _interopDefault(require('external-cjs-exports'));␊ + var externalModuleExports = _interopDefault(require('external-cjs-module-exports'));␊ + var externalNamed = _interopDefault(require('external-esm-named'));␊ + var externalMixed = _interopDefault(require('external-esm-mixed'));␊ + var externalDefault = _interopDefault(require('external-esm-default'));␊ + ␊ + t.deepEqual(externalExports, { foo: 'foo' }, 'external exports');␊ + t.deepEqual(externalModuleExports, 'bar', 'external module exports');␊ + t.deepEqual(externalNamed, { foo: 'foo' }, 'external named');␊ + t.deepEqual(externalMixed, 'bar', 'external mixed');␊ + t.deepEqual(externalDefault, 'bar', 'external default');␊ + ␊ + var main = {␊ + ␊ + };␊ + ␊ + module.exports = main;␊ + `, + } + +## esm-externals-function + +> Snapshot 1 + + { + 'main.js': `'use strict';␊ + ␊ + function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }␊ + ␊ + var externalExports = _interopDefault(require('external-cjs-exports'));␊ + var externalModuleExports = _interopDefault(require('external-cjs-module-exports'));␊ + var externalNamed = _interopDefault(require('external-esm-named'));␊ + var externalMixed = _interopDefault(require('external-esm-mixed'));␊ + var externalEsmDefault = require('external-esm-default');␊ + ␊ + t.deepEqual(externalExports, { foo: 'foo' }, 'external exports');␊ + t.deepEqual(externalModuleExports, 'bar', 'external module exports');␊ + t.deepEqual(externalNamed, { foo: 'foo' }, 'external named');␊ + t.deepEqual(externalMixed, 'bar', 'external mixed');␊ + t.deepEqual(externalEsmDefault, { default: 'bar' }, 'external default');␊ + ␊ + var main = {␊ + ␊ + };␊ + ␊ + module.exports = main;␊ + `, + } + +## esm-externals-list + +> Snapshot 1 + + { + 'main.js': `'use strict';␊ + ␊ + function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }␊ + ␊ + var externalExports = _interopDefault(require('external-cjs-exports'));␊ + var externalModuleExports = _interopDefault(require('external-cjs-module-exports'));␊ + var externalNamed = _interopDefault(require('external-esm-named'));␊ + var externalMixed = _interopDefault(require('external-esm-mixed'));␊ + var externalEsmDefault = require('external-esm-default');␊ + ␊ + t.deepEqual(externalExports, { foo: 'foo' }, 'external exports');␊ + t.deepEqual(externalModuleExports, 'bar', 'external module exports');␊ + t.deepEqual(externalNamed, { foo: 'foo' }, 'external named');␊ + t.deepEqual(externalMixed, 'bar', 'external mixed');␊ + t.deepEqual(externalEsmDefault, { default: 'bar' }, 'external default');␊ + ␊ + var main = {␊ + ␊ + };␊ + ␊ + module.exports = main;␊ + `, + } + +## esm-externals-true + +> Snapshot 1 + + { + 'main.js': `'use strict';␊ + ␊ + var externalCjsExports = require('external-cjs-exports');␊ + var externalCjsModuleExports = require('external-cjs-module-exports');␊ + var externalEsmNamed = require('external-esm-named');␊ + var externalEsmMixed = require('external-esm-mixed');␊ + var externalEsmDefault = require('external-esm-default');␊ + ␊ + t.deepEqual(externalCjsExports, { foo: 'foo' }, 'external exports');␊ + t.deepEqual(externalCjsModuleExports, 'bar', 'external module exports');␊ + t.deepEqual(externalEsmNamed, { foo: 'foo' }, 'external named');␊ + t.deepEqual(externalEsmMixed, { default: 'bar', foo: 'foo' }, 'external mixed');␊ + t.deepEqual(externalEsmDefault, { default: 'bar' }, 'external default');␊ + ␊ + var main = {␊ + ␊ + };␊ + ␊ + module.exports = main;␊ + `, + } + +## esm-externals-undefined + +> Snapshot 1 + + { + 'main.js': `'use strict';␊ + ␊ + function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }␊ + ␊ + var externalExports = _interopDefault(require('external-cjs-exports'));␊ + var externalModuleExports = _interopDefault(require('external-cjs-module-exports'));␊ + var externalNamed = _interopDefault(require('external-esm-named'));␊ + var externalMixed = _interopDefault(require('external-esm-mixed'));␊ + var externalDefault = _interopDefault(require('external-esm-default'));␊ + ␊ + t.deepEqual(externalExports, { foo: 'foo' }, 'external exports');␊ + t.deepEqual(externalModuleExports, 'bar', 'external module exports');␊ + t.deepEqual(externalNamed, { foo: 'foo' }, 'external named');␊ + t.deepEqual(externalMixed, 'bar', 'external mixed');␊ + t.deepEqual(externalDefault, 'bar', 'external default');␊ + ␊ + var main = {␊ + ␊ + };␊ + ␊ + module.exports = main;␊ + `, + } + ## export-default-from > Snapshot 1 @@ -2827,7 +2972,9 @@ Generated by [AVA](https://ava.li). { 'main.js': `'use strict';␊ ␊ - var foo = require('foo');␊ + function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }␊ + ␊ + var foo = _interopDefault(require('foo'));␊ ␊ var main = foo;␊ ␊ diff --git a/packages/commonjs/test/snapshots/function.js.snap b/packages/commonjs/test/snapshots/function.js.snap index 768fb0d09..db8a75baa 100644 Binary files a/packages/commonjs/test/snapshots/function.js.snap and b/packages/commonjs/test/snapshots/function.js.snap differ