webpack 5.35.1 → 5.37.0

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.

Files changed (37) hide show
  1. package/lib/Chunk.js +8 -2
  2. package/lib/ChunkGraph.js +58 -35
  3. package/lib/Compilation.js +73 -43
  4. package/lib/Compiler.js +27 -13
  5. package/lib/Dependency.js +69 -4
  6. package/lib/EntryPlugin.js +1 -1
  7. package/lib/FileSystemInfo.js +1 -1
  8. package/lib/InitFragment.js +21 -6
  9. package/lib/ModuleGraph.js +2 -2
  10. package/lib/NormalModule.js +16 -2
  11. package/lib/NormalModuleFactory.js +27 -23
  12. package/lib/RuntimeGlobals.js +7 -0
  13. package/lib/RuntimePlugin.js +19 -1
  14. package/lib/SourceMapDevToolPlugin.js +1 -1
  15. package/lib/WebpackOptionsApply.js +1 -0
  16. package/lib/buildChunkGraph.js +7 -2
  17. package/lib/cache/PackFileCacheStrategy.js +65 -4
  18. package/lib/config/defaults.js +12 -1
  19. package/lib/config/normalization.js +10 -0
  20. package/lib/dependencies/CreateScriptUrlDependency.js +54 -0
  21. package/lib/dependencies/HarmonyExportInitFragment.js +47 -0
  22. package/lib/dependencies/NullDependency.js +0 -8
  23. package/lib/dependencies/WorkerPlugin.js +32 -4
  24. package/lib/javascript/JavascriptParser.js +39 -31
  25. package/lib/optimize/InnerGraphPlugin.js +8 -9
  26. package/lib/runtime/CreateScriptUrlRuntimeModule.js +61 -0
  27. package/lib/runtime/LoadScriptRuntimeModule.js +10 -2
  28. package/lib/util/AsyncQueue.js +6 -1
  29. package/lib/util/comparators.js +22 -16
  30. package/lib/util/fs.js +8 -8
  31. package/lib/util/internalSerializables.js +2 -0
  32. package/lib/webworker/ImportScriptsChunkLoadingPlugin.js +13 -1
  33. package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +14 -4
  34. package/package.json +5 -5
  35. package/schemas/WebpackOptions.check.js +1 -1
  36. package/schemas/WebpackOptions.json +35 -0
  37. package/types.d.ts +479 -44
package/lib/Chunk.js CHANGED
@@ -568,9 +568,15 @@ class Chunk {
568
568
  Array.from(this.groupsIterable, g => new Set(g.chunks))
569
569
  );
570
570
 
571
- for (const chunkGroup of this.groupsIterable) {
571
+ const initialQueue = new Set(this.groupsIterable);
572
+
573
+ for (const chunkGroup of initialQueue) {
572
574
  for (const child of chunkGroup.childrenIterable) {
573
- queue.add(child);
575
+ if (child instanceof Entrypoint) {
576
+ initialQueue.add(child);
577
+ } else {
578
+ queue.add(child);
579
+ }
574
580
  }
575
581
  }
576
582
 
package/lib/ChunkGraph.js CHANGED
@@ -1446,17 +1446,37 @@ Caller might not support runtime-dependent code generation (opt-out via optimiza
1446
1446
  runtime
1447
1447
  ).toString(16);
1448
1448
  const connections = this.moduleGraph.getOutgoingConnections(module);
1449
+ /** @type {Set<Module>} */
1450
+ const activeNamespaceModules = new Set();
1449
1451
  /** @type {Map<string, Module | Set<Module>>} */
1450
1452
  const connectedModules = new Map();
1451
- for (const connection of connections) {
1452
- let stateInfo;
1453
- if (typeof runtime === "string") {
1453
+ const processConnection = (connection, stateInfo) => {
1454
+ const module = connection.module;
1455
+ stateInfo += module.getExportsType(this.moduleGraph, strict);
1456
+ // cspell:word Tnamespace
1457
+ if (stateInfo === "Tnamespace") activeNamespaceModules.add(module);
1458
+ else {
1459
+ const oldModule = connectedModules.get(stateInfo);
1460
+ if (oldModule === undefined) {
1461
+ connectedModules.set(stateInfo, module);
1462
+ } else if (oldModule instanceof Set) {
1463
+ oldModule.add(module);
1464
+ } else if (oldModule !== module) {
1465
+ connectedModules.set(stateInfo, new Set([oldModule, module]));
1466
+ }
1467
+ }
1468
+ };
1469
+ if (runtime === undefined || typeof runtime === "string") {
1470
+ for (const connection of connections) {
1454
1471
  const state = connection.getActiveState(runtime);
1455
1472
  if (state === false) continue;
1456
- stateInfo = activeStateToString(state);
1457
- } else {
1473
+ processConnection(connection, state === true ? "T" : "O");
1474
+ }
1475
+ } else {
1476
+ // cspell:word Tnamespace
1477
+ for (const connection of connections) {
1458
1478
  const states = new Set();
1459
- stateInfo = "";
1479
+ let stateInfo = "";
1460
1480
  forEachRuntime(
1461
1481
  runtime,
1462
1482
  runtime => {
@@ -1471,46 +1491,49 @@ Caller might not support runtime-dependent code generation (opt-out via optimiza
1471
1491
  if (state === false) continue;
1472
1492
  stateInfo = activeStateToString(state);
1473
1493
  }
1474
- }
1475
- const module = connection.module;
1476
- stateInfo += module.getExportsType(this.moduleGraph, strict);
1477
- const oldModule = connectedModules.get(stateInfo);
1478
- if (oldModule === undefined) {
1479
- connectedModules.set(stateInfo, module);
1480
- } else if (oldModule instanceof Set) {
1481
- oldModule.add(module);
1482
- } else if (oldModule !== module) {
1483
- connectedModules.set(stateInfo, new Set([oldModule, module]));
1494
+ processConnection(connection, stateInfo);
1484
1495
  }
1485
1496
  }
1486
- if (connectedModules.size === 0) return graphHash;
1497
+ // cspell:word Tnamespace
1498
+ if (activeNamespaceModules.size === 0 && connectedModules.size === 0)
1499
+ return graphHash;
1487
1500
  const connectedModulesInOrder =
1488
1501
  connectedModules.size > 1
1489
1502
  ? Array.from(connectedModules).sort(([a], [b]) => (a < b ? -1 : 1))
1490
1503
  : connectedModules;
1491
1504
  const hash = createHash("md4");
1505
+ const addModuleToHash = module => {
1506
+ hash.update(
1507
+ this._getModuleGraphHashBigInt(
1508
+ this._getChunkGraphModule(module),
1509
+ module,
1510
+ runtime
1511
+ ).toString(16)
1512
+ );
1513
+ };
1514
+ const addModulesToHash = modules => {
1515
+ let xor = ZERO_BIG_INT;
1516
+ for (const m of modules) {
1517
+ xor =
1518
+ xor ^
1519
+ this._getModuleGraphHashBigInt(
1520
+ this._getChunkGraphModule(m),
1521
+ m,
1522
+ runtime
1523
+ );
1524
+ }
1525
+ hash.update(xor.toString(16));
1526
+ };
1527
+ if (activeNamespaceModules.size === 1)
1528
+ addModuleToHash(activeNamespaceModules.values().next().value);
1529
+ else if (activeNamespaceModules.size > 1)
1530
+ addModulesToHash(activeNamespaceModules);
1492
1531
  for (const [stateInfo, modules] of connectedModulesInOrder) {
1493
1532
  hash.update(stateInfo);
1494
1533
  if (modules instanceof Set) {
1495
- let xor = ZERO_BIG_INT;
1496
- for (const m of modules) {
1497
- xor =
1498
- xor ^
1499
- this._getModuleGraphHashBigInt(
1500
- this._getChunkGraphModule(m),
1501
- m,
1502
- runtime
1503
- );
1504
- }
1505
- hash.update(xor.toString(16));
1534
+ addModulesToHash(modules);
1506
1535
  } else {
1507
- hash.update(
1508
- this._getModuleGraphHashBigInt(
1509
- this._getChunkGraphModule(modules),
1510
- modules,
1511
- runtime
1512
- ).toString(16)
1513
- );
1536
+ addModuleToHash(modules);
1514
1537
  }
1515
1538
  }
1516
1539
  hash.update(graphHash);
@@ -1375,84 +1375,114 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
1375
1375
  * @returns {void}
1376
1376
  */
1377
1377
  _processModuleDependencies(module, callback) {
1378
- const dependencies = new Map();
1379
-
1380
1378
  /**
1381
1379
  * @type {Array<{factory: ModuleFactory, dependencies: Dependency[], originModule: Module|null}>}
1382
1380
  */
1383
1381
  const sortedDependencies = [];
1384
1382
 
1385
- let currentBlock = module;
1383
+ /** @type {DependenciesBlock} */
1384
+ let currentBlock;
1386
1385
 
1386
+ /** @type {Map<ModuleFactory, Map<string, Dependency[]>>} */
1387
+ let dependencies;
1388
+ /** @type {DepConstructor} */
1387
1389
  let factoryCacheKey;
1390
+ /** @type {ModuleFactory} */
1391
+ let factoryCacheKey2;
1392
+ /** @type {Map<string, Dependency[]>} */
1388
1393
  let factoryCacheValue;
1389
- let factoryCacheValue2;
1390
- let listCacheKey;
1394
+ /** @type {string} */
1395
+ let listCacheKey1;
1396
+ /** @type {string} */
1397
+ let listCacheKey2;
1398
+ /** @type {Dependency[]} */
1391
1399
  let listCacheValue;
1392
1400
 
1401
+ /**
1402
+ * @param {Dependency} dep dependency
1403
+ * @returns {void}
1404
+ */
1393
1405
  const processDependency = dep => {
1394
1406
  this.moduleGraph.setParents(dep, currentBlock, module);
1395
1407
  const resourceIdent = dep.getResourceIdentifier();
1396
- if (resourceIdent) {
1397
- // Here webpack is using heuristic that assumes
1398
- // mostly esm dependencies would be used
1399
- // so we don't allocate extra string for them
1408
+ if (resourceIdent !== undefined && resourceIdent !== null) {
1400
1409
  const category = dep.category;
1401
- const cacheKey =
1402
- category === esmDependencyCategory
1403
- ? resourceIdent
1404
- : `${category}${resourceIdent}`;
1405
- const constructor = dep.constructor;
1406
- let innerMap;
1407
- let factory;
1410
+ const constructor = /** @type {DepConstructor} */ (dep.constructor);
1408
1411
  if (factoryCacheKey === constructor) {
1409
- innerMap = factoryCacheValue;
1410
- if (listCacheKey === cacheKey) {
1412
+ // Fast path 1: same constructor as prev item
1413
+ if (listCacheKey1 === category && listCacheKey2 === resourceIdent) {
1414
+ // Super fast path 1: also same resource
1411
1415
  listCacheValue.push(dep);
1412
1416
  return;
1413
1417
  }
1414
1418
  } else {
1415
- factory = this.dependencyFactories.get(dep.constructor);
1419
+ const factory = this.dependencyFactories.get(constructor);
1416
1420
  if (factory === undefined) {
1417
1421
  throw new Error(
1418
- `No module factory available for dependency type: ${dep.constructor.name}`
1422
+ `No module factory available for dependency type: ${constructor.name}`
1419
1423
  );
1420
1424
  }
1421
- innerMap = dependencies.get(factory);
1422
- if (innerMap === undefined) {
1423
- dependencies.set(factory, (innerMap = new Map()));
1425
+ if (factoryCacheKey2 === factory) {
1426
+ // Fast path 2: same factory as prev item
1427
+ factoryCacheKey = constructor;
1428
+ if (listCacheKey1 === category && listCacheKey2 === resourceIdent) {
1429
+ // Super fast path 2: also same resource
1430
+ listCacheValue.push(dep);
1431
+ return;
1432
+ }
1433
+ } else {
1434
+ // Slow path
1435
+ if (factoryCacheKey2 !== undefined) {
1436
+ // Archive last cache entry
1437
+ if (dependencies === undefined) dependencies = new Map();
1438
+ dependencies.set(factoryCacheKey2, factoryCacheValue);
1439
+ factoryCacheValue = dependencies.get(factory);
1440
+ if (factoryCacheValue === undefined) {
1441
+ factoryCacheValue = new Map();
1442
+ }
1443
+ } else {
1444
+ factoryCacheValue = new Map();
1445
+ }
1446
+ factoryCacheKey = constructor;
1447
+ factoryCacheKey2 = factory;
1424
1448
  }
1425
- factoryCacheKey = constructor;
1426
- factoryCacheValue = innerMap;
1427
- factoryCacheValue2 = factory;
1428
1449
  }
1429
- let list = innerMap.get(cacheKey);
1450
+ // Here webpack is using heuristic that assumes
1451
+ // mostly esm dependencies would be used
1452
+ // so we don't allocate extra string for them
1453
+ const cacheKey =
1454
+ category === esmDependencyCategory
1455
+ ? resourceIdent
1456
+ : `${category}${resourceIdent}`;
1457
+ let list = factoryCacheValue.get(cacheKey);
1430
1458
  if (list === undefined) {
1431
- innerMap.set(cacheKey, (list = []));
1459
+ factoryCacheValue.set(cacheKey, (list = []));
1432
1460
  sortedDependencies.push({
1433
- factory: factoryCacheValue2,
1461
+ factory: factoryCacheKey2,
1434
1462
  dependencies: list,
1435
1463
  originModule: module
1436
1464
  });
1437
1465
  }
1438
1466
  list.push(dep);
1439
- listCacheKey = cacheKey;
1467
+ listCacheKey1 = category;
1468
+ listCacheKey2 = resourceIdent;
1440
1469
  listCacheValue = list;
1441
1470
  }
1442
1471
  };
1443
1472
 
1444
- const processDependenciesBlock = block => {
1445
- if (block.dependencies) {
1446
- currentBlock = block;
1447
- for (const dep of block.dependencies) processDependency(dep);
1448
- }
1449
- if (block.blocks) {
1450
- for (const b of block.blocks) processDependenciesBlock(b);
1451
- }
1452
- };
1453
-
1454
1473
  try {
1455
- processDependenciesBlock(module);
1474
+ /** @type {DependenciesBlock[]} */
1475
+ const queue = [module];
1476
+ do {
1477
+ const block = queue.pop();
1478
+ if (block.dependencies) {
1479
+ currentBlock = block;
1480
+ for (const dep of block.dependencies) processDependency(dep);
1481
+ }
1482
+ if (block.blocks) {
1483
+ for (const b of block.blocks) queue.push(b);
1484
+ }
1485
+ } while (queue.length !== 0);
1456
1486
  } catch (e) {
1457
1487
  return callback(e);
1458
1488
  }
@@ -3963,8 +3993,8 @@ This prevents using hashes of each other and should be avoided.`);
3963
3993
  * from parent (or top level compiler) and creates a child Compilation
3964
3994
  *
3965
3995
  * @param {string} name name of the child compiler
3966
- * @param {OutputOptions} outputOptions // Need to convert config schema to types for this
3967
- * @param {Array<WebpackPluginInstance | WebpackPluginFunction>} plugins webpack plugins that will be applied
3996
+ * @param {OutputOptions=} outputOptions // Need to convert config schema to types for this
3997
+ * @param {Array<WebpackPluginInstance | WebpackPluginFunction>=} plugins webpack plugins that will be applied
3968
3998
  * @returns {Compiler} creates a child Compiler instance
3969
3999
  */
3970
4000
  createChildCompiler(name, outputOptions, plugins) {
package/lib/Compiler.js CHANGED
@@ -263,6 +263,8 @@ class Compiler {
263
263
  this._assetEmittingSourceCache = new WeakMap();
264
264
  /** @private @type {Map<string, number>} */
265
265
  this._assetEmittingWrittenFiles = new Map();
266
+ /** @private @type {Set<string>} */
267
+ this._assetEmittingPreviousFiles = new Set();
266
268
  }
267
269
 
268
270
  /**
@@ -556,6 +558,8 @@ class Compiler {
556
558
  compilation.assets = { ...compilation.assets };
557
559
  /** @type {Map<string, { path: string, source: Source, size: number, waiting: { cacheEntry: any, file: string }[] }>} */
558
560
  const caseInsensitiveMap = new Map();
561
+ /** @type {Set<string>} */
562
+ const allTargetPaths = new Set();
559
563
  asyncLib.forEachLimit(
560
564
  assets,
561
565
  15,
@@ -583,6 +587,7 @@ class Compiler {
583
587
  outputPath,
584
588
  targetFile
585
589
  );
590
+ allTargetPaths.add(targetPath);
586
591
 
587
592
  // check if the target file has already been written by this Compiler
588
593
  const targetFileGeneration = this._assetEmittingWrittenFiles.get(
@@ -775,18 +780,22 @@ ${other}`);
775
780
  // check if the Source has been written to this target file
776
781
  const writtenGeneration = cacheEntry.writtenTo.get(targetPath);
777
782
  if (writtenGeneration === targetFileGeneration) {
778
- // if yes, we skip writing the file
779
- // as it's already there
780
- // (we assume one doesn't remove files while the Compiler is running)
783
+ // if yes, we may skip writing the file
784
+ // if it's already there
785
+ // (we assume one doesn't modify files while the Compiler is running, other then removing them)
781
786
 
782
- compilation.updateAsset(file, cacheEntry.sizeOnlySource, {
783
- size: cacheEntry.sizeOnlySource.size()
784
- });
785
-
786
- return callback();
787
- }
787
+ if (this._assetEmittingPreviousFiles.has(targetPath)) {
788
+ // We assume that assets from the last compilation say intact on disk (they are not removed)
789
+ compilation.updateAsset(file, cacheEntry.sizeOnlySource, {
790
+ size: cacheEntry.sizeOnlySource.size()
791
+ });
788
792
 
789
- if (!immutable) {
793
+ return callback();
794
+ } else {
795
+ // Settings immutable will make it accept file content without comparing when file exist
796
+ immutable = true;
797
+ }
798
+ } else if (!immutable) {
790
799
  if (checkSimilarFile()) return;
791
800
  // We wrote to this file before which has very likely a different content
792
801
  // skip comparing and assume content is different for performance
@@ -822,7 +831,12 @@ ${other}`);
822
831
  err => {
823
832
  // Clear map to free up memory
824
833
  caseInsensitiveMap.clear();
825
- if (err) return callback(err);
834
+ if (err) {
835
+ this._assetEmittingPreviousFiles.clear();
836
+ return callback(err);
837
+ }
838
+
839
+ this._assetEmittingPreviousFiles = allTargetPaths;
826
840
 
827
841
  this.hooks.afterEmit.callAsync(compilation, err => {
828
842
  if (err) return callback(err);
@@ -917,8 +931,8 @@ ${other}`);
917
931
  * @param {Compilation} compilation the compilation
918
932
  * @param {string} compilerName the compiler's name
919
933
  * @param {number} compilerIndex the compiler's index
920
- * @param {OutputOptions} outputOptions the output options
921
- * @param {WebpackPluginInstance[]} plugins the plugins to apply
934
+ * @param {OutputOptions=} outputOptions the output options
935
+ * @param {WebpackPluginInstance[]=} plugins the plugins to apply
922
936
  * @returns {Compiler} a child compiler
923
937
  */
924
938
  createChildCompiler(
package/lib/Dependency.js CHANGED
@@ -95,8 +95,13 @@ class Dependency {
95
95
  // TODO check if this can be moved into ModuleDependency
96
96
  /** @type {boolean} */
97
97
  this.optional = false;
98
- /** @type {DependencyLocation} */
99
- this.loc = undefined;
98
+ this._locSL = 0;
99
+ this._locSC = 0;
100
+ this._locEL = 0;
101
+ this._locEC = 0;
102
+ this._locI = undefined;
103
+ this._locN = undefined;
104
+ this._loc = undefined;
100
105
  }
101
106
 
102
107
  /**
@@ -113,6 +118,56 @@ class Dependency {
113
118
  return "unknown";
114
119
  }
115
120
 
121
+ /**
122
+ * @returns {DependencyLocation} location
123
+ */
124
+ get loc() {
125
+ if (this._loc !== undefined) return this._loc;
126
+ /** @type {SyntheticDependencyLocation & RealDependencyLocation} */
127
+ const loc = {};
128
+ if (this._locSL > 0) {
129
+ loc.start = { line: this._locSL, column: this._locSC };
130
+ }
131
+ if (this._locEL > 0) {
132
+ loc.end = { line: this._locEL, column: this._locEC };
133
+ }
134
+ if (this._locN !== undefined) {
135
+ loc.name = this._locN;
136
+ }
137
+ if (this._locI !== undefined) {
138
+ loc.index = this._locI;
139
+ }
140
+ return (this._loc = loc);
141
+ }
142
+
143
+ set loc(loc) {
144
+ if ("start" in loc && typeof loc.start === "object") {
145
+ this._locSL = loc.start.line || 0;
146
+ this._locSC = loc.start.column || 0;
147
+ } else {
148
+ this._locSL = 0;
149
+ this._locSC = 0;
150
+ }
151
+ if ("end" in loc && typeof loc.end === "object") {
152
+ this._locEL = loc.end.line || 0;
153
+ this._locEC = loc.end.column || 0;
154
+ } else {
155
+ this._locEL = 0;
156
+ this._locEC = 0;
157
+ }
158
+ if ("index" in loc) {
159
+ this._locI = loc.index;
160
+ } else {
161
+ this._locI = undefined;
162
+ }
163
+ if ("name" in loc) {
164
+ this._locN = loc.name;
165
+ } else {
166
+ this._locN = undefined;
167
+ }
168
+ this._loc = loc;
169
+ }
170
+
116
171
  /**
117
172
  * @returns {string | null} an identifier to merge equal requests
118
173
  */
@@ -212,13 +267,23 @@ class Dependency {
212
267
  serialize({ write }) {
213
268
  write(this.weak);
214
269
  write(this.optional);
215
- write(this.loc);
270
+ write(this._locSL);
271
+ write(this._locSC);
272
+ write(this._locEL);
273
+ write(this._locEC);
274
+ write(this._locI);
275
+ write(this._locN);
216
276
  }
217
277
 
218
278
  deserialize({ read }) {
219
279
  this.weak = read();
220
280
  this.optional = read();
221
- this.loc = read();
281
+ this._locSL = read();
282
+ this._locSC = read();
283
+ this._locEL = read();
284
+ this._locEC = read();
285
+ this._locI = read();
286
+ this._locN = read();
222
287
  }
223
288
  }
224
289
 
@@ -17,7 +17,7 @@ class EntryPlugin {
17
17
  *
18
18
  * @param {string} context context path
19
19
  * @param {string} entry entry path
20
- * @param {EntryOptions | string} options entry options (passing a string is deprecated)
20
+ * @param {EntryOptions | string=} options entry options (passing a string is deprecated)
21
21
  */
22
22
  constructor(context, entry, options) {
23
23
  this.context = context;
@@ -1472,7 +1472,7 @@ class FileSystemInfo {
1472
1472
  }
1473
1473
  } else if (supportsEsm && /\.m?js$/.test(path)) {
1474
1474
  if (!this._warnAboutExperimentalEsmTracking) {
1475
- this.logger.info(
1475
+ this.logger.log(
1476
1476
  "Node.js doesn't offer a (nice) way to introspect the ESM dependency graph yet.\n" +
1477
1477
  "Until a full solution is available webpack uses an experimental ESM tracking based on parsing.\n" +
1478
1478
  "As best effort webpack parses the ESM files to guess dependencies. But this can lead to expensive and incorrect tracking."
@@ -73,13 +73,25 @@ class InitFragment {
73
73
  // Deduplicate fragments. If a fragment has no key, it is always included.
74
74
  const keyedFragments = new Map();
75
75
  for (const [fragment] of sortedFragments) {
76
- if (typeof fragment.merge === "function") {
76
+ if (typeof fragment.mergeAll === "function") {
77
+ if (!fragment.key) {
78
+ throw new Error(
79
+ `InitFragment with mergeAll function must have a valid key: ${fragment.constructor.name}`
80
+ );
81
+ }
82
+ const oldValue = keyedFragments.get(fragment.key);
83
+ if (oldValue === undefined) {
84
+ keyedFragments.set(fragment.key, fragment);
85
+ } else if (Array.isArray(oldValue)) {
86
+ oldValue.push(fragment);
87
+ } else {
88
+ keyedFragments.set(fragment.key, [oldValue, fragment]);
89
+ }
90
+ continue;
91
+ } else if (typeof fragment.merge === "function") {
77
92
  const oldValue = keyedFragments.get(fragment.key);
78
93
  if (oldValue !== undefined) {
79
- keyedFragments.set(
80
- fragment.key || Symbol(),
81
- fragment.merge(oldValue)
82
- );
94
+ keyedFragments.set(fragment.key, fragment.merge(oldValue));
83
95
  continue;
84
96
  }
85
97
  }
@@ -88,7 +100,10 @@ class InitFragment {
88
100
 
89
101
  const concatSource = new ConcatSource();
90
102
  const endContents = [];
91
- for (const fragment of keyedFragments.values()) {
103
+ for (let fragment of keyedFragments.values()) {
104
+ if (Array.isArray(fragment)) {
105
+ fragment = fragment[0].mergeAll(fragment);
106
+ }
92
107
  concatSource.add(fragment.getContent(generateContext));
93
108
  const endContent = fragment.getEndContent(generateContext);
94
109
  if (endContent) {
@@ -25,7 +25,7 @@ const WeakTupleMap = require("./util/WeakTupleMap");
25
25
  * @returns {string}
26
26
  */
27
27
 
28
- const EMPTY_ARRAY = [];
28
+ const EMPTY_SET = new Set();
29
29
 
30
30
  /**
31
31
  * @param {SortableSet<ModuleGraphConnection>} set input
@@ -396,7 +396,7 @@ class ModuleGraph {
396
396
  */
397
397
  getOutgoingConnections(module) {
398
398
  const connections = this._getModuleGraphModule(module).outgoingConnections;
399
- return connections === undefined ? EMPTY_ARRAY : connections;
399
+ return connections === undefined ? EMPTY_SET : connections;
400
400
  }
401
401
 
402
402
  /**
@@ -41,10 +41,12 @@ const { contextify, absolutify } = require("./util/identifier");
41
41
  const makeSerializable = require("./util/makeSerializable");
42
42
  const memoize = require("./util/memoize");
43
43
 
44
- /** @typedef {import("source-map").RawSourceMap} SourceMap */
45
44
  /** @typedef {import("webpack-sources").Source} Source */
45
+ /** @typedef {import("../declarations/LoaderContext").NormalModuleLoaderContext} NormalModuleLoaderContext */
46
+ /** @typedef {import("../declarations/WebpackOptions").Mode} Mode */
46
47
  /** @typedef {import("../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptions */
47
48
  /** @typedef {import("./ChunkGraph")} ChunkGraph */
49
+ /** @typedef {import("./Compiler")} Compiler */
48
50
  /** @typedef {import("./Dependency").UpdateHashContext} UpdateHashContext */
49
51
  /** @typedef {import("./DependencyTemplates")} DependencyTemplates */
50
52
  /** @typedef {import("./Generator")} Generator */
@@ -60,10 +62,22 @@ const memoize = require("./util/memoize");
60
62
  /** @typedef {import("./RequestShortener")} RequestShortener */
61
63
  /** @typedef {import("./ResolverFactory").ResolverWithOptions} ResolverWithOptions */
62
64
  /** @typedef {import("./RuntimeTemplate")} RuntimeTemplate */
65
+ /** @typedef {import("./logging/Logger").Logger} WebpackLogger */
63
66
  /** @typedef {import("./util/Hash")} Hash */
64
67
  /** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */
65
68
  /** @typedef {import("./util/runtime").RuntimeSpec} RuntimeSpec */
66
69
 
70
+ /**
71
+ * @typedef {Object} SourceMap
72
+ * @property {number} version
73
+ * @property {string[]} sources
74
+ * @property {string} mappings
75
+ * @property {string=} file
76
+ * @property {string=} sourceRoot
77
+ * @property {string[]=} sourcesContent
78
+ * @property {string[]=} names
79
+ */
80
+
67
81
  const getInvalidDependenciesModuleWarning = memoize(() =>
68
82
  require("./InvalidDependenciesModuleWarning")
69
83
  );
@@ -421,7 +435,7 @@ class NormalModule extends Module {
421
435
  * @param {WebpackOptions} options webpack options
422
436
  * @param {Compilation} compilation the compilation
423
437
  * @param {InputFileSystem} fs file system from reading
424
- * @returns {any} loader context
438
+ * @returns {NormalModuleLoaderContext} loader context
425
439
  */
426
440
  createLoaderContext(resolver, options, compilation, fs) {
427
441
  const { requestShortener } = compilation.runtimeTemplate;
@@ -520,29 +520,33 @@ class NormalModuleFactory extends ModuleFactory {
520
520
  )
521
521
  );
522
522
  }
523
- Object.assign(data.createData, {
524
- layer:
525
- layer === undefined ? contextInfo.issuerLayer || null : layer,
526
- request: stringifyLoadersAndResource(
527
- allLoaders,
528
- resourceData.resource
529
- ),
530
- userRequest,
531
- rawRequest: request,
532
- loaders: allLoaders,
533
- resource: resourceData.resource,
534
- matchResource: matchResourceData
535
- ? matchResourceData.resource
536
- : undefined,
537
- resourceResolveData: resourceData.data,
538
- settings,
539
- type,
540
- parser: this.getParser(type, settings.parser),
541
- parserOptions: settings.parser,
542
- generator: this.getGenerator(type, settings.generator),
543
- generatorOptions: settings.generator,
544
- resolveOptions
545
- });
523
+ try {
524
+ Object.assign(data.createData, {
525
+ layer:
526
+ layer === undefined ? contextInfo.issuerLayer || null : layer,
527
+ request: stringifyLoadersAndResource(
528
+ allLoaders,
529
+ resourceData.resource
530
+ ),
531
+ userRequest,
532
+ rawRequest: request,
533
+ loaders: allLoaders,
534
+ resource: resourceData.resource,
535
+ matchResource: matchResourceData
536
+ ? matchResourceData.resource
537
+ : undefined,
538
+ resourceResolveData: resourceData.data,
539
+ settings,
540
+ type,
541
+ parser: this.getParser(type, settings.parser),
542
+ parserOptions: settings.parser,
543
+ generator: this.getGenerator(type, settings.generator),
544
+ generatorOptions: settings.generator,
545
+ resolveOptions
546
+ });
547
+ } catch (e) {
548
+ return callback(e);
549
+ }
546
550
  callback();
547
551
  });
548
552
  this.resolveRequestArray(