Skip to content

Commit

Permalink
feat(commonjs): support all styles of transpiled ES modules
Browse files Browse the repository at this point in the history
BREAKING CHANGES: CJS entry points will always have a default export
  • Loading branch information
lukastaegert committed Jul 18, 2020
1 parent 72f84a2 commit d8e3a6f
Show file tree
Hide file tree
Showing 38 changed files with 749 additions and 91 deletions.
12 changes: 12 additions & 0 deletions packages/commonjs/src/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,21 @@ export const HELPERS_ID = '\0commonjsHelpers.js';

// `x['default']` is used instead of `x.default` for backward compatibility with ES3 browsers.
// Minifiers like uglify will usually transpile it back if compatibility with ES3 is not enabled.
// This will no longer be necessary once Rollup switches to ES6 output, likely
// in Rollup 3

// The "hasOwnProperty" call in "getDefaultExportFromCjs" is technically not
// needed, but for consumers that use Rollup's old interop pattern, it will fix
// rollup/rollup-plugin-commonjs#224
// We should remove it once Rollup core and this plugin are updated to not use
// this pattern any more
export const HELPERS = `
export var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
export function getDefaultExportFromCjs (x) {
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
}
export function createCommonjsModule(fn, basedir, module) {
return module = {
path: basedir,
Expand Down
4 changes: 0 additions & 4 deletions packages/commonjs/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,10 @@ export default function commonjs(options = {}) {
return null;
}

const moduleInfo = this.getModuleInfo(id);

const transformed = transformCommonjs(
this.parse,
code,
id,
moduleInfo.isEntry,
moduleInfo.importers && moduleInfo.importers.length > 0,
isEsModule,
ignoreGlobal || isEsModule,
ignoreRequire,
Expand Down
39 changes: 18 additions & 21 deletions packages/commonjs/src/transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,6 @@ export function transformCommonjs(
parse,
code,
id,
isEntry,
hasImporters,
isEsModule,
ignoreGlobal,
ignoreRequire,
Expand Down Expand Up @@ -577,7 +575,7 @@ export function transformCommonjs(
let wrapperEnd = '';

const moduleName = deconflict(scope, globals, getName(id));
if ((!isEntry || hasImporters) && !isEsModule) {
if (!isEsModule) {
const exportModuleExports = {
str: `export { ${moduleName} as __moduleExports };`,
name: '__moduleExports'
Expand Down Expand Up @@ -647,38 +645,37 @@ export function transformCommonjs(
}
}

if (!hasDefaultExport && (names.length || ((!isEntry || hasImporters) && !isEsModule))) {
if (!(isEsModule || hasDefaultExport)) {
wrapperEnd = `\n\nvar ${moduleName} = {\n${names
.map(({ name, deconflicted }) => `\t${name}: ${deconflicted}`)
.join(',\n')}\n};`;
}
}

const defaultExport = `export default ${moduleName};`;

const named = namedExportDeclarations
.filter((x) => x.name !== 'default' || !hasDefaultExport)
.map((x) => x.str);

const exportBlock = `\n\n${(isEsModule ? [] : [defaultExport])
.concat(named)
.concat(hasDefaultExport ? defaultExportPropertyAssignments : [])
.join('\n')}`;

magicString
.trim()
.prepend(importBlock + wrapperStart)
.trim()
.append(wrapperEnd);

const injectExportBlock =
hasDefaultExport || named.length > 0 || shouldWrap || !isEntry || hasImporters;
if (injectExportBlock) {
magicString.append(exportBlock);
}
const defaultExport =
code.indexOf('__esModule') >= 0
? `export default /*@__PURE__*/${HELPERS_NAME}.getDefaultExportFromCjs(${moduleName});`
: `export default ${moduleName};`;

const named = namedExportDeclarations
.filter((x) => x.name !== 'default' || !hasDefaultExport)
.map((x) => x.str);

magicString.append(
`\n\n${(isEsModule ? [] : [defaultExport])
.concat(named)
.concat(hasDefaultExport ? defaultExportPropertyAssignments : [])
.join('\n')}`
);

code = magicString.toString();
const map = sourceMap ? magicString.generateMap() : null;

return { code, map, syntheticNamedExports: injectExportBlock };
return { code, map, syntheticNamedExports: '__moduleExports' };
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,10 @@ var foo = function () {
};

var input = 42;

var input_1 = {

};

export default input_1;
export { input_1 as __moduleExports };
3 changes: 0 additions & 3 deletions packages/commonjs/test/fixtures/function/__esModule/answer.js

This file was deleted.

4 changes: 0 additions & 4 deletions packages/commonjs/test/fixtures/function/__esModule/main.js

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const path = require('path');
const fs = require('fs');

const ID_MAIN = path.join(__dirname, 'main.js');
const ID_OTHER = path.join(__dirname, 'other.js');

module.exports = {
options: {
input: [ID_MAIN, ID_OTHER],
plugins: [
{
load(id) {
if (id === ID_MAIN) {
return new Promise((resolve) =>
setTimeout(() => resolve(fs.readFileSync(ID_MAIN, 'utf8')), 100)
);
}
return null;
}
}
]
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const foo = require('./other.js');

t.is(foo, 'foo');
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = 'foo';
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = 42;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const dep = require('./dep.js');

t.is(dep, 42);
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Object.defineProperty(exports, '__esModule', { value: true });
exports.default = 'default';
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import dep from './dep';

t.is(dep, 'default');
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const path = require('path');

module.exports = {
description:
'Creates correct exports if an ES module that was transpiled to CJS is used as entry point',
options: {
input: [path.join(__dirname, 'main.js'), path.join(__dirname, 'entry.js')]
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Object.defineProperty(exports, '__esModule', { value: true });
exports.default = 'default';
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import * as entry from './entry.js';

t.deepEqual(entry, { default: 'default' });
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const path = require('path');

module.exports = {
description:
'Creates correct exports if an ES module that was transpiled to CJS is used as entry point',
options: {
input: [path.join(__dirname, 'main.js'), path.join(__dirname, 'entry.js')]
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Object.defineProperty(exports, '__esModule', { value: true });
exports.default = 'default';
exports.named = 'named';
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import * as entry from './entry.js';

t.deepEqual(entry, { default: 'default', named: 'named' });
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const path = require('path');

module.exports = {
description:
'Creates correct exports if an ES module that was transpiled to CJS is used as entry point',
options: {
input: [path.join(__dirname, 'main.js'), path.join(__dirname, 'entry.js')]
}
};
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
Object.defineProperty(exports, '__esModule', { value: true });
exports.x = 10;
exports.named = 'named';
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import * as entry from './entry.js';

t.deepEqual(entry, {
// Technically, this should ideally not exist, or if we cannot avoid it due
// to runtime default export detection, it should probably be undefined. We
// return the namespace instead as this will fix
// rollup/rollup-plugin-commonjs#224 until the remaining Rollup interop has
// been updated
default: { named: 'named' },
named: 'named'
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Object.defineProperty(exports, '__esModule', { value: true });
exports.named = 'named';
exports.default = 'default';
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import dep, { named } from './dep';

t.is(dep, 'default');
t.is(named, 'named');
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Object.defineProperty(exports, '__esModule', { value: true });
exports.named = 'named';
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { named } from './dep';

t.is(named, 'named');
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Object.defineProperty(exports, '__esModule', { value: true });
exports.default = 'default';
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import * as x from './dep';

t.deepEqual(x, {
default: 'default'
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Object.defineProperty(exports, '__esModule', { value: true });
exports.named = 'named';
exports.default = 'default';
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import * as x from './dep';

t.deepEqual(x, {
default: 'default',
named: 'named'
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Object.defineProperty(exports, '__esModule', { value: true });
exports.named = 'named';
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import * as x from './dep';

t.deepEqual(x, {
named: 'named',
// Technically, this should ideally not exist, or if we cannot avoid it due
// to runtime default export detection, it should probably be undefined. We
// return the namespace instead as this will fix
// rollup/rollup-plugin-commonjs#224 until the remaining Rollup interop has
// been updated
default: { named: 'named' }
});

This file was deleted.

Loading

0 comments on commit d8e3a6f

Please sign in to comment.