Skip to content

Commit 274ba1c

Browse files
authored
feat(commonjs): pass type of import to node-resolve (#611)
* refactor(commonjs): Refine logic for id wrapping, import transformation * feat(commonjs): Pass type of import to node-resolve
1 parent 70fad01 commit 274ba1c

File tree

35 files changed

+455
-184
lines changed

35 files changed

+455
-184
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
"@ava/babel": "^1.0.1",
2727
"@typescript-eslint/eslint-plugin": "^3.7.1",
2828
"@typescript-eslint/parser": "^3.7.1",
29-
"ava": "^3.11.0",
29+
"ava": "^3.13.0",
3030
"chalk": "^4.1.0",
3131
"codecov-lite": "^1.0.3",
3232
"del-cli": "^3.0.1",
@@ -36,7 +36,7 @@
3636
"husky": "^4.2.5",
3737
"lint-staged": "^10.2.11",
3838
"nyc": "^15.1.0",
39-
"pnpm": "^5.4.6",
39+
"pnpm": "^5.9.3",
4040
"prettier": "^2.0.5",
4141
"prettier-plugin-package": "^1.0.0",
4242
"ts-node": "^8.10.2",

packages/commonjs/README.md

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ export default {
3434
input: 'src/index.js',
3535
output: {
3636
dir: 'output',
37-
format: 'cjs',
37+
format: 'cjs'
3838
},
39-
plugins: [commonjs()],
39+
plugins: [commonjs()]
4040
};
4141
```
4242

@@ -66,8 +66,8 @@ commonjs({
6666
'!node_modules/logform/index.js',
6767
'!node_modules/logform/format.js',
6868
'!node_modules/logform/levels.js',
69-
'!node_modules/logform/browser.js',
70-
],
69+
'!node_modules/logform/browser.js'
70+
]
7171
});
7272
```
7373

@@ -143,7 +143,7 @@ You can also supply an array of ids to be treated as ES modules, or a function t
143143

144144
### `requireReturnsDefault`
145145

146-
Type: `boolean | "auto" | "preferred" | ((id: string) => boolean | "auto" | "preferred")`<br>
146+
Type: `boolean | "namespace" | "auto" | "preferred" | ((id: string) => boolean | "auto" | "preferred")`<br>
147147
Default: `false`
148148

149149
Controls what is returned when requiring an ES module from a CommonJS file. When using the `esmExternals` option, this will also apply to external modules. By default, this plugin will render those imports as namespace imports, i.e.
@@ -174,7 +174,7 @@ This is in line with how other bundlers handle this situation and is also the mo
174174

175175
var dep$1 = /*#__PURE__*/ Object.freeze({
176176
__proto__: null,
177-
default: dep,
177+
default: dep
178178
});
179179

180180
console.log(dep$1.default);
@@ -205,7 +205,7 @@ For these situations, you can change Rollup's behaviour either globally or per m
205205
enumerable: true,
206206
get: function () {
207207
return n[k];
208-
},
208+
}
209209
}
210210
);
211211
});
@@ -287,9 +287,9 @@ export default {
287287
output: {
288288
file: 'bundle.js',
289289
format: 'iife',
290-
name: 'MyModule',
290+
name: 'MyModule'
291291
},
292-
plugins: [resolve(), commonjs()],
292+
plugins: [resolve(), commonjs()]
293293
};
294294
```
295295

@@ -299,7 +299,7 @@ Symlinks are common in monorepos and are also created by the `npm link` command.
299299

300300
```js
301301
commonjs({
302-
include: /node_modules/,
302+
include: /node_modules/
303303
});
304304
```
305305

@@ -322,11 +322,11 @@ function cjsDetectionPlugin() {
322322
moduleParsed({
323323
id,
324324
meta: {
325-
commonjs: { isCommonJS },
326-
},
325+
commonjs: { isCommonJS }
326+
}
327327
}) {
328328
console.log(`File ${id} is CommonJS: ${isCommonJS}`);
329-
},
329+
}
330330
};
331331
}
332332
```

packages/commonjs/src/dynamic-packages-manager.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,7 @@ export function getDynamicPackagesEntryIntro(
4343
).join('\n');
4444

4545
if (dynamicRequireModuleDirPaths.length) {
46-
dynamicImports += `require(${JSON.stringify(
47-
DYNAMIC_REGISTER_PREFIX + DYNAMIC_PACKAGES_ID
48-
)});`;
46+
dynamicImports += `require(${JSON.stringify(DYNAMIC_REGISTER_PREFIX + DYNAMIC_PACKAGES_ID)});`;
4947
}
5048

5149
return dynamicImports;

packages/commonjs/src/helpers.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
export const PROXY_SUFFIX = '?commonjs-proxy';
2-
export const getProxyId = (id) => `\0${id}${PROXY_SUFFIX}`;
3-
export const getIdFromProxyId = (proxyId) => proxyId.slice(1, -PROXY_SUFFIX.length);
1+
export const isWrappedId = (id, suffix) => id.endsWith(suffix);
2+
export const wrapId = (id, suffix) => `\0${id}${suffix}`;
3+
export const unwrapId = (wrappedId, suffix) => wrappedId.slice(1, -suffix.length);
44

5+
export const PROXY_SUFFIX = '?commonjs-proxy';
6+
export const REQUIRE_SUFFIX = '?commonjs-require';
57
export const EXTERNAL_SUFFIX = '?commonjs-external';
6-
export const getExternalProxyId = (id) => `\0${id}${EXTERNAL_SUFFIX}`;
7-
export const getIdFromExternalProxyId = (proxyId) => proxyId.slice(1, -EXTERNAL_SUFFIX.length);
88

99
export const VIRTUAL_PATH_BASE = '/$$rollup_base$$';
1010
export const getVirtualPathForDynamicRequirePath = (path, commonDir) => {

packages/commonjs/src/index.js

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ import {
1616
DYNAMIC_PACKAGES_ID,
1717
EXTERNAL_SUFFIX,
1818
getHelpersModule,
19-
getIdFromExternalProxyId,
20-
getIdFromProxyId,
2119
HELPERS_ID,
22-
PROXY_SUFFIX
20+
isWrappedId,
21+
PROXY_SUFFIX,
22+
unwrapId
2323
} from './helpers';
2424
import { setIsCjsPromise } from './is-cjs';
2525
import {
@@ -81,10 +81,8 @@ export default function commonjs(options = {}) {
8181

8282
function transformAndCheckExports(code, id) {
8383
if (isDynamicRequireModulesEnabled && this.getModuleInfo(id).isEntry) {
84-
code = getDynamicPackagesEntryIntro(
85-
dynamicRequireModuleDirPaths,
86-
dynamicRequireModuleSet
87-
) + code;
84+
code =
85+
getDynamicPackagesEntryIntro(dynamicRequireModuleDirPaths, dynamicRequireModuleSet) + code;
8886
}
8987

9088
const { isEsModule, hasDefaultExport, hasNamedExports, ast } = checkEsModule(
@@ -156,8 +154,8 @@ export default function commonjs(options = {}) {
156154
return getSpecificHelperProxy(id);
157155
}
158156

159-
if (id.endsWith(EXTERNAL_SUFFIX)) {
160-
const actualId = getIdFromExternalProxyId(id);
157+
if (isWrappedId(id, EXTERNAL_SUFFIX)) {
158+
const actualId = unwrapId(id, EXTERNAL_SUFFIX);
161159
return getUnknownRequireProxy(
162160
actualId,
163161
isEsmExternal(actualId) ? getRequireReturnsDefault(actualId) : true
@@ -176,8 +174,8 @@ export default function commonjs(options = {}) {
176174
return getDynamicRequireProxy(normalizePathSlashes(id), commonDir);
177175
}
178176

179-
if (id.endsWith(PROXY_SUFFIX)) {
180-
const actualId = getIdFromProxyId(id);
177+
if (isWrappedId(id, PROXY_SUFFIX)) {
178+
const actualId = unwrapId(id, PROXY_SUFFIX);
181179
return getStaticRequireProxy(
182180
actualId,
183181
getRequireReturnsDefault(actualId),

packages/commonjs/src/resolve-id.js

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ import { dirname, resolve, sep } from 'path';
66
import {
77
DYNAMIC_JSON_PREFIX,
88
DYNAMIC_PACKAGES_ID,
9-
getExternalProxyId,
10-
getIdFromProxyId,
11-
getProxyId,
9+
EXTERNAL_SUFFIX,
1210
HELPERS_ID,
13-
PROXY_SUFFIX
11+
isWrappedId,
12+
PROXY_SUFFIX,
13+
REQUIRE_SUFFIX,
14+
unwrapId,
15+
wrapId
1416
} from './helpers';
1517

1618
function getCandidatesForExtension(resolved, extension) {
@@ -44,10 +46,18 @@ export default function getResolveId(extensions) {
4446
return undefined;
4547
}
4648

47-
function resolveId(importee, importer) {
48-
const isProxyModule = importee.endsWith(PROXY_SUFFIX);
49+
return function resolveId(importee, importer) {
50+
// Proxies are only importing resolved ids, no need to resolve again
51+
if (importer && isWrappedId(importer, PROXY_SUFFIX)) {
52+
return importee;
53+
}
54+
55+
const isProxyModule = isWrappedId(importee, PROXY_SUFFIX);
56+
const isRequiredModule = isWrappedId(importee, REQUIRE_SUFFIX);
4957
if (isProxyModule) {
50-
importee = getIdFromProxyId(importee);
58+
importee = unwrapId(importee, PROXY_SUFFIX);
59+
} else if (isRequiredModule) {
60+
importee = unwrapId(importee, REQUIRE_SUFFIX);
5161
}
5262
if (importee.startsWith('\0')) {
5363
if (
@@ -57,30 +67,23 @@ export default function getResolveId(extensions) {
5767
) {
5868
return importee;
5969
}
60-
if (!isProxyModule) {
61-
return null;
62-
}
70+
return null;
6371
}
6472

65-
if (importer && importer.endsWith(PROXY_SUFFIX)) {
66-
importer = getIdFromProxyId(importer);
67-
}
68-
69-
return this.resolve(importee, importer, { skipSelf: true }).then((resolved) => {
73+
return this.resolve(importee, importer, {
74+
skipSelf: true,
75+
custom: { 'node-resolve': { isRequire: isProxyModule || isRequiredModule } }
76+
}).then((resolved) => {
7077
if (!resolved) {
7178
resolved = resolveExtensions(importee, importer);
7279
}
73-
if (isProxyModule) {
74-
if (!resolved) {
75-
return { id: getExternalProxyId(importee), external: false };
76-
}
77-
resolved.id = (resolved.external ? getExternalProxyId : getProxyId)(resolved.id);
80+
if (resolved && isProxyModule) {
81+
resolved.id = wrapId(resolved.id, resolved.external ? EXTERNAL_SUFFIX : PROXY_SUFFIX);
7882
resolved.external = false;
79-
return resolved;
83+
} else if (!resolved && (isProxyModule || isRequiredModule)) {
84+
return { id: wrapId(importee, EXTERNAL_SUFFIX), external: false };
8085
}
8186
return resolved;
8287
});
83-
}
84-
85-
return resolveId;
88+
};
8689
}

packages/commonjs/src/transform.js

Lines changed: 32 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@ import { flatten, isFalsy, isReference, isTruthy } from './ast-utils';
1111
import {
1212
DYNAMIC_JSON_PREFIX,
1313
DYNAMIC_REGISTER_PREFIX,
14-
getProxyId,
1514
getVirtualPathForDynamicRequirePath,
16-
HELPERS_ID
15+
HELPERS_ID,
16+
PROXY_SUFFIX,
17+
REQUIRE_SUFFIX,
18+
wrapId
1719
} from './helpers';
1820
import { getName } from './utils';
1921

@@ -138,7 +140,8 @@ export function transformCommonjs(
138140
const required = {};
139141
// Because objects have no guaranteed ordering, yet we need it,
140142
// we need to keep track of the order in a array
141-
const sources = [];
143+
const requiredSources = [];
144+
const dynamicRegisterSources = [];
142145

143146
let uid = 0;
144147

@@ -229,8 +232,7 @@ export function transformCommonjs(
229232
}
230233

231234
const existing = required[sourceId];
232-
// eslint-disable-next-line no-undefined
233-
if (existing === undefined) {
235+
if (!existing) {
234236
const isDynamic = hasDynamicModuleForPath(sourceId);
235237

236238
if (!name) {
@@ -240,12 +242,15 @@ export function transformCommonjs(
240242
} while (scope.contains(name));
241243
}
242244

243-
if (isDynamicRegister && sourceId.endsWith('.json')) {
244-
sourceId = DYNAMIC_JSON_PREFIX + sourceId;
245+
if (isDynamicRegister) {
246+
if (sourceId.endsWith('.json')) {
247+
sourceId = DYNAMIC_JSON_PREFIX + sourceId;
248+
}
249+
dynamicRegisterSources.push(sourceId);
245250
}
246251

247-
if (isDynamicRegister || !isDynamic || sourceId.endsWith('.json')) {
248-
sources.push([sourceId, isDynamicRegister]);
252+
if (!isDynamic || sourceId.endsWith('.json')) {
253+
requiredSources.push(sourceId);
249254
}
250255

251256
required[sourceId] = { source: sourceId, name, importsDefault: false, isDynamic };
@@ -553,7 +558,8 @@ export function transformCommonjs(
553558
usesCommonjsHelpers = usesCommonjsHelpers || shouldWrap;
554559

555560
if (
556-
!sources.length &&
561+
!requiredSources.length &&
562+
!dynamicRegisterSources.length &&
557563
!uses.module &&
558564
!uses.exports &&
559565
!uses.require &&
@@ -568,25 +574,22 @@ export function transformCommonjs(
568574
: []
569575
)
570576
.concat(
571-
// dynamic registers first (`commonjsRegister(,,,)`), as the may be required in the other modules
572-
sources
573-
.filter(([, isDynamicRegister]) => isDynamicRegister)
574-
.map(([source]) => `import '${source}';`),
575-
576-
// now the solid modules, non-commonjsRegister
577-
sources
578-
.filter(([, isDynamicRegister]) => !isDynamicRegister)
579-
.map(([source]) => `import '${source}';`),
580-
581-
// now the proxies for solid modules (non-commonjsRegister)
582-
sources
583-
.filter(([, isDynamicRegister]) => !isDynamicRegister)
584-
.map(([source]) => {
585-
const { name, importsDefault } = required[source];
586-
return `import ${importsDefault ? `${name} from ` : ``}'${
587-
source.startsWith('\0') ? source : getProxyId(source)
588-
}';`;
589-
})
577+
// dynamic registers first, as the may be required in the other modules
578+
dynamicRegisterSources.map((source) => `import '${source}';`),
579+
580+
// now the actual modules so that they are analyzed before creating the proxies;
581+
// no need to do this for virtual modules as we never proxy them
582+
requiredSources
583+
.filter((source) => !source.startsWith('\0'))
584+
.map((source) => `import '${wrapId(source, REQUIRE_SUFFIX)}';`),
585+
586+
// now the proxy modules
587+
requiredSources.map((source) => {
588+
const { name, importsDefault } = required[source];
589+
return `import ${importsDefault ? `${name} from ` : ``}'${
590+
source.startsWith('\0') ? source : wrapId(source, PROXY_SUFFIX)
591+
}';`;
592+
})
590593
)
591594
.join('\n')}\n\n`;
592595

packages/commonjs/test/fixtures/form/constant-template-literal/output.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import 'tape';
1+
import '_tape?commonjs-require';
22
import foo from '_tape?commonjs-proxy';
33

44
console.log(foo);

packages/commonjs/test/fixtures/form/ignore-ids-function/output.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import 'bar';
1+
import '_bar?commonjs-require';
22
import bar from '_bar?commonjs-proxy';
33

44
var foo = require( 'foo' );

packages/commonjs/test/fixtures/form/ignore-ids/output.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import 'bar';
1+
import '_bar?commonjs-require';
22
import bar from '_bar?commonjs-proxy';
33

44
var foo = require( 'foo' );

0 commit comments

Comments
 (0)