Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(commonjs): Expose cjs detection and support offline caching #604

Merged
merged 1 commit into from Oct 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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);
}