webpack 5.57.1 → 5.58.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.

@@ -37,6 +37,7 @@ const {
37
37
  keepOriginalOrder
38
38
  } = require("./util/comparators");
39
39
  const createHash = require("./util/createHash");
40
+ const { createFakeHook } = require("./util/deprecation");
40
41
  const { join } = require("./util/fs");
41
42
  const {
42
43
  contextify,
@@ -187,6 +188,7 @@ makeSerializable(
187
188
  * @property {SyncHook<[object, NormalModule]>} loader
188
189
  * @property {SyncHook<[LoaderItem[], NormalModule, object]>} beforeLoaders
189
190
  * @property {HookMap<AsyncSeriesBailHook<[string, NormalModule], string | Buffer>>} readResourceForScheme
191
+ * @property {HookMap<AsyncSeriesBailHook<[object], string | Buffer>>} readResource
190
192
  * @property {AsyncSeriesBailHook<[NormalModule, NeedBuildContext], boolean>} needBuild
191
193
  */
192
194
 
@@ -209,8 +211,28 @@ class NormalModule extends Module {
209
211
  hooks = {
210
212
  loader: new SyncHook(["loaderContext", "module"]),
211
213
  beforeLoaders: new SyncHook(["loaders", "module", "loaderContext"]),
212
- readResourceForScheme: new HookMap(
213
- () => new AsyncSeriesBailHook(["resource", "module"])
214
+ // TODO webpack 6 deprecate
215
+ readResourceForScheme: new HookMap(scheme => {
216
+ const hook = hooks.readResource.for(scheme);
217
+ return createFakeHook(
218
+ /** @type {AsyncSeriesBailHook<[string, NormalModule], string | Buffer>} */ ({
219
+ tap: (options, fn) =>
220
+ hook.tap(options, loaderContext =>
221
+ fn(loaderContext.resource, loaderContext._module)
222
+ ),
223
+ tapAsync: (options, fn) =>
224
+ hook.tapAsync(options, (loaderContext, callback) =>
225
+ fn(loaderContext.resource, loaderContext._module, callback)
226
+ ),
227
+ tapPromise: (options, fn) =>
228
+ hook.tapPromise(options, loaderContext =>
229
+ fn(loaderContext.resource, loaderContext._module)
230
+ )
231
+ })
232
+ );
233
+ }),
234
+ readResource: new HookMap(
235
+ () => new AsyncSeriesBailHook(["loaderContext"])
214
236
  ),
215
237
  needBuild: new AsyncSeriesBailHook(["module", "context"])
216
238
  };
@@ -786,20 +808,15 @@ class NormalModule extends Module {
786
808
  processResource: (loaderContext, resourcePath, callback) => {
787
809
  const resource = loaderContext.resource;
788
810
  const scheme = getScheme(resource);
789
- if (scheme) {
790
- hooks.readResourceForScheme
791
- .for(scheme)
792
- .callAsync(resource, this, (err, result) => {
793
- if (err) return callback(err);
794
- if (typeof result !== "string" && !result) {
795
- return callback(new UnhandledSchemeError(scheme, resource));
796
- }
797
- return callback(null, result);
798
- });
799
- } else {
800
- loaderContext.addDependency(resourcePath);
801
- fs.readFile(resourcePath, callback);
802
- }
811
+ hooks.readResource
812
+ .for(scheme)
813
+ .callAsync(loaderContext, (err, result) => {
814
+ if (err) return callback(err);
815
+ if (typeof result !== "string" && !result) {
816
+ return callback(new UnhandledSchemeError(scheme, resource));
817
+ }
818
+ return callback(null, result);
819
+ });
803
820
  }
804
821
  },
805
822
  (err, result) => {
@@ -43,7 +43,7 @@ const { getEntryRuntime, mergeRuntime } = require("./util/runtime");
43
43
  * @property {boolean} minAvailableModulesOwned true, if minAvailableModules is owned and can be modified
44
44
  * @property {ModuleSetPlus[]} availableModulesToBeMerged enqueued updates to the minimal set of available modules
45
45
  * @property {Set<Module>=} skippedItems modules that were skipped because module is already available in parent chunks (need to reconsider when minAvailableModules is shrinking)
46
- * @property {Set<[Module, ModuleGraphConnection[]]>=} skippedModuleConnections referenced modules that where skipped because they were not active in this runtime
46
+ * @property {Set<[Module, ConnectionState]>=} skippedModuleConnections referenced modules that where skipped because they were not active in this runtime
47
47
  * @property {ModuleSetPlus} resultingAvailableModules set of modules available including modules from this chunk group
48
48
  * @property {Set<ChunkGroupInfo>} children set of children chunk groups, that will be revisited when availableModules shrink
49
49
  * @property {Set<ChunkGroupInfo>} availableSources set of chunk groups that are the source for minAvailableModules
@@ -70,97 +70,106 @@ const bySetSize = (a, b) => {
70
70
  return b.size + b.plus.size - a.size - a.plus.size;
71
71
  };
72
72
 
73
- /**
74
- *
75
- * @param {ModuleGraphConnection[]} connections list of connections
76
- * @param {RuntimeSpec} runtime for which runtime
77
- * @returns {ConnectionState} connection state
78
- */
79
- const getActiveStateOfConnections = (connections, runtime) => {
80
- let merged = connections[0].getActiveState(runtime);
81
- if (merged === true) return true;
82
- for (let i = 1; i < connections.length; i++) {
83
- const c = connections[i];
84
- merged = ModuleGraphConnection.addConnectionStates(
85
- merged,
86
- c.getActiveState(runtime)
87
- );
88
- if (merged === true) return true;
73
+ const extractBlockModules = (module, moduleGraph, runtime, blockModulesMap) => {
74
+ let blockCache;
75
+ let modules;
76
+
77
+ const arrays = [];
78
+
79
+ const queue = [module];
80
+ while (queue.length > 0) {
81
+ const block = queue.pop();
82
+ const arr = [];
83
+ arrays.push(arr);
84
+ blockModulesMap.set(block, arr);
85
+ for (const b of block.blocks) {
86
+ queue.push(b);
87
+ }
89
88
  }
90
- return merged;
91
- };
92
89
 
93
- /**
94
- * Extracts block to modules mapping from all modules
95
- * @param {Compilation} compilation the compilation
96
- * @returns {Map<DependenciesBlock, Map<Module, ModuleGraphConnection[]>>} the mapping block to modules
97
- */
98
- const extractBlockModulesMap = compilation => {
99
- const { moduleGraph } = compilation;
100
-
101
- /** @type {Map<DependenciesBlock, Map<Module, ModuleGraphConnection[]>>} */
102
- const blockModulesMap = new Map();
103
-
104
- const blockQueue = new Set();
105
-
106
- for (const module of compilation.modules) {
107
- /** @type {WeakMap<Dependency, ModuleGraphConnection>} */
108
- let moduleMap;
109
-
110
- for (const connection of moduleGraph.getOutgoingConnections(module)) {
111
- const d = connection.dependency;
112
- // We skip connections without dependency
113
- if (!d) continue;
114
- const m = connection.module;
115
- // We skip connections without Module pointer
116
- if (!m) continue;
117
- // We skip weak connections
118
- if (connection.weak) continue;
119
- const state = connection.getActiveState(undefined);
120
- // We skip inactive connections
121
- if (state === false) continue;
122
- // Store Dependency to Module mapping in local map
123
- // to allow to access it faster compared to
124
- // moduleGraph.getConnection()
125
- if (moduleMap === undefined) {
126
- moduleMap = new WeakMap();
127
- }
128
- moduleMap.set(connection.dependency, connection);
90
+ for (const connection of moduleGraph.getOutgoingConnections(module)) {
91
+ const d = connection.dependency;
92
+ // We skip connections without dependency
93
+ if (!d) continue;
94
+ const m = connection.module;
95
+ // We skip connections without Module pointer
96
+ if (!m) continue;
97
+ // We skip weak connections
98
+ if (connection.weak) continue;
99
+ const state = connection.getActiveState(runtime);
100
+ // We skip inactive connections
101
+ if (state === false) continue;
102
+
103
+ const block = moduleGraph.getParentBlock(d);
104
+ let index = moduleGraph.getParentBlockIndex(d);
105
+
106
+ // deprecated fallback
107
+ if (index < 0) {
108
+ index = block.dependencies.indexOf(d);
129
109
  }
130
110
 
131
- blockQueue.clear();
132
- blockQueue.add(module);
133
- for (const block of blockQueue) {
134
- let modules;
135
-
136
- if (moduleMap !== undefined && block.dependencies) {
137
- for (const dep of block.dependencies) {
138
- const connection = moduleMap.get(dep);
139
- if (connection !== undefined) {
140
- const { module } = connection;
141
- if (modules === undefined) {
142
- modules = new Map();
143
- blockModulesMap.set(block, modules);
144
- }
145
- const old = modules.get(module);
146
- if (old !== undefined) {
147
- old.push(connection);
148
- } else {
149
- modules.set(module, [connection]);
150
- }
111
+ if (blockCache !== block) {
112
+ modules = blockModulesMap.get((blockCache = block));
113
+ }
114
+
115
+ const i = index << 2;
116
+ modules[i] = m;
117
+ modules[i + 1] = state;
118
+ }
119
+
120
+ for (const modules of arrays) {
121
+ if (modules.length === 0) continue;
122
+ let indexMap;
123
+ let length = 0;
124
+ outer: for (let j = 0; j < modules.length; j += 2) {
125
+ const m = modules[j];
126
+ if (m === undefined) continue;
127
+ const state = modules[j + 1];
128
+ if (indexMap === undefined) {
129
+ let i = 0;
130
+ for (; i < length; i += 2) {
131
+ if (modules[i] === m) {
132
+ const merged = modules[i + 1];
133
+ if (merged === true) continue outer;
134
+ modules[i + 1] = ModuleGraphConnection.addConnectionStates(
135
+ merged,
136
+ state
137
+ );
151
138
  }
152
139
  }
153
- }
154
-
155
- if (block.blocks) {
156
- for (const b of block.blocks) {
157
- blockQueue.add(b);
140
+ modules[length] = m;
141
+ length++;
142
+ modules[length] = state;
143
+ length++;
144
+ if (length > 30) {
145
+ // To avoid worse case performance, we will use an index map for
146
+ // linear cost access, which allows to maintain O(n) complexity
147
+ // while keeping allocations down to a minimum
148
+ indexMap = new Map();
149
+ for (let i = 0; i < length; i += 2) {
150
+ indexMap.set(modules[i], i + 1);
151
+ }
152
+ }
153
+ } else {
154
+ const idx = indexMap.get(m);
155
+ if (idx !== undefined) {
156
+ const merged = modules[idx];
157
+ if (merged === true) continue outer;
158
+ modules[idx] = ModuleGraphConnection.addConnectionStates(
159
+ merged,
160
+ state
161
+ );
162
+ } else {
163
+ modules[length] = m;
164
+ length++;
165
+ modules[length] = state;
166
+ indexMap.set(m, length);
167
+ length++;
158
168
  }
159
169
  }
160
170
  }
171
+ modules.length = length;
161
172
  }
162
-
163
- return blockModulesMap;
164
173
  };
165
174
 
166
175
  /**
@@ -182,10 +191,55 @@ const visitModules = (
182
191
  blocksWithNestedBlocks,
183
192
  allCreatedChunkGroups
184
193
  ) => {
185
- const { moduleGraph, chunkGraph } = compilation;
194
+ const { moduleGraph, chunkGraph, moduleMemCaches } = compilation;
186
195
 
187
- logger.time("visitModules: prepare");
188
- const blockModulesMap = extractBlockModulesMap(compilation);
196
+ const blockModulesRuntimeMap = new Map();
197
+
198
+ /** @type {RuntimeSpec | false} */
199
+ let blockModulesMapRuntime = false;
200
+ let blockModulesMap;
201
+
202
+ /**
203
+ *
204
+ * @param {DependenciesBlock} block block
205
+ * @param {RuntimeSpec} runtime runtime
206
+ * @returns {(Module | ConnectionState)[]} block modules in flatten tuples
207
+ */
208
+ const getBlockModules = (block, runtime) => {
209
+ if (blockModulesMapRuntime !== runtime) {
210
+ blockModulesMap = blockModulesRuntimeMap.get(runtime);
211
+ if (blockModulesMap === undefined) {
212
+ blockModulesMap = new Map();
213
+ blockModulesRuntimeMap.set(runtime, blockModulesMap);
214
+ }
215
+ }
216
+ let blockModules = blockModulesMap.get(block);
217
+ if (blockModules !== undefined) return blockModules;
218
+ const module = /** @type {Module} */ (block.getRootBlock());
219
+ const memCache = moduleMemCaches && moduleMemCaches.get(module);
220
+ if (memCache !== undefined) {
221
+ const map = memCache.provide(
222
+ "bundleChunkGraph.blockModules",
223
+ runtime,
224
+ () => {
225
+ logger.time("visitModules: prepare");
226
+ const map = new Map();
227
+ extractBlockModules(module, moduleGraph, runtime, map);
228
+ logger.timeAggregate("visitModules: prepare");
229
+ return map;
230
+ }
231
+ );
232
+ for (const [block, blockModules] of map)
233
+ blockModulesMap.set(block, blockModules);
234
+ return map.get(block);
235
+ } else {
236
+ logger.time("visitModules: prepare");
237
+ extractBlockModules(module, moduleGraph, runtime, blockModulesMap);
238
+ blockModules = blockModulesMap.get(block);
239
+ logger.timeAggregate("visitModules: prepare");
240
+ return blockModules;
241
+ }
242
+ };
189
243
 
190
244
  let statProcessedQueueItems = 0;
191
245
  let statProcessedBlocks = 0;
@@ -308,9 +362,7 @@ const visitModules = (
308
362
  /** @type {QueueItem[]} */
309
363
  let queueDelayed = [];
310
364
 
311
- logger.timeEnd("visitModules: prepare");
312
-
313
- /** @type {[Module, ModuleGraphConnection[]][]} */
365
+ /** @type {[Module, ConnectionState][]} */
314
366
  const skipConnectionBuffer = [];
315
367
  /** @type {Module[]} */
316
368
  const skipBuffer = [];
@@ -478,21 +530,23 @@ const visitModules = (
478
530
  const processBlock = block => {
479
531
  statProcessedBlocks++;
480
532
  // get prepared block info
481
- const blockModules = blockModulesMap.get(block);
533
+ const blockModules = getBlockModules(block, chunkGroupInfo.runtime);
482
534
 
483
535
  if (blockModules !== undefined) {
484
- const { minAvailableModules, runtime } = chunkGroupInfo;
536
+ const { minAvailableModules } = chunkGroupInfo;
485
537
  // Buffer items because order need to be reversed to get indices correct
486
538
  // Traverse all referenced modules
487
- for (const entry of blockModules) {
488
- const [refModule, connections] = entry;
539
+ for (let i = 0; i < blockModules.length; i += 2) {
540
+ const refModule = /** @type {Module} */ (blockModules[i]);
489
541
  if (chunkGraph.isModuleInChunk(refModule, chunk)) {
490
542
  // skip early if already connected
491
543
  continue;
492
544
  }
493
- const activeState = getActiveStateOfConnections(connections, runtime);
545
+ const activeState = /** @type {ConnectionState} */ (
546
+ blockModules[i + 1]
547
+ );
494
548
  if (activeState !== true) {
495
- skipConnectionBuffer.push(entry);
549
+ skipConnectionBuffer.push([refModule, activeState]);
496
550
  if (activeState === false) continue;
497
551
  }
498
552
  if (
@@ -562,12 +616,15 @@ const visitModules = (
562
616
  const processEntryBlock = block => {
563
617
  statProcessedBlocks++;
564
618
  // get prepared block info
565
- const blockModules = blockModulesMap.get(block);
619
+ const blockModules = getBlockModules(block, chunkGroupInfo.runtime);
566
620
 
567
621
  if (blockModules !== undefined) {
568
622
  // Traverse all referenced modules
569
- for (const [refModule, connections] of blockModules) {
570
- const activeState = getActiveStateOfConnections(connections, undefined);
623
+ for (let i = 0; i < blockModules.length; i += 2) {
624
+ const refModule = /** @type {Module} */ (blockModules[i]);
625
+ const activeState = /** @type {ConnectionState} */ (
626
+ blockModules[i + 1]
627
+ );
571
628
  // enqueue, then add and enter to be in the correct order
572
629
  // this is relevant with circular dependencies
573
630
  queueBuffer.push({
@@ -1059,10 +1116,9 @@ const visitModules = (
1059
1116
 
1060
1117
  // 2. Reconsider skipped connections
1061
1118
  if (info.skippedModuleConnections !== undefined) {
1062
- const { minAvailableModules, runtime } = info;
1119
+ const { minAvailableModules } = info;
1063
1120
  for (const entry of info.skippedModuleConnections) {
1064
- const [module, connections] = entry;
1065
- const activeState = getActiveStateOfConnections(connections, runtime);
1121
+ const [module, activeState] = entry;
1066
1122
  if (activeState === false) continue;
1067
1123
  if (activeState === true) {
1068
1124
  info.skippedModuleConnections.delete(entry);
@@ -1114,6 +1170,7 @@ const visitModules = (
1114
1170
  while (queue.length || queueConnect.size) {
1115
1171
  logger.time("visitModules: visiting");
1116
1172
  processQueue();
1173
+ logger.timeAggregateEnd("visitModules: prepare");
1117
1174
  logger.timeEnd("visitModules: visiting");
1118
1175
 
1119
1176
  if (chunkGroupsForCombining.size > 0) {
@@ -155,6 +155,7 @@ class WebpackLogger {
155
155
  if (this[TIMERS_AGGREGATES_SYMBOL] === undefined) return;
156
156
  const time = this[TIMERS_AGGREGATES_SYMBOL].get(label);
157
157
  if (time === undefined) return;
158
+ this[TIMERS_AGGREGATES_SYMBOL].delete(label);
158
159
  this[LOG_SYMBOL](LogType.time, [label, ...time]);
159
160
  }
160
161
  }
@@ -19,6 +19,7 @@ const builtins = [
19
19
  "constants",
20
20
  "crypto",
21
21
  "dgram",
22
+ "diagnostics_channel",
22
23
  "dns",
23
24
  "dns/promises",
24
25
  "domain",
@@ -30,6 +30,7 @@ class EnsureChunkConditionsPlugin {
30
30
  /** @type {Set<ChunkGroup>} */
31
31
  const chunkGroups = new Set();
32
32
  for (const module of compilation.modules) {
33
+ if (!module.hasChunkCondition()) continue;
33
34
  for (const chunk of chunkGraph.getModuleChunksIterable(module)) {
34
35
  if (!module.chunkCondition(chunk, compilation)) {
35
36
  sourceChunks.add(chunk);