Skip to content

Commit 71cf7f4

Browse files
committed
add support for reexporting in CommonJS
and necessary refactoring + fixes for that
1 parent 0090eb9 commit 71cf7f4

25 files changed

+938
-243
lines changed

lib/ContextModule.js

+1
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,7 @@ class ContextModule extends Module {
490490
const fakeMap = Object.create(null);
491491
for (const module of sortedModules) {
492492
const exportsType = module.getExportsType(
493+
moduleGraph,
493494
this.options.namespaceObject === "strict"
494495
);
495496
const id = chunkGraph.getModuleId(module);

lib/ExportsInfo.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -425,9 +425,6 @@ class ExportsInfo {
425425
return true;
426426
}
427427
}
428-
if (this._sideEffectsOnlyInfo.getUsed(runtime) !== UsageState.Unused) {
429-
return true;
430-
}
431428
for (const exportInfo of this._exports.values()) {
432429
if (exportInfo.getUsed(runtime) !== UsageState.Unused) {
433430
return true;
@@ -641,7 +638,10 @@ class ExportsInfo {
641638
getUsedName(name, runtime) {
642639
if (Array.isArray(name)) {
643640
// TODO improve this
644-
if (name.length === 0) return name;
641+
if (name.length === 0) {
642+
if (!this.isUsed(runtime)) return false;
643+
return name;
644+
}
645645
let info = this.getReadOnlyExportInfo(name[0]);
646646
const x = info.getUsedName(name[0], runtime);
647647
if (x === false) return false;

lib/Module.js

+45-2
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ const makeSerializable = require("./util/makeSerializable");
7171
* @property {string=} exportsArgument
7272
* @property {boolean=} strict
7373
* @property {string=} moduleConcatenationBailout
74-
* @property {("default" | "namespace" | "flagged")=} exportsType
74+
* @property {("default" | "namespace" | "flagged" | "dynamic")=} exportsType
7575
* @property {(false | "redirect" | "redirect-warn")=} defaultObject
7676
* @property {boolean=} strictHarmonyModule
7777
* @property {boolean=} async
@@ -263,6 +263,10 @@ class Module extends DependenciesBlock {
263263
).getUsedExports(this, undefined);
264264
}
265265

266+
/**
267+
* @deprecated
268+
* @returns {(string | OptimizationBailoutFunction)[]} list
269+
*/
266270
get optimizationBailout() {
267271
return ModuleGraph.getModuleGraphForModule(
268272
this,
@@ -372,14 +376,15 @@ class Module extends DependenciesBlock {
372376
}
373377

374378
/**
379+
* @param {ModuleGraph} moduleGraph the module graph
375380
* @param {boolean} strict the importing module is strict
376381
* @returns {"namespace" | "default-only" | "default-with-named" | "dynamic"} export type
377382
* "namespace": Exports is already a namespace object. namespace = exports.
378383
* "dynamic": Check at runtime if __esModule is set. When set: namespace = { ...exports, default: exports }. When not set: namespace = { default: exports }.
379384
* "default-only": Provide a namespace object with only default export. namespace = { default: exports }
380385
* "default-with-named": Provide a namespace object with named and default export. namespace = { ...exports, default: exports }
381386
*/
382-
getExportsType(strict) {
387+
getExportsType(moduleGraph, strict) {
383388
switch (this.buildMeta && this.buildMeta.exportsType) {
384389
case "flagged":
385390
return strict ? "default-only" : "namespace";
@@ -393,6 +398,44 @@ class Module extends DependenciesBlock {
393398
default:
394399
return "default-only";
395400
}
401+
case "dynamic": {
402+
if (strict) return "default-only";
403+
// Try to figure out value of __esModule by following reexports
404+
const handleDefault = () => {
405+
switch (this.buildMeta.defaultObject) {
406+
case "redirect":
407+
case "redirect-warn":
408+
return "default-with-named";
409+
default:
410+
return "default-only";
411+
}
412+
};
413+
const exportInfo = moduleGraph.getExportInfo(this, "__esModule");
414+
if (exportInfo.provided === false) {
415+
return handleDefault();
416+
}
417+
const target = exportInfo.getTarget(moduleGraph);
418+
if (
419+
!target ||
420+
!target.export ||
421+
target.export.length !== 1 ||
422+
target.export[0] !== "__esModule"
423+
) {
424+
return "dynamic";
425+
}
426+
switch (
427+
target.module.buildMeta &&
428+
target.module.buildMeta.exportsType
429+
) {
430+
case "flagged":
431+
case "namespace":
432+
return "namespace";
433+
case "default":
434+
return handleDefault();
435+
default:
436+
return "dynamic";
437+
}
438+
}
396439
default:
397440
return strict ? "default-only" : "dynamic";
398441
}

lib/RuntimeGlobals.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ exports.exports = "__webpack_exports__";
2626
exports.thisAsExports = "top-level-this-exports";
2727

2828
/**
29-
* top-level this need to be the exports object
29+
* runtime need to return the exports of the last entry module
3030
*/
3131
exports.returnExportsFromRuntime = "return-exports-from-runtime";
3232

lib/RuntimeTemplate.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ class RuntimeTemplate {
357357
request,
358358
weak
359359
});
360-
const exportsType = module.getExportsType(strict);
360+
const exportsType = module.getExportsType(chunkGraph.moduleGraph, strict);
361361
switch (exportsType) {
362362
case "namespace":
363363
return this.moduleRaw({
@@ -461,7 +461,7 @@ class RuntimeTemplate {
461461
request,
462462
weak
463463
});
464-
const exportsType = module.getExportsType(strict);
464+
const exportsType = module.getExportsType(chunkGraph.moduleGraph, strict);
465465
let fakeType = 0;
466466
switch (exportsType) {
467467
case "namespace":
@@ -590,6 +590,7 @@ class RuntimeTemplate {
590590
const optDeclaration = update ? "" : "var ";
591591

592592
const exportsType = module.getExportsType(
593+
chunkGraph.moduleGraph,
593594
originModule.buildMeta.strictHarmonyModule
594595
);
595596
runtimeRequirements.add(RuntimeGlobals.require);
@@ -646,6 +647,7 @@ class RuntimeTemplate {
646647
exportName = exportName ? [exportName] : [];
647648
}
648649
const exportsType = module.getExportsType(
650+
moduleGraph,
649651
originModule.buildMeta.strictHarmonyModule
650652
);
651653

lib/config/defaults.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -680,7 +680,13 @@ const applyOptimizationDefaults = (
680680
apply: compiler => {
681681
// Lazy load the Terser plugin
682682
const TerserPlugin = require("terser-webpack-plugin");
683-
new TerserPlugin().apply(compiler);
683+
new TerserPlugin({
684+
terserOptions: {
685+
compress: {
686+
passes: 2
687+
}
688+
}
689+
}).apply(compiler);
684690
}
685691
}
686692
]);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
MIT License http://www.opensource.org/licenses/mit-license.php
3+
Author Tobias Koppers @sokra
4+
*/
5+
6+
"use strict";
7+
8+
const RuntimeGlobals = require("../RuntimeGlobals");
9+
10+
exports.handleDependencyBase = (depBase, module, runtimeRequirements) => {
11+
let base = undefined;
12+
let type;
13+
switch (depBase) {
14+
case "exports":
15+
runtimeRequirements.add(RuntimeGlobals.exports);
16+
base = module.exportsArgument;
17+
type = "expression";
18+
break;
19+
case "module.exports":
20+
runtimeRequirements.add(RuntimeGlobals.module);
21+
base = `${module.moduleArgument}.exports`;
22+
type = "expression";
23+
break;
24+
case "this":
25+
runtimeRequirements.add(RuntimeGlobals.thisAsExports);
26+
base = "this";
27+
type = "expression";
28+
break;
29+
case "Object.defineProperty(exports)":
30+
runtimeRequirements.add(RuntimeGlobals.exports);
31+
base = module.exportsArgument;
32+
type = "Object.defineProperty";
33+
break;
34+
case "Object.defineProperty(module.exports)":
35+
runtimeRequirements.add(RuntimeGlobals.module);
36+
base = `${module.moduleArgument}.exports`;
37+
type = "Object.defineProperty";
38+
break;
39+
case "Object.defineProperty(this)":
40+
runtimeRequirements.add(RuntimeGlobals.thisAsExports);
41+
base = "this";
42+
type = "Object.defineProperty";
43+
break;
44+
default:
45+
throw new Error(`Unsupported base ${depBase}`);
46+
}
47+
48+
return [type, base];
49+
};

0 commit comments

Comments
 (0)