Skip to content

Commit 7434b0f

Browse files
committed
fix(commonjs): proxy all entries to not break legacy polyfill plugins (#1038)
1 parent 1424249 commit 7434b0f

File tree

23 files changed

+718
-167
lines changed

23 files changed

+718
-167
lines changed

packages/commonjs/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
"require"
5353
],
5454
"peerDependencies": {
55-
"rollup": "^2.61.1"
55+
"rollup": "^2.67.0"
5656
},
5757
"dependencies": {
5858
"@rollup/pluginutils": "^3.1.0",

packages/commonjs/src/generate-imports.js

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,12 @@ export function getRequireHandlers() {
9090
exportsName,
9191
id,
9292
exportMode,
93-
resolveRequireSourcesAndGetMeta,
93+
resolveRequireSourcesAndUpdateMeta,
9494
needsRequireWrapper,
9595
isEsModule,
9696
isDynamicRequireModulesEnabled,
97-
getIgnoreTryCatchRequireStatementMode
97+
getIgnoreTryCatchRequireStatementMode,
98+
commonjsMeta
9899
) {
99100
const imports = [];
100101
imports.push(`import * as ${helpersName} from "${HELPERS_ID}";`);
@@ -117,9 +118,10 @@ export function getRequireHandlers() {
117118
);
118119
}
119120
const requiresBySource = collectSources(requireExpressions);
120-
const { requireTargets, usesRequireWrapper } = await resolveRequireSourcesAndGetMeta(
121+
const requireTargets = await resolveRequireSourcesAndUpdateMeta(
121122
id,
122123
needsRequireWrapper ? IS_WRAPPED_COMMONJS : !isEsModule,
124+
commonjsMeta,
123125
Object.keys(requiresBySource).map((source) => {
124126
return {
125127
source,
@@ -134,10 +136,7 @@ export function getRequireHandlers() {
134136
getIgnoreTryCatchRequireStatementMode,
135137
magicString
136138
);
137-
return {
138-
importBlock: imports.length ? `${imports.join('\n')}\n\n` : '',
139-
usesRequireWrapper
140-
};
139+
return imports.length ? `${imports.join('\n')}\n\n` : '';
141140
}
142141

143142
return {

packages/commonjs/src/helpers.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ export const WRAPPED_SUFFIX = '?commonjs-wrapped';
77
export const EXTERNAL_SUFFIX = '?commonjs-external';
88
export const EXPORTS_SUFFIX = '?commonjs-exports';
99
export const MODULE_SUFFIX = '?commonjs-module';
10-
export const ES_IMPORT_SUFFIX = '?es-import';
10+
export const ENTRY_SUFFIX = '?commonjs-entry';
11+
export const ES_IMPORT_SUFFIX = '?commonjs-es-import';
1112

1213
export const DYNAMIC_MODULES_ID = '\0commonjs-dynamic-modules';
1314
export const HELPERS_ID = '\0commonjsHelpers.js';

packages/commonjs/src/index.js

Lines changed: 42 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { getDynamicModuleRegistry, getDynamicRequireModules } from './dynamic-mo
99

1010
import {
1111
DYNAMIC_MODULES_ID,
12+
ENTRY_SUFFIX,
1213
ES_IMPORT_SUFFIX,
1314
EXPORTS_SUFFIX,
1415
EXTERNAL_SUFFIX,
@@ -20,13 +21,20 @@ import {
2021
unwrapId
2122
} from './helpers';
2223
import { hasCjsKeywords } from './parse';
23-
import { getEsImportProxy, getStaticRequireProxy, getUnknownRequireProxy } from './proxies';
24+
import {
25+
getEntryProxy,
26+
getEsImportProxy,
27+
getStaticRequireProxy,
28+
getUnknownRequireProxy
29+
} from './proxies';
2430
import getResolveId from './resolve-id';
25-
import { getResolveRequireSourcesAndGetMeta } from './resolve-require-sources';
31+
import { getRequireResolver } from './resolve-require-sources';
2632
import validateVersion from './rollup-version';
2733
import transformCommonjs from './transform-commonjs';
2834
import { getName, getStrictRequiresFilter, normalizePathSlashes } from './utils';
2935

36+
const PLUGIN_NAME = 'commonjs';
37+
3038
export default function commonjs(options = {}) {
3139
const {
3240
ignoreGlobal,
@@ -58,11 +66,6 @@ export default function commonjs(options = {}) {
5866
: () =>
5967
typeof defaultIsModuleExportsOption === 'boolean' ? defaultIsModuleExportsOption : 'auto';
6068

61-
const {
62-
resolveRequireSourcesAndGetMeta,
63-
getWrappedIds,
64-
isRequiredId
65-
} = getResolveRequireSourcesAndGetMeta(extensions, detectCyclesAndConditional);
6669
const dynamicRequireRoot =
6770
typeof options.dynamicRequireRoot === 'string'
6871
? resolve(options.dynamicRequireRoot)
@@ -73,9 +76,6 @@ export default function commonjs(options = {}) {
7376
);
7477
const isDynamicRequireModulesEnabled = dynamicRequireModules.size > 0;
7578

76-
const esModulesWithDefaultExport = new Set();
77-
const esModulesWithNamedExports = new Set();
78-
7979
const ignoreRequire =
8080
typeof options.ignore === 'function'
8181
? options.ignore
@@ -103,25 +103,31 @@ export default function commonjs(options = {}) {
103103

104104
const sourceMap = options.sourceMap !== false;
105105

106+
// Initialized in buildStart
107+
let requireResolver;
108+
106109
function transformAndCheckExports(code, id) {
107110
const { isEsModule, hasDefaultExport, hasNamedExports, ast } = analyzeTopLevelStatements(
108111
this.parse,
109112
code,
110113
id
111114
);
115+
116+
const commonjsMeta = this.getModuleInfo(id).meta.commonjs || {};
112117
if (hasDefaultExport) {
113-
esModulesWithDefaultExport.add(id);
118+
commonjsMeta.hasDefaultExport = true;
114119
}
115120
if (hasNamedExports) {
116-
esModulesWithNamedExports.add(id);
121+
commonjsMeta.hasNamedExports = true;
117122
}
118123

119124
if (
120125
!dynamicRequireModules.has(normalizePathSlashes(id)) &&
121-
(!(hasCjsKeywords(code, ignoreGlobal) || isRequiredId(id)) ||
126+
(!(hasCjsKeywords(code, ignoreGlobal) || requireResolver.isRequiredId(id)) ||
122127
(isEsModule && !options.transformMixedEsModules))
123128
) {
124-
return { meta: { commonjs: { isCommonJS: false } } };
129+
commonjsMeta.isCommonJS = false;
130+
return { meta: { commonjs: commonjsMeta } };
125131
}
126132

127133
const needsRequireWrapper =
@@ -160,22 +166,23 @@ export default function commonjs(options = {}) {
160166
ast,
161167
getDefaultIsModuleExports(id),
162168
needsRequireWrapper,
163-
resolveRequireSourcesAndGetMeta(this),
164-
isRequiredId(id),
165-
checkDynamicRequire
169+
requireResolver.resolveRequireSourcesAndUpdateMeta(this),
170+
requireResolver.isRequiredId(id),
171+
checkDynamicRequire,
172+
commonjsMeta
166173
);
167174
}
168175

169176
return {
170-
name: 'commonjs',
177+
name: PLUGIN_NAME,
171178

172179
version,
173180

174181
options(rawOptions) {
175182
// We inject the resolver in the beginning so that "catch-all-resolver" like node-resolver
176183
// do not prevent our plugin from resolving entry points ot proxies.
177184
const plugins = Array.isArray(rawOptions.plugins)
178-
? rawOptions.plugins
185+
? [...rawOptions.plugins]
179186
: rawOptions.plugins
180187
? [rawOptions.plugins]
181188
: [];
@@ -197,11 +204,12 @@ export default function commonjs(options = {}) {
197204
'The namedExports option from "@rollup/plugin-commonjs" is deprecated. Named exports are now handled automatically.'
198205
);
199206
}
207+
requireResolver = getRequireResolver(extensions, detectCyclesAndConditional);
200208
},
201209

202210
buildEnd() {
203211
if (options.strictRequires === 'debug') {
204-
const wrappedIds = getWrappedIds();
212+
const wrappedIds = requireResolver.getWrappedIds();
205213
if (wrappedIds.length) {
206214
this.warn({
207215
code: 'WRAPPED_IDS',
@@ -250,6 +258,15 @@ export default function commonjs(options = {}) {
250258
);
251259
}
252260

261+
// entry suffix is just appended to not mess up relative external resolution
262+
if (id.endsWith(ENTRY_SUFFIX)) {
263+
return getEntryProxy(
264+
id.slice(0, -ENTRY_SUFFIX.length),
265+
defaultIsModuleExports,
266+
this.getModuleInfo
267+
);
268+
}
269+
253270
if (isWrappedId(id, ES_IMPORT_SUFFIX)) {
254271
return getEsImportProxy(unwrapId(id, ES_IMPORT_SUFFIX), defaultIsModuleExports);
255272
}
@@ -265,18 +282,16 @@ export default function commonjs(options = {}) {
265282

266283
if (isWrappedId(id, PROXY_SUFFIX)) {
267284
const actualId = unwrapId(id, PROXY_SUFFIX);
268-
return getStaticRequireProxy(
269-
actualId,
270-
getRequireReturnsDefault(actualId),
271-
esModulesWithDefaultExport,
272-
esModulesWithNamedExports,
273-
this.load
274-
);
285+
return getStaticRequireProxy(actualId, getRequireReturnsDefault(actualId), this.load);
275286
}
276287

277288
return null;
278289
},
279290

291+
shouldTransformCachedModule(...args) {
292+
return requireResolver.shouldTransformCachedModule.call(this, ...args);
293+
},
294+
280295
transform(code, id) {
281296
const extName = extname(id);
282297
if (extName !== '.cjs' && (!filter(id) || !extensions.includes(extName))) {

packages/commonjs/src/proxies.js

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { HELPERS_ID } from './helpers';
1+
import { HELPERS_ID, IS_WRAPPED_COMMONJS } from './helpers';
22
import { capitalize, getName } from './utils';
33

44
export function getUnknownRequireProxy(id, requireReturnsDefault) {
@@ -17,36 +17,46 @@ export function getUnknownRequireProxy(id, requireReturnsDefault) {
1717
return `import * as ${name} from ${JSON.stringify(id)}; ${exported}`;
1818
}
1919

20-
export async function getStaticRequireProxy(
21-
id,
22-
requireReturnsDefault,
23-
esModulesWithDefaultExport,
24-
esModulesWithNamedExports,
25-
loadModule
26-
) {
20+
export async function getStaticRequireProxy(id, requireReturnsDefault, loadModule) {
2721
const name = getName(id);
2822
const {
2923
meta: { commonjs: commonjsMeta }
3024
} = await loadModule({ id });
31-
if (commonjsMeta && commonjsMeta.isCommonJS) {
32-
return `export { __moduleExports as default } from ${JSON.stringify(id)};`;
33-
} else if (!commonjsMeta) {
25+
if (!commonjsMeta) {
3426
return getUnknownRequireProxy(id, requireReturnsDefault);
27+
} else if (commonjsMeta.isCommonJS) {
28+
return `export { __moduleExports as default } from ${JSON.stringify(id)};`;
3529
} else if (!requireReturnsDefault) {
3630
return `import { getAugmentedNamespace } from "${HELPERS_ID}"; import * as ${name} from ${JSON.stringify(
3731
id
3832
)}; export default /*@__PURE__*/getAugmentedNamespace(${name});`;
3933
} else if (
4034
requireReturnsDefault !== true &&
4135
(requireReturnsDefault === 'namespace' ||
42-
!esModulesWithDefaultExport.has(id) ||
43-
(requireReturnsDefault === 'auto' && esModulesWithNamedExports.has(id)))
36+
!commonjsMeta.hasDefaultExport ||
37+
(requireReturnsDefault === 'auto' && commonjsMeta.hasNamedExports))
4438
) {
4539
return `import * as ${name} from ${JSON.stringify(id)}; export default ${name};`;
4640
}
4741
return `export { default } from ${JSON.stringify(id)};`;
4842
}
4943

44+
export function getEntryProxy(id, defaultIsModuleExports, getModuleInfo) {
45+
const {
46+
meta: { commonjs: commonjsMeta },
47+
hasDefaultExport
48+
} = getModuleInfo(id);
49+
if (!commonjsMeta || commonjsMeta.isCommonJS !== IS_WRAPPED_COMMONJS) {
50+
const stringifiedId = JSON.stringify(id);
51+
let code = `export * from ${stringifiedId};`;
52+
if (hasDefaultExport) {
53+
code += `export { default } from ${stringifiedId};`;
54+
}
55+
return code;
56+
}
57+
return getEsImportProxy(id, defaultIsModuleExports);
58+
}
59+
5060
export function getEsImportProxy(id, defaultIsModuleExports) {
5161
const name = getName(id);
5262
const exportsName = `${name}Exports`;

packages/commonjs/src/resolve-id.js

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { dirname, resolve, sep } from 'path';
55

66
import {
77
DYNAMIC_MODULES_ID,
8+
ENTRY_SUFFIX,
89
ES_IMPORT_SUFFIX,
910
EXPORTS_SUFFIX,
1011
EXTERNAL_SUFFIX,
@@ -51,18 +52,16 @@ export function resolveExtensions(importee, importer, extensions) {
5152
export default function getResolveId(extensions) {
5253
return async function resolveId(importee, importer, resolveOptions) {
5354
// We assume that all requires are pre-resolved
54-
if (
55-
resolveOptions.custom &&
56-
resolveOptions.custom['node-resolve'] &&
57-
resolveOptions.custom['node-resolve'].isRequire
58-
) {
55+
const customOptions = resolveOptions.custom;
56+
if (customOptions && customOptions['node-resolve'] && customOptions['node-resolve'].isRequire) {
5957
return null;
6058
}
6159
if (isWrappedId(importee, WRAPPED_SUFFIX)) {
6260
return unwrapId(importee, WRAPPED_SUFFIX);
6361
}
6462

6563
if (
64+
importee.endsWith(ENTRY_SUFFIX) ||
6665
isWrappedId(importee, MODULE_SUFFIX) ||
6766
isWrappedId(importee, EXPORTS_SUFFIX) ||
6867
isWrappedId(importee, PROXY_SUFFIX) ||
@@ -79,7 +78,8 @@ export default function getResolveId(extensions) {
7978
importer === DYNAMIC_MODULES_ID ||
8079
// Proxies are only importing resolved ids, no need to resolve again
8180
isWrappedId(importer, PROXY_SUFFIX) ||
82-
isWrappedId(importer, ES_IMPORT_SUFFIX)
81+
isWrappedId(importer, ES_IMPORT_SUFFIX) ||
82+
importer.endsWith(ENTRY_SUFFIX)
8383
) {
8484
return importee;
8585
}
@@ -99,22 +99,27 @@ export default function getResolveId(extensions) {
9999

100100
// If this is an entry point or ESM import, we need to figure out if the importee is wrapped and
101101
// if that is the case, we need to add a proxy.
102-
const customOptions = resolveOptions.custom;
103-
104-
// If this is a require, we do not need a proxy
105-
if (customOptions && customOptions['node-resolve'] && customOptions['node-resolve'].isRequire) {
106-
return null;
107-
}
108-
109102
const resolved =
110103
(await this.resolve(importee, importer, Object.assign({ skipSelf: true }, resolveOptions))) ||
111104
resolveExtensions(importee, importer, extensions);
112-
if (!resolved || resolved.external) {
105+
// Make sure that even if other plugins resolve again, we ignore our own proxies
106+
if (
107+
!resolved ||
108+
resolved.external ||
109+
resolved.id.endsWith(ENTRY_SUFFIX) ||
110+
isWrappedId(resolved.id, ES_IMPORT_SUFFIX)
111+
) {
113112
return resolved;
114113
}
114+
const moduleInfo = await this.load(resolved);
115+
if (resolveOptions.isEntry) {
116+
moduleInfo.moduleSideEffects = true;
117+
// We must not precede entry proxies with a `\0` as that will mess up relative external resolution
118+
return resolved.id + ENTRY_SUFFIX;
119+
}
115120
const {
116121
meta: { commonjs: commonjsMeta }
117-
} = await this.load(resolved);
122+
} = moduleInfo;
118123
if (commonjsMeta && commonjsMeta.isCommonJS === IS_WRAPPED_COMMONJS) {
119124
return wrapId(resolved.id, ES_IMPORT_SUFFIX);
120125
}

0 commit comments

Comments
 (0)