webpack 5.54.0 → 5.56.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of webpack might be problematic. Click here for more details.
- package/lib/Compilation.js +430 -178
- package/lib/Compiler.js +6 -5
- package/lib/DefinePlugin.js +14 -9
- package/lib/Dependency.js +11 -0
- package/lib/FlagDependencyExportsPlugin.js +9 -27
- package/lib/ModuleFactory.js +1 -0
- package/lib/ModuleGraph.js +90 -21
- package/lib/NormalModuleFactory.js +8 -43
- package/lib/dependencies/CommonJsExportRequireDependency.js +19 -9
- package/lib/dependencies/CommonJsFullRequireDependency.js +11 -9
- package/lib/dependencies/ContextDependency.js +8 -0
- package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +179 -163
- package/lib/dependencies/HarmonyImportDependency.js +4 -1
- package/lib/dependencies/ModuleDependency.js +8 -0
- package/lib/dependencies/NullDependency.js +8 -4
- package/lib/dependencies/WebAssemblyExportImportedDependency.js +9 -0
- package/lib/util/WeakTupleMap.js +95 -92
- package/package.json +1 -1
- package/types.d.ts +56 -18
- package/lib/MemCache.js +0 -45
package/lib/Compilation.js
CHANGED
@@ -25,6 +25,7 @@ const ChunkRenderError = require("./ChunkRenderError");
|
|
25
25
|
const ChunkTemplate = require("./ChunkTemplate");
|
26
26
|
const CodeGenerationError = require("./CodeGenerationError");
|
27
27
|
const CodeGenerationResults = require("./CodeGenerationResults");
|
28
|
+
const Dependency = require("./Dependency");
|
28
29
|
const DependencyTemplates = require("./DependencyTemplates");
|
29
30
|
const Entrypoint = require("./Entrypoint");
|
30
31
|
const ErrorHelpers = require("./ErrorHelpers");
|
@@ -38,7 +39,6 @@ const {
|
|
38
39
|
tryRunOrWebpackError
|
39
40
|
} = require("./HookWebpackError");
|
40
41
|
const MainTemplate = require("./MainTemplate");
|
41
|
-
const MemCache = require("./MemCache");
|
42
42
|
const Module = require("./Module");
|
43
43
|
const ModuleDependencyError = require("./ModuleDependencyError");
|
44
44
|
const ModuleDependencyWarning = require("./ModuleDependencyWarning");
|
@@ -61,6 +61,7 @@ const { equals: arrayEquals } = require("./util/ArrayHelpers");
|
|
61
61
|
const AsyncQueue = require("./util/AsyncQueue");
|
62
62
|
const LazySet = require("./util/LazySet");
|
63
63
|
const { provide } = require("./util/MapHelpers");
|
64
|
+
const WeakTupleMap = require("./util/WeakTupleMap");
|
64
65
|
const { cachedCleverMerge } = require("./util/cleverMerge");
|
65
66
|
const {
|
66
67
|
compareLocations,
|
@@ -77,7 +78,7 @@ const {
|
|
77
78
|
createFakeHook
|
78
79
|
} = require("./util/deprecation");
|
79
80
|
const processAsyncTree = require("./util/processAsyncTree");
|
80
|
-
const { getRuntimeKey
|
81
|
+
const { getRuntimeKey } = require("./util/runtime");
|
81
82
|
const { isSourceEqual } = require("./util/source");
|
82
83
|
|
83
84
|
/** @template T @typedef {import("tapable").AsArray<T>} AsArray<T> */
|
@@ -92,8 +93,8 @@ const { isSourceEqual } = require("./util/source");
|
|
92
93
|
/** @typedef {import("./CacheFacade")} CacheFacade */
|
93
94
|
/** @typedef {import("./ChunkGroup").ChunkGroupOptions} ChunkGroupOptions */
|
94
95
|
/** @typedef {import("./Compiler")} Compiler */
|
96
|
+
/** @typedef {import("./Compiler").CompilationParams} CompilationParams */
|
95
97
|
/** @typedef {import("./DependenciesBlock")} DependenciesBlock */
|
96
|
-
/** @typedef {import("./Dependency")} Dependency */
|
97
98
|
/** @typedef {import("./Dependency").DependencyLocation} DependencyLocation */
|
98
99
|
/** @typedef {import("./Dependency").ReferencedExport} ReferencedExport */
|
99
100
|
/** @typedef {import("./DependencyTemplate")} DependencyTemplate */
|
@@ -101,6 +102,7 @@ const { isSourceEqual } = require("./util/source");
|
|
101
102
|
/** @typedef {import("./Module").CodeGenerationResult} CodeGenerationResult */
|
102
103
|
/** @typedef {import("./ModuleFactory")} ModuleFactory */
|
103
104
|
/** @typedef {import("./ModuleFactory").ModuleFactoryCreateDataContextInfo} ModuleFactoryCreateDataContextInfo */
|
105
|
+
/** @typedef {import("./ModuleFactory").ModuleFactoryResult} ModuleFactoryResult */
|
104
106
|
/** @typedef {import("./RequestShortener")} RequestShortener */
|
105
107
|
/** @typedef {import("./RuntimeModule")} RuntimeModule */
|
106
108
|
/** @typedef {import("./Template").RenderManifestEntry} RenderManifestEntry */
|
@@ -125,6 +127,20 @@ const { isSourceEqual } = require("./util/source");
|
|
125
127
|
* @returns {void}
|
126
128
|
*/
|
127
129
|
|
130
|
+
/**
|
131
|
+
* @callback ModuleFactoryResultCallback
|
132
|
+
* @param {WebpackError=} err
|
133
|
+
* @param {ModuleFactoryResult=} result
|
134
|
+
* @returns {void}
|
135
|
+
*/
|
136
|
+
|
137
|
+
/**
|
138
|
+
* @callback ModuleOrFactoryResultCallback
|
139
|
+
* @param {WebpackError=} err
|
140
|
+
* @param {Module | ModuleFactoryResult=} result
|
141
|
+
* @returns {void}
|
142
|
+
*/
|
143
|
+
|
128
144
|
/**
|
129
145
|
* @callback ExecuteModuleCallback
|
130
146
|
* @param {WebpackError=} err
|
@@ -400,12 +416,19 @@ const byLocation = compareSelect(err => err.loc, compareLocations);
|
|
400
416
|
|
401
417
|
const compareErrors = concatComparators(byModule, byLocation, byMessage);
|
402
418
|
|
419
|
+
/** @type {WeakMap<Dependency, Module & { restoreFromUnsafeCache: Function }>} */
|
420
|
+
const unsafeCacheDependencies = new WeakMap();
|
421
|
+
|
422
|
+
/** @type {WeakMap<Module, object>} */
|
423
|
+
const unsafeCacheData = new WeakMap();
|
424
|
+
|
403
425
|
class Compilation {
|
404
426
|
/**
|
405
427
|
* Creates an instance of Compilation.
|
406
428
|
* @param {Compiler} compiler the compiler which created the compilation
|
429
|
+
* @param {CompilationParams} params the compilation parameters
|
407
430
|
*/
|
408
|
-
constructor(compiler) {
|
431
|
+
constructor(compiler, params) {
|
409
432
|
const getNormalModuleLoader = () => deprecatedNormalModuleLoaderHook(this);
|
410
433
|
/** @typedef {{ additionalAssets?: true | Function }} ProcessAssetsAdditionalOptions */
|
411
434
|
/** @type {AsyncSeriesHook<[CompilationAssets], ProcessAssetsAdditionalOptions>} */
|
@@ -880,6 +903,7 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
|
|
880
903
|
/** @type {boolean} */
|
881
904
|
this.profile = (options && options.profile) || false;
|
882
905
|
|
906
|
+
this.params = params;
|
883
907
|
this.mainTemplate = new MainTemplate(this.outputOptions, this);
|
884
908
|
this.chunkTemplate = new ChunkTemplate(this.outputOptions, this);
|
885
909
|
this.runtimeTemplate = new RuntimeTemplate(
|
@@ -893,9 +917,7 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
|
|
893
917
|
};
|
894
918
|
defineRemovedModuleTemplates(this.moduleTemplates);
|
895
919
|
|
896
|
-
/** @type {
|
897
|
-
this.memCache = undefined;
|
898
|
-
/** @type {WeakMap<Module, MemCache> | undefined} */
|
920
|
+
/** @type {WeakMap<Module, WeakTupleMap<any, any>> | undefined} */
|
899
921
|
this.moduleMemCaches = undefined;
|
900
922
|
this.moduleGraph = new ModuleGraph();
|
901
923
|
/** @type {ChunkGraph} */
|
@@ -916,7 +938,7 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
|
|
916
938
|
getKey: module => module.identifier(),
|
917
939
|
processor: this._addModule.bind(this)
|
918
940
|
});
|
919
|
-
/** @type {AsyncQueue<FactorizeModuleOptions, string, Module>} */
|
941
|
+
/** @type {AsyncQueue<FactorizeModuleOptions, string, Module | ModuleFactoryResult>} */
|
920
942
|
this.factorizeQueue = new AsyncQueue({
|
921
943
|
name: "factorize",
|
922
944
|
parent: this.addModuleQueue,
|
@@ -999,6 +1021,8 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
|
|
999
1021
|
this.usedModuleIds = null;
|
1000
1022
|
/** @type {boolean} */
|
1001
1023
|
this.needAdditionalPass = false;
|
1024
|
+
/** @type {Set<Module>} */
|
1025
|
+
this._restoredUnsafeCacheEntries = new Set();
|
1002
1026
|
/** @type {WeakSet<Module>} */
|
1003
1027
|
this.builtModules = new WeakSet();
|
1004
1028
|
/** @type {WeakSet<Module>} */
|
@@ -1031,6 +1055,11 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
|
|
1031
1055
|
this._modulesCache = this.getCache("Compilation/modules");
|
1032
1056
|
this._assetsCache = this.getCache("Compilation/assets");
|
1033
1057
|
this._codeGenerationCache = this.getCache("Compilation/codeGeneration");
|
1058
|
+
|
1059
|
+
const unsafeCache = options.module.unsafeCache;
|
1060
|
+
this._unsafeCache = !!unsafeCache;
|
1061
|
+
this._unsafeCachePredicate =
|
1062
|
+
typeof unsafeCache === "function" ? unsafeCache : () => true;
|
1034
1063
|
}
|
1035
1064
|
|
1036
1065
|
getStats() {
|
@@ -1415,12 +1444,44 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
|
|
1415
1444
|
/** @type {Dependency[]} */
|
1416
1445
|
let listCacheValue;
|
1417
1446
|
|
1447
|
+
const unsafeRestoredModules = new Set();
|
1448
|
+
|
1418
1449
|
/**
|
1419
1450
|
* @param {Dependency} dep dependency
|
1420
1451
|
* @returns {void}
|
1421
1452
|
*/
|
1422
1453
|
const processDependency = dep => {
|
1423
1454
|
this.moduleGraph.setParents(dep, currentBlock, module);
|
1455
|
+
if (this._unsafeCache) {
|
1456
|
+
try {
|
1457
|
+
const cachedModule = unsafeCacheDependencies.get(dep);
|
1458
|
+
if (cachedModule === null) return;
|
1459
|
+
if (cachedModule !== undefined) {
|
1460
|
+
if (!this._restoredUnsafeCacheEntries.has(cachedModule)) {
|
1461
|
+
const data = unsafeCacheData.get(cachedModule);
|
1462
|
+
cachedModule.restoreFromUnsafeCache(
|
1463
|
+
data,
|
1464
|
+
this.params.normalModuleFactory,
|
1465
|
+
this.params
|
1466
|
+
);
|
1467
|
+
this._restoredUnsafeCacheEntries.add(cachedModule);
|
1468
|
+
if (!this.modules.has(cachedModule)) {
|
1469
|
+
this._handleNewModuleFromUnsafeCache(module, dep, cachedModule);
|
1470
|
+
unsafeRestoredModules.add(cachedModule);
|
1471
|
+
return;
|
1472
|
+
}
|
1473
|
+
}
|
1474
|
+
this._handleExistingModuleFromUnsafeCache(
|
1475
|
+
module,
|
1476
|
+
dep,
|
1477
|
+
cachedModule
|
1478
|
+
);
|
1479
|
+
return;
|
1480
|
+
}
|
1481
|
+
} catch (e) {
|
1482
|
+
console.error(e);
|
1483
|
+
}
|
1484
|
+
}
|
1424
1485
|
const resourceIdent = dep.getResourceIdentifier();
|
1425
1486
|
if (resourceIdent !== undefined && resourceIdent !== null) {
|
1426
1487
|
const category = dep.category;
|
@@ -1504,7 +1565,7 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
|
|
1504
1565
|
return callback(e);
|
1505
1566
|
}
|
1506
1567
|
|
1507
|
-
if (sortedDependencies.length === 0) {
|
1568
|
+
if (sortedDependencies.length === 0 && unsafeRestoredModules.size === 0) {
|
1508
1569
|
callback();
|
1509
1570
|
return;
|
1510
1571
|
}
|
@@ -1512,27 +1573,78 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
|
|
1512
1573
|
// This is nested so we need to allow one additional task
|
1513
1574
|
this.processDependenciesQueue.increaseParallelism();
|
1514
1575
|
|
1515
|
-
|
1516
|
-
|
1517
|
-
|
1518
|
-
|
1519
|
-
|
1520
|
-
|
1521
|
-
//
|
1522
|
-
|
1523
|
-
|
1524
|
-
|
1525
|
-
|
1526
|
-
|
1527
|
-
|
1528
|
-
});
|
1529
|
-
},
|
1530
|
-
err => {
|
1531
|
-
this.processDependenciesQueue.decreaseParallelism();
|
1576
|
+
const processSortedDependency = (item, callback) => {
|
1577
|
+
this.handleModuleCreation(item, err => {
|
1578
|
+
// In V8, the Error objects keep a reference to the functions on the stack. These warnings &
|
1579
|
+
// errors are created inside closures that keep a reference to the Compilation, so errors are
|
1580
|
+
// leaking the Compilation object.
|
1581
|
+
if (err && this.bail) {
|
1582
|
+
// eslint-disable-next-line no-self-assign
|
1583
|
+
err.stack = err.stack;
|
1584
|
+
return callback(err);
|
1585
|
+
}
|
1586
|
+
callback();
|
1587
|
+
});
|
1588
|
+
};
|
1532
1589
|
|
1533
|
-
|
1534
|
-
|
1590
|
+
const processUnsafeRestoredModule = (item, callback) => {
|
1591
|
+
this._handleModuleBuildAndDependencies(module, item, true, callback);
|
1592
|
+
};
|
1593
|
+
|
1594
|
+
const finalCallback = err => {
|
1595
|
+
this.processDependenciesQueue.decreaseParallelism();
|
1596
|
+
|
1597
|
+
return callback(err);
|
1598
|
+
};
|
1599
|
+
|
1600
|
+
if (sortedDependencies.length === 0) {
|
1601
|
+
asyncLib.forEach(
|
1602
|
+
unsafeRestoredModules,
|
1603
|
+
processUnsafeRestoredModule,
|
1604
|
+
finalCallback
|
1605
|
+
);
|
1606
|
+
} else if (unsafeRestoredModules.size === 0) {
|
1607
|
+
asyncLib.forEach(
|
1608
|
+
sortedDependencies,
|
1609
|
+
processSortedDependency,
|
1610
|
+
finalCallback
|
1611
|
+
);
|
1612
|
+
} else {
|
1613
|
+
asyncLib.parallel(
|
1614
|
+
[
|
1615
|
+
cb =>
|
1616
|
+
asyncLib.forEach(
|
1617
|
+
unsafeRestoredModules,
|
1618
|
+
processUnsafeRestoredModule,
|
1619
|
+
cb
|
1620
|
+
),
|
1621
|
+
cb =>
|
1622
|
+
asyncLib.forEach(sortedDependencies, processSortedDependency, cb)
|
1623
|
+
],
|
1624
|
+
finalCallback
|
1625
|
+
);
|
1626
|
+
}
|
1627
|
+
}
|
1628
|
+
|
1629
|
+
_handleNewModuleFromUnsafeCache(originModule, dependency, module) {
|
1630
|
+
const moduleGraph = this.moduleGraph;
|
1631
|
+
|
1632
|
+
moduleGraph.setResolvedModule(originModule, dependency, module);
|
1633
|
+
|
1634
|
+
moduleGraph.setIssuerIfUnset(
|
1635
|
+
module,
|
1636
|
+
originModule !== undefined ? originModule : null
|
1535
1637
|
);
|
1638
|
+
|
1639
|
+
this._modules.set(module.identifier(), module);
|
1640
|
+
this.modules.add(module);
|
1641
|
+
ModuleGraph.setModuleGraphForModule(module, this.moduleGraph);
|
1642
|
+
}
|
1643
|
+
|
1644
|
+
_handleExistingModuleFromUnsafeCache(originModule, dependency, module) {
|
1645
|
+
const moduleGraph = this.moduleGraph;
|
1646
|
+
|
1647
|
+
moduleGraph.setResolvedModule(originModule, dependency, module);
|
1536
1648
|
}
|
1537
1649
|
|
1538
1650
|
/**
|
@@ -1572,12 +1684,27 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
|
|
1572
1684
|
currentProfile,
|
1573
1685
|
factory,
|
1574
1686
|
dependencies,
|
1687
|
+
factoryResult: true,
|
1575
1688
|
originModule,
|
1576
1689
|
contextInfo,
|
1577
1690
|
context
|
1578
1691
|
},
|
1579
|
-
(err,
|
1692
|
+
(err, factoryResult) => {
|
1693
|
+
const applyFactoryResultDependencies = () => {
|
1694
|
+
const { fileDependencies, contextDependencies, missingDependencies } =
|
1695
|
+
factoryResult;
|
1696
|
+
if (fileDependencies) {
|
1697
|
+
this.fileDependencies.addAll(fileDependencies);
|
1698
|
+
}
|
1699
|
+
if (contextDependencies) {
|
1700
|
+
this.contextDependencies.addAll(contextDependencies);
|
1701
|
+
}
|
1702
|
+
if (missingDependencies) {
|
1703
|
+
this.missingDependencies.addAll(missingDependencies);
|
1704
|
+
}
|
1705
|
+
};
|
1580
1706
|
if (err) {
|
1707
|
+
if (factoryResult) applyFactoryResultDependencies();
|
1581
1708
|
if (dependencies.every(d => d.optional)) {
|
1582
1709
|
this.warnings.push(err);
|
1583
1710
|
return callback();
|
@@ -1587,7 +1714,10 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
|
|
1587
1714
|
}
|
1588
1715
|
}
|
1589
1716
|
|
1717
|
+
const newModule = factoryResult.module;
|
1718
|
+
|
1590
1719
|
if (!newModule) {
|
1720
|
+
applyFactoryResultDependencies();
|
1591
1721
|
return callback();
|
1592
1722
|
}
|
1593
1723
|
|
@@ -1597,6 +1727,7 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
|
|
1597
1727
|
|
1598
1728
|
this.addModule(newModule, (err, module) => {
|
1599
1729
|
if (err) {
|
1730
|
+
applyFactoryResultDependencies();
|
1600
1731
|
if (!err.module) {
|
1601
1732
|
err.module = module;
|
1602
1733
|
}
|
@@ -1605,13 +1736,37 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
|
|
1605
1736
|
return callback(err);
|
1606
1737
|
}
|
1607
1738
|
|
1608
|
-
|
1609
|
-
|
1610
|
-
|
1611
|
-
|
1612
|
-
|
1613
|
-
|
1614
|
-
)
|
1739
|
+
if (
|
1740
|
+
this._unsafeCache &&
|
1741
|
+
factoryResult.cacheable !== false &&
|
1742
|
+
/** @type {any} */ (module).restoreFromUnsafeCache &&
|
1743
|
+
this._unsafeCachePredicate(module)
|
1744
|
+
) {
|
1745
|
+
for (let i = 0; i < dependencies.length; i++) {
|
1746
|
+
const dependency = dependencies[i];
|
1747
|
+
moduleGraph.setResolvedModule(
|
1748
|
+
connectOrigin ? originModule : null,
|
1749
|
+
dependency,
|
1750
|
+
module
|
1751
|
+
);
|
1752
|
+
unsafeCacheDependencies.set(
|
1753
|
+
dependency,
|
1754
|
+
/** @type {any} */ (module)
|
1755
|
+
);
|
1756
|
+
}
|
1757
|
+
if (!unsafeCacheData.has(module)) {
|
1758
|
+
unsafeCacheData.set(module, module.getUnsafeCacheData());
|
1759
|
+
}
|
1760
|
+
} else {
|
1761
|
+
applyFactoryResultDependencies();
|
1762
|
+
for (let i = 0; i < dependencies.length; i++) {
|
1763
|
+
const dependency = dependencies[i];
|
1764
|
+
moduleGraph.setResolvedModule(
|
1765
|
+
connectOrigin ? originModule : null,
|
1766
|
+
dependency,
|
1767
|
+
module
|
1768
|
+
);
|
1769
|
+
}
|
1615
1770
|
}
|
1616
1771
|
|
1617
1772
|
moduleGraph.setIssuerIfUnset(
|
@@ -1629,99 +1784,89 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
|
|
1629
1784
|
}
|
1630
1785
|
}
|
1631
1786
|
|
1632
|
-
|
1633
|
-
|
1634
|
-
|
1635
|
-
|
1636
|
-
|
1637
|
-
|
1638
|
-
|
1639
|
-
|
1640
|
-
|
1641
|
-
|
1642
|
-
creatingModuleDuringBuildSet
|
1643
|
-
);
|
1644
|
-
}
|
1645
|
-
creatingModuleDuringBuildSet.add(originModule);
|
1646
|
-
|
1647
|
-
// When building is blocked by another module
|
1648
|
-
// search for a cycle, cancel the cycle by throwing
|
1649
|
-
// an error (otherwise this would deadlock)
|
1650
|
-
const blockReasons = this.creatingModuleDuringBuild.get(module);
|
1651
|
-
if (blockReasons !== undefined) {
|
1652
|
-
const set = new Set(blockReasons);
|
1653
|
-
for (const item of set) {
|
1654
|
-
const blockReasons = this.creatingModuleDuringBuild.get(item);
|
1655
|
-
if (blockReasons !== undefined) {
|
1656
|
-
for (const m of blockReasons) {
|
1657
|
-
if (m === module) {
|
1658
|
-
return callback(new BuildCycleError(module));
|
1659
|
-
}
|
1660
|
-
set.add(m);
|
1661
|
-
}
|
1662
|
-
}
|
1663
|
-
}
|
1664
|
-
}
|
1665
|
-
}
|
1787
|
+
this._handleModuleBuildAndDependencies(
|
1788
|
+
originModule,
|
1789
|
+
module,
|
1790
|
+
recursive,
|
1791
|
+
callback
|
1792
|
+
);
|
1793
|
+
});
|
1794
|
+
}
|
1795
|
+
);
|
1796
|
+
}
|
1666
1797
|
|
1667
|
-
|
1668
|
-
|
1669
|
-
|
1670
|
-
|
1671
|
-
|
1672
|
-
|
1673
|
-
|
1798
|
+
_handleModuleBuildAndDependencies(originModule, module, recursive, callback) {
|
1799
|
+
// Check for cycles when build is trigger inside another build
|
1800
|
+
let creatingModuleDuringBuildSet = undefined;
|
1801
|
+
if (!recursive && this.buildQueue.isProcessing(originModule)) {
|
1802
|
+
// Track build dependency
|
1803
|
+
creatingModuleDuringBuildSet =
|
1804
|
+
this.creatingModuleDuringBuild.get(originModule);
|
1805
|
+
if (creatingModuleDuringBuildSet === undefined) {
|
1806
|
+
creatingModuleDuringBuildSet = new Set();
|
1807
|
+
this.creatingModuleDuringBuild.set(
|
1808
|
+
originModule,
|
1809
|
+
creatingModuleDuringBuildSet
|
1810
|
+
);
|
1811
|
+
}
|
1812
|
+
creatingModuleDuringBuildSet.add(originModule);
|
1813
|
+
|
1814
|
+
// When building is blocked by another module
|
1815
|
+
// search for a cycle, cancel the cycle by throwing
|
1816
|
+
// an error (otherwise this would deadlock)
|
1817
|
+
const blockReasons = this.creatingModuleDuringBuild.get(module);
|
1818
|
+
if (blockReasons !== undefined) {
|
1819
|
+
const set = new Set(blockReasons);
|
1820
|
+
for (const item of set) {
|
1821
|
+
const blockReasons = this.creatingModuleDuringBuild.get(item);
|
1822
|
+
if (blockReasons !== undefined) {
|
1823
|
+
for (const m of blockReasons) {
|
1824
|
+
if (m === module) {
|
1825
|
+
return callback(new BuildCycleError(module));
|
1674
1826
|
}
|
1675
|
-
|
1676
|
-
|
1677
|
-
return callback(err);
|
1827
|
+
set.add(m);
|
1678
1828
|
}
|
1829
|
+
}
|
1830
|
+
}
|
1831
|
+
}
|
1832
|
+
}
|
1679
1833
|
|
1680
|
-
|
1681
|
-
|
1682
|
-
|
1683
|
-
|
1684
|
-
|
1834
|
+
this.buildModule(module, err => {
|
1835
|
+
if (creatingModuleDuringBuildSet !== undefined) {
|
1836
|
+
creatingModuleDuringBuildSet.delete(module);
|
1837
|
+
}
|
1838
|
+
if (err) {
|
1839
|
+
if (!err.module) {
|
1840
|
+
err.module = module;
|
1841
|
+
}
|
1842
|
+
this.errors.push(err);
|
1685
1843
|
|
1686
|
-
|
1687
|
-
|
1688
|
-
return callback();
|
1689
|
-
}
|
1844
|
+
return callback(err);
|
1845
|
+
}
|
1690
1846
|
|
1691
|
-
|
1692
|
-
|
1693
|
-
|
1694
|
-
|
1695
|
-
callback(null, module);
|
1696
|
-
});
|
1697
|
-
});
|
1698
|
-
});
|
1847
|
+
if (!recursive) {
|
1848
|
+
this.processModuleDependenciesNonRecursive(module);
|
1849
|
+
callback(null, module);
|
1850
|
+
return;
|
1699
1851
|
}
|
1700
|
-
);
|
1701
|
-
}
|
1702
1852
|
|
1703
|
-
|
1704
|
-
|
1705
|
-
|
1706
|
-
|
1707
|
-
* @property {Dependency[]} dependencies
|
1708
|
-
* @property {Module | null} originModule
|
1709
|
-
* @property {Partial<ModuleFactoryCreateDataContextInfo>=} contextInfo
|
1710
|
-
* @property {string=} context
|
1711
|
-
*/
|
1853
|
+
// This avoids deadlocks for circular dependencies
|
1854
|
+
if (this.processDependenciesQueue.isProcessing(module)) {
|
1855
|
+
return callback();
|
1856
|
+
}
|
1712
1857
|
|
1713
|
-
|
1714
|
-
|
1715
|
-
|
1716
|
-
|
1717
|
-
|
1718
|
-
|
1719
|
-
|
1858
|
+
this.processModuleDependencies(module, err => {
|
1859
|
+
if (err) {
|
1860
|
+
return callback(err);
|
1861
|
+
}
|
1862
|
+
callback(null, module);
|
1863
|
+
});
|
1864
|
+
});
|
1720
1865
|
}
|
1721
1866
|
|
1722
1867
|
/**
|
1723
1868
|
* @param {FactorizeModuleOptions} options options object
|
1724
|
-
* @param {
|
1869
|
+
* @param {ModuleOrFactoryResultCallback} callback callback
|
1725
1870
|
* @returns {void}
|
1726
1871
|
*/
|
1727
1872
|
_factorizeModule(
|
@@ -1730,6 +1875,7 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
|
|
1730
1875
|
factory,
|
1731
1876
|
dependencies,
|
1732
1877
|
originModule,
|
1878
|
+
factoryResult,
|
1733
1879
|
contextInfo,
|
1734
1880
|
context
|
1735
1881
|
},
|
@@ -1763,16 +1909,21 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
|
|
1763
1909
|
module: result
|
1764
1910
|
};
|
1765
1911
|
}
|
1766
|
-
|
1767
|
-
|
1768
|
-
|
1769
|
-
|
1770
|
-
|
1771
|
-
|
1772
|
-
|
1773
|
-
|
1774
|
-
|
1775
|
-
|
1912
|
+
if (!factoryResult) {
|
1913
|
+
const {
|
1914
|
+
fileDependencies,
|
1915
|
+
contextDependencies,
|
1916
|
+
missingDependencies
|
1917
|
+
} = result;
|
1918
|
+
if (fileDependencies) {
|
1919
|
+
this.fileDependencies.addAll(fileDependencies);
|
1920
|
+
}
|
1921
|
+
if (contextDependencies) {
|
1922
|
+
this.contextDependencies.addAll(contextDependencies);
|
1923
|
+
}
|
1924
|
+
if (missingDependencies) {
|
1925
|
+
this.missingDependencies.addAll(missingDependencies);
|
1926
|
+
}
|
1776
1927
|
}
|
1777
1928
|
}
|
1778
1929
|
if (err) {
|
@@ -1781,20 +1932,17 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
|
|
1781
1932
|
err,
|
1782
1933
|
dependencies.map(d => d.loc).filter(Boolean)[0]
|
1783
1934
|
);
|
1784
|
-
return callback(notFoundError);
|
1935
|
+
return callback(notFoundError, factoryResult ? result : undefined);
|
1785
1936
|
}
|
1786
1937
|
if (!result) {
|
1787
1938
|
return callback();
|
1788
1939
|
}
|
1789
|
-
|
1790
|
-
if (!newModule) {
|
1791
|
-
return callback();
|
1792
|
-
}
|
1940
|
+
|
1793
1941
|
if (currentProfile !== undefined) {
|
1794
1942
|
currentProfile.markFactoryEnd();
|
1795
1943
|
}
|
1796
1944
|
|
1797
|
-
callback(null,
|
1945
|
+
callback(null, factoryResult ? result : result.module);
|
1798
1946
|
}
|
1799
1947
|
);
|
1800
1948
|
}
|
@@ -2020,64 +2168,143 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
|
|
2020
2168
|
_computeAffectedModules(modules) {
|
2021
2169
|
const moduleMemCacheCache = this.compiler.moduleMemCaches;
|
2022
2170
|
if (!moduleMemCacheCache) return;
|
2023
|
-
if (!this.moduleMemCaches)
|
2024
|
-
|
2025
|
-
|
2171
|
+
if (!this.moduleMemCaches) {
|
2172
|
+
this.moduleMemCaches = new WeakMap();
|
2173
|
+
this.moduleGraph.setModuleMemCaches(this.moduleMemCaches);
|
2174
|
+
}
|
2175
|
+
const { moduleGraph, moduleMemCaches } = this;
|
2026
2176
|
const affectedModules = new Set();
|
2027
2177
|
const infectedModules = new Set();
|
2028
2178
|
let statNew = 0;
|
2029
2179
|
let statChanged = 0;
|
2030
2180
|
let statUnchanged = 0;
|
2181
|
+
let statReferencesChanged = 0;
|
2031
2182
|
let statWithoutHash = 0;
|
2183
|
+
|
2184
|
+
const computeReferences = module => {
|
2185
|
+
/** @type {WeakMap<Dependency, Module>} */
|
2186
|
+
let references = undefined;
|
2187
|
+
for (const connection of moduleGraph.getOutgoingConnections(module)) {
|
2188
|
+
const d = connection.dependency;
|
2189
|
+
const m = connection.module;
|
2190
|
+
if (!d || !m || unsafeCacheDependencies.has(d)) continue;
|
2191
|
+
if (references === undefined) references = new WeakMap();
|
2192
|
+
references.set(d, m);
|
2193
|
+
}
|
2194
|
+
return references;
|
2195
|
+
};
|
2196
|
+
|
2197
|
+
/**
|
2198
|
+
* @param {Module} module the module
|
2199
|
+
* @param {WeakMap<Dependency, Module>} references references
|
2200
|
+
* @returns {boolean} true, when the references differ
|
2201
|
+
*/
|
2202
|
+
const compareReferences = (module, references) => {
|
2203
|
+
if (references === undefined) return true;
|
2204
|
+
for (const connection of moduleGraph.getOutgoingConnections(module)) {
|
2205
|
+
const d = connection.dependency;
|
2206
|
+
if (!d) continue;
|
2207
|
+
const entry = references.get(d);
|
2208
|
+
if (entry === undefined) continue;
|
2209
|
+
if (entry !== connection.module) return false;
|
2210
|
+
}
|
2211
|
+
return true;
|
2212
|
+
};
|
2213
|
+
|
2032
2214
|
for (const module of modules) {
|
2033
2215
|
const hash = module.buildInfo && module.buildInfo.hash;
|
2034
2216
|
if (typeof hash === "string") {
|
2035
2217
|
const cachedMemCache = moduleMemCacheCache.get(module);
|
2036
2218
|
if (cachedMemCache === undefined) {
|
2037
2219
|
// create a new entry
|
2220
|
+
const memCache = new WeakTupleMap();
|
2038
2221
|
moduleMemCacheCache.set(module, {
|
2039
2222
|
hash: hash,
|
2223
|
+
references: computeReferences(module),
|
2040
2224
|
memCache
|
2041
2225
|
});
|
2042
2226
|
moduleMemCaches.set(module, memCache);
|
2043
2227
|
affectedModules.add(module);
|
2044
2228
|
statNew++;
|
2045
|
-
} else if (cachedMemCache.hash
|
2046
|
-
// keep the old mem cache
|
2047
|
-
moduleMemCaches.set(module, cachedMemCache.memCache);
|
2048
|
-
statUnchanged++;
|
2049
|
-
} else {
|
2229
|
+
} else if (cachedMemCache.hash !== hash) {
|
2050
2230
|
// use a new one
|
2231
|
+
const memCache = new WeakTupleMap();
|
2051
2232
|
moduleMemCaches.set(module, memCache);
|
2052
2233
|
affectedModules.add(module);
|
2053
2234
|
cachedMemCache.hash = hash;
|
2235
|
+
cachedMemCache.references = computeReferences(module);
|
2054
2236
|
cachedMemCache.memCache = memCache;
|
2055
2237
|
statChanged++;
|
2238
|
+
} else if (!compareReferences(module, cachedMemCache.references)) {
|
2239
|
+
// use a new one
|
2240
|
+
const memCache = new WeakTupleMap();
|
2241
|
+
moduleMemCaches.set(module, memCache);
|
2242
|
+
affectedModules.add(module);
|
2243
|
+
cachedMemCache.references = computeReferences(module);
|
2244
|
+
cachedMemCache.memCache = memCache;
|
2245
|
+
statReferencesChanged++;
|
2246
|
+
} else {
|
2247
|
+
// keep the old mem cache
|
2248
|
+
moduleMemCaches.set(module, cachedMemCache.memCache);
|
2249
|
+
statUnchanged++;
|
2056
2250
|
}
|
2057
2251
|
} else {
|
2058
2252
|
infectedModules.add(module);
|
2059
2253
|
statWithoutHash++;
|
2060
2254
|
}
|
2061
2255
|
}
|
2256
|
+
const reduceAffectType = connections => {
|
2257
|
+
let affected = false;
|
2258
|
+
for (const { dependency } of connections) {
|
2259
|
+
if (!dependency) continue;
|
2260
|
+
const type = dependency.couldAffectReferencingModule();
|
2261
|
+
if (type === Dependency.TRANSITIVE) return Dependency.TRANSITIVE;
|
2262
|
+
if (type === false) continue;
|
2263
|
+
affected = true;
|
2264
|
+
}
|
2265
|
+
return affected;
|
2266
|
+
};
|
2267
|
+
const directOnlyInfectedModules = new Set();
|
2062
2268
|
for (const module of infectedModules) {
|
2063
|
-
for (const
|
2064
|
-
|
2065
|
-
|
2269
|
+
for (const [
|
2270
|
+
referencingModule,
|
2271
|
+
connections
|
2272
|
+
] of moduleGraph.getIncomingConnectionsByOriginModule(module)) {
|
2273
|
+
if (!referencingModule) continue;
|
2066
2274
|
if (infectedModules.has(referencingModule)) continue;
|
2067
|
-
|
2275
|
+
const type = reduceAffectType(connections);
|
2276
|
+
if (!type) continue;
|
2277
|
+
if (type === true) {
|
2278
|
+
directOnlyInfectedModules.add(referencingModule);
|
2279
|
+
} else {
|
2280
|
+
infectedModules.add(referencingModule);
|
2281
|
+
}
|
2068
2282
|
}
|
2069
2283
|
}
|
2284
|
+
for (const module of directOnlyInfectedModules) infectedModules.add(module);
|
2285
|
+
const directOnlyAffectModules = new Set();
|
2070
2286
|
for (const module of affectedModules) {
|
2071
|
-
for (const
|
2072
|
-
|
2073
|
-
|
2287
|
+
for (const [
|
2288
|
+
referencingModule,
|
2289
|
+
connections
|
2290
|
+
] of moduleGraph.getIncomingConnectionsByOriginModule(module)) {
|
2074
2291
|
if (!referencingModule) continue;
|
2075
2292
|
if (infectedModules.has(referencingModule)) continue;
|
2076
2293
|
if (affectedModules.has(referencingModule)) continue;
|
2077
|
-
|
2294
|
+
const type = reduceAffectType(connections);
|
2295
|
+
if (!type) continue;
|
2296
|
+
if (type === true) {
|
2297
|
+
directOnlyAffectModules.add(referencingModule);
|
2298
|
+
} else {
|
2299
|
+
affectedModules.add(referencingModule);
|
2300
|
+
}
|
2301
|
+
const memCache = new WeakTupleMap();
|
2302
|
+
const cache = moduleMemCacheCache.get(referencingModule);
|
2303
|
+
cache.memCache = memCache;
|
2078
2304
|
moduleMemCaches.set(referencingModule, memCache);
|
2079
2305
|
}
|
2080
2306
|
}
|
2307
|
+
for (const module of directOnlyAffectModules) affectedModules.add(module);
|
2081
2308
|
this.logger.log(
|
2082
2309
|
`${Math.round(
|
2083
2310
|
(100 * (affectedModules.size + infectedModules.size)) /
|
@@ -2086,7 +2313,7 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
|
|
2086
2313
|
infectedModules.size
|
2087
2314
|
} infected of ${
|
2088
2315
|
this.modules.size
|
2089
|
-
}) modules flagged as affected (${statNew} new modules, ${statChanged} changed, ${statUnchanged} unchanged, ${statWithoutHash} without hash)`
|
2316
|
+
}) modules flagged as affected (${statNew} new modules, ${statChanged} changed, ${statReferencesChanged} references changed, ${statUnchanged} unchanged, ${statWithoutHash} without hash)`
|
2090
2317
|
);
|
2091
2318
|
}
|
2092
2319
|
|
@@ -2280,7 +2507,7 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
|
|
2280
2507
|
if (err) return callback(err);
|
2281
2508
|
|
2282
2509
|
// extract warnings and errors from modules
|
2283
|
-
this.moduleGraph.freeze();
|
2510
|
+
this.moduleGraph.freeze("dependency errors");
|
2284
2511
|
// TODO keep a cacheToken (= {}) for each module in the graph
|
2285
2512
|
// create a new one per compilation and flag all updated files
|
2286
2513
|
// and parents with it
|
@@ -2289,7 +2516,7 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
|
|
2289
2516
|
// TODO only run for modules with changed cacheToken
|
2290
2517
|
// global WeakMap<CacheToken, WeakSet<Module>> to keep modules without errors/warnings
|
2291
2518
|
const memCache = moduleMemCaches && moduleMemCaches.get(module);
|
2292
|
-
if (memCache && memCache.get(
|
2519
|
+
if (memCache && memCache.get("noWarningsOrErrors")) continue;
|
2293
2520
|
let hasProblems = this.reportDependencyErrorsAndWarnings(module, [
|
2294
2521
|
module
|
2295
2522
|
]);
|
@@ -2313,8 +2540,7 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
|
|
2313
2540
|
hasProblems = true;
|
2314
2541
|
}
|
2315
2542
|
}
|
2316
|
-
if (!hasProblems && memCache)
|
2317
|
-
memCache.set(module, "noWarningsOrErrors", true);
|
2543
|
+
if (!hasProblems && memCache) memCache.set("noWarningsOrErrors", true);
|
2318
2544
|
}
|
2319
2545
|
this.moduleGraph.unfreeze();
|
2320
2546
|
this.logger.timeEnd("report dependency errors and warnings");
|
@@ -2371,7 +2597,7 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
|
|
2371
2597
|
|
2372
2598
|
this.logger.time("create chunks");
|
2373
2599
|
this.hooks.beforeChunks.call();
|
2374
|
-
this.moduleGraph.freeze();
|
2600
|
+
this.moduleGraph.freeze("seal");
|
2375
2601
|
/** @type {Map<Entrypoint, Module[]>} */
|
2376
2602
|
const chunkGraphInit = new Map();
|
2377
2603
|
for (const [name, { dependencies, includeDependencies, options }] of this
|
@@ -2907,17 +3133,11 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
|
|
2907
3133
|
// modules with async blocks depend on the chunk graph and can't be cached that way
|
2908
3134
|
module.blocks.length === 0 &&
|
2909
3135
|
moduleMemCaches.get(module);
|
2910
|
-
/** @type {RuntimeSpecMap<Set<string>>} */
|
2911
|
-
const moduleRuntimeRequirementsMemCache =
|
2912
|
-
memCache &&
|
2913
|
-
memCache.provide(
|
2914
|
-
module,
|
2915
|
-
"moduleRuntimeRequirements",
|
2916
|
-
() => new RuntimeSpecMap()
|
2917
|
-
);
|
2918
3136
|
for (const runtime of chunkGraph.getModuleRuntimes(module)) {
|
2919
|
-
if (
|
2920
|
-
const cached =
|
3137
|
+
if (memCache) {
|
3138
|
+
const cached = memCache.get(
|
3139
|
+
`moduleRuntimeRequirements-${getRuntimeKey(runtime)}`
|
3140
|
+
);
|
2921
3141
|
if (cached !== undefined) {
|
2922
3142
|
if (cached !== null) {
|
2923
3143
|
chunkGraph.addModuleRuntimeRequirements(
|
@@ -2938,8 +3158,11 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
|
|
2938
3158
|
} else if (additionalModuleRuntimeRequirements.isUsed()) {
|
2939
3159
|
set = new Set();
|
2940
3160
|
} else {
|
2941
|
-
if (
|
2942
|
-
|
3161
|
+
if (memCache) {
|
3162
|
+
memCache.set(
|
3163
|
+
`moduleRuntimeRequirements-${getRuntimeKey(runtime)}`,
|
3164
|
+
null
|
3165
|
+
);
|
2943
3166
|
}
|
2944
3167
|
continue;
|
2945
3168
|
}
|
@@ -2950,12 +3173,18 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
|
|
2950
3173
|
if (hook !== undefined) hook.call(module, set, context);
|
2951
3174
|
}
|
2952
3175
|
if (set.size === 0) {
|
2953
|
-
if (
|
2954
|
-
|
3176
|
+
if (memCache) {
|
3177
|
+
memCache.set(
|
3178
|
+
`moduleRuntimeRequirements-${getRuntimeKey(runtime)}`,
|
3179
|
+
null
|
3180
|
+
);
|
2955
3181
|
}
|
2956
3182
|
} else {
|
2957
|
-
if (
|
2958
|
-
|
3183
|
+
if (memCache) {
|
3184
|
+
memCache.set(
|
3185
|
+
`moduleRuntimeRequirements-${getRuntimeKey(runtime)}`,
|
3186
|
+
set
|
3187
|
+
);
|
2959
3188
|
chunkGraph.addModuleRuntimeRequirements(
|
2960
3189
|
module,
|
2961
3190
|
runtime,
|
@@ -3368,13 +3597,9 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
|
|
3368
3597
|
// modules with async blocks depend on the chunk graph and can't be cached that way
|
3369
3598
|
module.blocks.length === 0 &&
|
3370
3599
|
moduleMemCaches.get(module);
|
3371
|
-
/** @type {RuntimeSpecMap<string>} */
|
3372
|
-
const moduleHashesMemCache =
|
3373
|
-
memCache &&
|
3374
|
-
memCache.provide(module, "moduleHashes", () => new RuntimeSpecMap());
|
3375
3600
|
for (const runtime of chunkGraph.getModuleRuntimes(module)) {
|
3376
|
-
if (
|
3377
|
-
const digest =
|
3601
|
+
if (memCache) {
|
3602
|
+
const digest = memCache.get(`moduleHash-${getRuntimeKey(runtime)}`);
|
3378
3603
|
if (digest !== undefined) {
|
3379
3604
|
chunkGraph.setModuleHashes(
|
3380
3605
|
module,
|
@@ -3396,8 +3621,8 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
|
|
3396
3621
|
hashDigest,
|
3397
3622
|
hashDigestLength
|
3398
3623
|
);
|
3399
|
-
if (
|
3400
|
-
|
3624
|
+
if (memCache) {
|
3625
|
+
memCache.set(`moduleHash-${getRuntimeKey(runtime)}`, digest);
|
3401
3626
|
}
|
3402
3627
|
}
|
3403
3628
|
}
|
@@ -4609,6 +4834,33 @@ This prevents using hashes of each other and should be avoided.`);
|
|
4609
4834
|
}
|
4610
4835
|
}
|
4611
4836
|
|
4837
|
+
/**
|
4838
|
+
* @typedef {Object} FactorizeModuleOptions
|
4839
|
+
* @property {ModuleProfile} currentProfile
|
4840
|
+
* @property {ModuleFactory} factory
|
4841
|
+
* @property {Dependency[]} dependencies
|
4842
|
+
* @property {boolean=} factoryResult return full ModuleFactoryResult instead of only module
|
4843
|
+
* @property {Module | null} originModule
|
4844
|
+
* @property {Partial<ModuleFactoryCreateDataContextInfo>=} contextInfo
|
4845
|
+
* @property {string=} context
|
4846
|
+
*/
|
4847
|
+
|
4848
|
+
/**
|
4849
|
+
* @param {FactorizeModuleOptions} options options object
|
4850
|
+
* @param {ModuleCallback | ModuleFactoryResultCallback} callback callback
|
4851
|
+
* @returns {void}
|
4852
|
+
*/
|
4853
|
+
|
4854
|
+
// Workaround for typescript as it doesn't support function overloading in jsdoc within a class
|
4855
|
+
Compilation.prototype.factorizeModule = /** @type {{
|
4856
|
+
(options: FactorizeModuleOptions & { factoryResult?: false }, callback: ModuleCallback): void;
|
4857
|
+
(options: FactorizeModuleOptions & { factoryResult: true }, callback: ModuleFactoryResultCallback): void;
|
4858
|
+
}} */ (
|
4859
|
+
function (options, callback) {
|
4860
|
+
this.factorizeQueue.add(options, callback);
|
4861
|
+
}
|
4862
|
+
);
|
4863
|
+
|
4612
4864
|
// Hide from typescript
|
4613
4865
|
const compilationPrototype = Compilation.prototype;
|
4614
4866
|
|