Skip to content

Commit

Permalink
feat(commonjs): Expose cjs detection and support offline caching
Browse files Browse the repository at this point in the history
BREAKING CHANGES: Raises minimal required Rollup version to 2.30.0
  • Loading branch information
lukastaegert committed Oct 15, 2020
1 parent ae30f42 commit 305605d
Show file tree
Hide file tree
Showing 15 changed files with 605 additions and 121 deletions.
20 changes: 20 additions & 0 deletions packages/commonjs/README.md
Expand Up @@ -311,6 +311,26 @@ ES modules are _always_ parsed in strict mode. That means that certain non-stric

Luckily, there is absolutely no good reason _not_ to use strict mode for everything — so the solution to this problem is to lobby the authors of those modules to update them.

## Inter-plugin-communication

This plugin exposes the result of its CommonJS file type detection for other plugins to use. You can access it via `this.getModuleInfo` or the `moduleParsed` hook:

```js
function cjsDetectionPlugin() {
return {
name: 'cjs-detection',
moduleParsed({
id,
meta: {
commonjs: { isCommonJS },
},
}) {
console.log(`File ${id} is CommonJS: ${isCommonJS}`);
},
};
}
```

## Meta

[CONTRIBUTING](/.github/CONTRIBUTING.md)
Expand Down
4 changes: 2 additions & 2 deletions packages/commonjs/package.json
Expand Up @@ -47,7 +47,7 @@
"require"
],
"peerDependencies": {
"rollup": "^2.22.0"
"rollup": "^2.30.0"
},
"dependencies": {
"@rollup/pluginutils": "^3.1.0",
Expand All @@ -63,7 +63,7 @@
"@rollup/plugin-node-resolve": "^8.4.0",
"locate-character": "^2.0.5",
"require-relative": "^0.8.7",
"rollup": "^2.23.0",
"rollup": "^2.30.0",
"shx": "^0.3.2",
"source-map": "^0.7.3",
"source-map-support": "^0.5.19",
Expand Down
27 changes: 14 additions & 13 deletions packages/commonjs/src/index.js
Expand Up @@ -103,14 +103,13 @@ export default function commonjs(options = {}) {
!dynamicRequireModuleSet.has(normalizePathSlashes(id)) &&
(!hasCjsKeywords(code, ignoreGlobal) || (isEsModule && !options.transformMixedEsModules))
) {
setIsCjsPromise(id, false);
return null;
return { meta: { commonjs: { isCommonJS: false } } };
}

// avoid wrapping in createCommonjsModule, as this is a commonjsRegister call
const disableWrap = isModuleRegistrationProxy(id, dynamicRequireModuleSet);

const transformed = transformCommonjs(
return transformCommonjs(
this.parse,
code,
id,
Expand All @@ -124,9 +123,6 @@ export default function commonjs(options = {}) {
commonDir,
ast
);

setIsCjsPromise(id, isEsModule ? false : Boolean(transformed));
return transformed;
}

return {
Expand Down Expand Up @@ -201,20 +197,25 @@ export default function commonjs(options = {}) {
!id.startsWith(DYNAMIC_JSON_PREFIX) &&
(!filter(id) || !extensions.includes(extName))
) {
setIsCjsPromise(id, null);
return null;
}

let transformed;
try {
transformed = transformAndCheckExports.call(this, code, id);
return transformAndCheckExports.call(this, code, id);
} catch (err) {
transformed = null;
setIsCjsPromise(id, false);
this.error(err, err.loc);
return this.error(err, err.loc);
}
},

return transformed;
moduleParsed({ id, meta: { commonjs } }) {
if (commonjs) {
const isCjs = commonjs.isCommonJS;
if (isCjs != null) {
setIsCjsPromise(id, isCjs);
return;
}
}
setIsCjsPromise(id, null);
}
};
}
7 changes: 3 additions & 4 deletions packages/commonjs/src/is-cjs.js
@@ -1,4 +1,3 @@
/* eslint-disable no-undefined */
const isCjsPromises = new Map();

export function getIsCjsPromise(id) {
Expand All @@ -8,7 +7,7 @@ export function getIsCjsPromise(id) {
const promise = new Promise((resolve) => {
isCjsPromise = {
resolve,
promise: undefined
promise: null
};
isCjsPromises.set(id, isCjsPromise);
});
Expand All @@ -22,9 +21,9 @@ export function setIsCjsPromise(id, resolution) {
if (isCjsPromise) {
if (isCjsPromise.resolve) {
isCjsPromise.resolve(resolution);
isCjsPromise.resolve = undefined;
isCjsPromise.resolve = null;
}
} else {
isCjsPromises.set(id, { promise: Promise.resolve(resolution), resolve: undefined });
isCjsPromises.set(id, { promise: Promise.resolve(resolution), resolve: null });
}
}
10 changes: 7 additions & 3 deletions packages/commonjs/src/transform.js
Expand Up @@ -560,8 +560,7 @@ export function transformCommonjs(
!usesCommonjsHelpers &&
(ignoreGlobal || !uses.global)
) {
// not a CommonJS module
return null;
return { meta: { commonjs: { isCommonJS: false } } };
}

const importBlock = `${(usesCommonjsHelpers
Expand Down Expand Up @@ -698,5 +697,10 @@ export function transformCommonjs(
code = magicString.toString();
const map = sourceMap ? magicString.generateMap() : null;

return { code, map, syntheticNamedExports: isEsModule ? false : '__moduleExports' };
return {
code,
map,
syntheticNamedExports: isEsModule ? false : '__moduleExports',
meta: { commonjs: { isCommonJS: !isEsModule } }
};
}
@@ -0,0 +1,33 @@
const path = require('path');

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

module.exports = {
description: 'exposes cjs file type detection to other plugins',
options: {
input: [ID_MAIN, ID_OTHER],
plugins: [
{
moduleParsed({
id,
meta: {
commonjs: { isCommonJS }
}
}) {
if (id === ID_MAIN) {
if (isCommonJS !== false) {
throw new Error(
`Main file wrongly detected: isCommonJS === ${JSON.stringify(isCommonJS)}`
);
}
} else if (isCommonJS !== true) {
throw new Error(
`Other file wrongly detected: isCommonJS === ${JSON.stringify(isCommonJS)}`
);
}
}
}
]
}
};
@@ -0,0 +1,3 @@
import foo from './other.js';

t.is(foo, 'foo');
@@ -0,0 +1 @@
module.exports = 'foo';
1 change: 1 addition & 0 deletions packages/commonjs/test/fixtures/samples/caching/dep.js
@@ -0,0 +1 @@
exports.dep = 42;
3 changes: 3 additions & 0 deletions packages/commonjs/test/fixtures/samples/caching/main.js
@@ -0,0 +1,3 @@
const dep = require('./dep');

console.log(dep);
20 changes: 20 additions & 0 deletions packages/commonjs/test/fixtures/samples/caching/rollupWorker.js
@@ -0,0 +1,20 @@
const { workerData, parentPort } = require('worker_threads');

const { rollup } = require('rollup');

const commonjs = require('../../../../dist/index');
const { getCodeFromBundle } = require('../../../helpers/util');

generateCode(workerData);

async function generateCode(cache) {
const code = await getCodeFromBundle(
await rollup({
input: 'fixtures/samples/caching/main.js',
cache,
plugins: [commonjs()]
})
);

parentPort.postMessage(code);
}

0 comments on commit 305605d

Please sign in to comment.