webpack 5.100.0 → 5.100.2

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.
@@ -292,7 +292,7 @@ const { isSourceEqual } = require("./util/source");
292
292
  * @property {boolean=} development true, when asset is only used for development and doesn't count towards user-facing assets
293
293
  * @property {boolean=} hotModuleReplacement true, when asset ships data for updating an existing application (HMR)
294
294
  * @property {boolean=} javascriptModule true, when asset is javascript and an ESM
295
- * @property {Record<string, string | string[]>=} related object of pointers to other assets, keyed by type of relation (only points from parent to child)
295
+ * @property {Record<string, null | string | string[]>=} related object of pointers to other assets, keyed by type of relation (only points from parent to child)
296
296
  */
297
297
 
298
298
  /** @typedef {KnownAssetInfo & Record<string, EXPECTED_ANY>} AssetInfo */
package/lib/Dependency.js CHANGED
@@ -85,9 +85,11 @@ const memoize = require("./util/memoize");
85
85
 
86
86
  const TRANSITIVE = Symbol("transitive");
87
87
 
88
- const getIgnoredModule = memoize(
89
- () => new RawModule("/* (ignored) */", "ignored", "(ignored)")
90
- );
88
+ const getIgnoredModule = memoize(() => {
89
+ const module = new RawModule("/* (ignored) */", "ignored", "(ignored)");
90
+ module.factoryMeta = { sideEffectFree: true };
91
+ return module;
92
+ });
91
93
 
92
94
  class Dependency {
93
95
  constructor() {
@@ -80,11 +80,14 @@ class IgnorePlugin {
80
80
  resolveData.dependencies.length > 0 &&
81
81
  resolveData.dependencies[0] instanceof EntryDependency
82
82
  ) {
83
- resolveData.ignoredModule = new RawModule(
83
+ const module = new RawModule(
84
84
  "",
85
85
  "ignored-entry-module",
86
86
  "(ignored-entry-module)"
87
87
  );
88
+ module.factoryMeta = { sideEffectFree: true };
89
+
90
+ resolveData.ignoredModule = module;
88
91
  }
89
92
 
90
93
  return result;
@@ -10,6 +10,7 @@ const ExportsInfo = require("./ExportsInfo");
10
10
  const ModuleGraphConnection = require("./ModuleGraphConnection");
11
11
  const SortableSet = require("./util/SortableSet");
12
12
  const WeakTupleMap = require("./util/WeakTupleMap");
13
+ const { sortWithSourceOrder } = require("./util/comparators");
13
14
 
14
15
  /** @typedef {import("./Compilation").ModuleMemCaches} ModuleMemCaches */
15
16
  /** @typedef {import("./DependenciesBlock")} DependenciesBlock */
@@ -19,6 +20,9 @@ const WeakTupleMap = require("./util/WeakTupleMap");
19
20
  /** @typedef {import("./ModuleProfile")} ModuleProfile */
20
21
  /** @typedef {import("./RequestShortener")} RequestShortener */
21
22
  /** @typedef {import("./util/runtime").RuntimeSpec} RuntimeSpec */
23
+ /** @typedef {import("./dependencies/HarmonyImportSideEffectDependency")} HarmonyImportSideEffectDependency */
24
+ /** @typedef {import("./dependencies/HarmonyImportSpecifierDependency")} HarmonyImportSpecifierDependency */
25
+ /** @typedef {import("./util/comparators").DependencySourceOrder} DependencySourceOrder */
22
26
 
23
27
  /**
24
28
  * @callback OptimizationBailoutFunction
@@ -158,6 +162,12 @@ class ModuleGraph {
158
162
  * @private
159
163
  */
160
164
  this._cacheStage = undefined;
165
+
166
+ /**
167
+ * @type {WeakMap<Dependency, DependencySourceOrder>}
168
+ * @private
169
+ */
170
+ this._dependencySourceOrderMap = new WeakMap();
161
171
  }
162
172
 
163
173
  /**
@@ -186,6 +196,15 @@ class ModuleGraph {
186
196
  dependency._parentModule = module;
187
197
  }
188
198
 
199
+ /**
200
+ * @param {Dependency} dependency the dependency
201
+ * @param {number} index the index
202
+ * @returns {void}
203
+ */
204
+ setParentDependenciesBlockIndex(dependency, index) {
205
+ dependency._parentDependenciesBlockIndex = index;
206
+ }
207
+
189
208
  /**
190
209
  * @param {Dependency} dependency the dependency
191
210
  * @returns {Module | undefined} parent module
@@ -265,6 +284,64 @@ class ModuleGraph {
265
284
  targetMgm.incomingConnections.add(newConnection);
266
285
  }
267
286
 
287
+ /**
288
+ * @param {Dependency} dependency the need update dependency
289
+ * @param {ModuleGraphConnection=} connection the target connection
290
+ * @param {Module=} parentModule the parent module
291
+ * @returns {void}
292
+ */
293
+ updateParent(dependency, connection, parentModule) {
294
+ if (this._dependencySourceOrderMap.has(dependency)) {
295
+ return;
296
+ }
297
+ if (!connection || !parentModule) {
298
+ return;
299
+ }
300
+ const originDependency = connection.dependency;
301
+
302
+ // src/index.js
303
+ // import { c } from "lib/c" -> c = 0
304
+ // import { a, b } from "lib" -> a and b have the same source order -> a = b = 1
305
+ // import { d } from "lib/d" -> d = 2
306
+ const currentSourceOrder =
307
+ /** @type { HarmonyImportSideEffectDependency | HarmonyImportSpecifierDependency} */ (
308
+ dependency
309
+ ).sourceOrder;
310
+
311
+ // lib/index.js (reexport)
312
+ // import { a } from "lib/a" -> a = 0
313
+ // import { b } from "lib/b" -> b = 1
314
+ const originSourceOrder =
315
+ /** @type { HarmonyImportSideEffectDependency | HarmonyImportSpecifierDependency} */ (
316
+ originDependency
317
+ ).sourceOrder;
318
+ if (
319
+ typeof currentSourceOrder === "number" &&
320
+ typeof originSourceOrder === "number"
321
+ ) {
322
+ // src/index.js
323
+ // import { c } from "lib/c" -> c = 0
324
+ // import { a } from "lib/a" -> a = 1.0 = 1(main) + 0.0(sub)
325
+ // import { b } from "lib/b" -> b = 1.1 = 1(main) + 0.1(sub)
326
+ // import { d } from "lib/d" -> d = 2
327
+ this._dependencySourceOrderMap.set(dependency, {
328
+ main: currentSourceOrder,
329
+ sub: originSourceOrder
330
+ });
331
+
332
+ // If dependencies like HarmonyImportSideEffectDependency and HarmonyImportSpecifierDependency have a SourceOrder,
333
+ // we sort based on it; otherwise, we preserve the original order.
334
+ sortWithSourceOrder(
335
+ parentModule.dependencies,
336
+ this._dependencySourceOrderMap
337
+ );
338
+
339
+ for (const [index, dep] of parentModule.dependencies.entries()) {
340
+ this.setParentDependenciesBlockIndex(dep, index);
341
+ }
342
+ }
343
+ }
344
+
268
345
  /**
269
346
  * @param {Dependency} dependency the referencing dependency
270
347
  * @returns {void}
@@ -40,7 +40,8 @@ const {
40
40
  compareLocations,
41
41
  compareSelect,
42
42
  concatComparators,
43
- keepOriginalOrder
43
+ keepOriginalOrder,
44
+ sortWithSourceOrder
44
45
  } = require("./util/comparators");
45
46
  const createHash = require("./util/createHash");
46
47
  const { createFakeHook } = require("./util/deprecation");
@@ -99,6 +100,8 @@ const memoize = require("./util/memoize");
99
100
  /** @typedef {import("./util/runtime").RuntimeSpec} RuntimeSpec */
100
101
  /** @typedef {import("../declarations/WebpackOptions").HashFunction} HashFunction */
101
102
  /** @typedef {import("./util/identifier").AssociatedObjectForCache} AssociatedObjectForCache */
103
+ /** @typedef {import("./dependencies/HarmonyImportSideEffectDependency")} HarmonyImportSideEffectDependency */
104
+ /** @typedef {import("./dependencies/HarmonyImportSpecifierDependency")} HarmonyImportSpecifierDependency */
102
105
  /**
103
106
  * @template T
104
107
  * @typedef {import("./util/deprecation").FakeHook<T>} FakeHook
@@ -1221,6 +1224,7 @@ class NormalModule extends Module {
1221
1224
  keepOriginalOrder(this.dependencies)
1222
1225
  )
1223
1226
  );
1227
+ sortWithSourceOrder(this.dependencies, new WeakMap());
1224
1228
  this._initBuildHash(compilation);
1225
1229
  this._lastSuccessfulBuildMeta =
1226
1230
  /** @type {BuildMeta} */
@@ -572,8 +572,11 @@ class NormalModuleFactory extends ModuleFactory {
572
572
 
573
573
  /** @type {ModuleSettings} */
574
574
  const settings = {};
575
+ /** @type {LoaderItem[]} */
575
576
  const useLoadersPost = [];
577
+ /** @type {LoaderItem[]} */
576
578
  const useLoaders = [];
579
+ /** @type {LoaderItem[]} */
577
580
  const useLoadersPre = [];
578
581
 
579
582
  // handle .webpack[] suffix
@@ -632,7 +635,8 @@ class NormalModuleFactory extends ModuleFactory {
632
635
  typeof r.value === "object" &&
633
636
  r.value !== null &&
634
637
  typeof settings[
635
- /** @type {keyof ModuleSettings} */ (r.type)
638
+ /** @type {keyof ModuleSettings} */
639
+ (r.type)
636
640
  ] === "object" &&
637
641
  settings[/** @type {keyof ModuleSettings} */ (r.type)] !== null
638
642
  ) {
package/lib/RawModule.js CHANGED
@@ -24,6 +24,8 @@ const makeSerializable = require("./util/makeSerializable");
24
24
  /** @typedef {import("./Module").NeedBuildCallback} NeedBuildCallback */
25
25
  /** @typedef {import("./Module").NeedBuildContext} NeedBuildContext */
26
26
  /** @typedef {import("./Module").ReadOnlyRuntimeRequirements} ReadOnlyRuntimeRequirements */
27
+ /** @typedef {import("./ModuleGraph")} ModuleGraph */
28
+ /** @typedef {import("./ModuleGraphConnection").ConnectionState} ConnectionState */
27
29
  /** @typedef {import("./RequestShortener")} RequestShortener */
28
30
  /** @typedef {import("./ResolverFactory").ResolverWithOptions} ResolverWithOptions */
29
31
  /** @typedef {import("./RuntimeTemplate")} RuntimeTemplate */
@@ -105,6 +107,18 @@ class RawModule extends Module {
105
107
  callback();
106
108
  }
107
109
 
110
+ /**
111
+ * @param {ModuleGraph} moduleGraph the module graph
112
+ * @returns {ConnectionState} how this module should be connected to referencing modules when consumed for side-effects only
113
+ */
114
+ getSideEffectsConnectionState(moduleGraph) {
115
+ if (this.factoryMeta !== undefined) {
116
+ if (this.factoryMeta.sideEffectFree) return false;
117
+ if (this.factoryMeta.sideEffectFree === false) return true;
118
+ }
119
+ return true;
120
+ }
121
+
108
122
  /**
109
123
  * @param {CodeGenerationContext} context context for code generation
110
124
  * @returns {CodeGenerationResult} result
@@ -8,6 +8,9 @@
8
8
  const InitFragment = require("./InitFragment");
9
9
  const RuntimeGlobals = require("./RuntimeGlobals");
10
10
  const Template = require("./Template");
11
+ const {
12
+ getOutgoingAsyncModules
13
+ } = require("./async-modules/AsyncModuleHelpers");
11
14
  const {
12
15
  getMakeDeferredNamespaceModeFromExportsType,
13
16
  getOptimizedDeferredModule
@@ -814,27 +817,12 @@ class RuntimeTemplate {
814
817
  ];
815
818
  }
816
819
 
817
- /** @type {Set<Module>} */
818
- const innerAsyncDependencies = new Set();
819
820
  defer = defer && (module.buildMeta ? !module.buildMeta.async : true);
820
821
 
821
- if (this.compilation.options.experiments.deferImport && defer) {
822
- const seen = new Set();
823
- (function gatherInnerAsyncDependencies(mod) {
824
- if (!moduleGraph.isAsync(mod) || seen.has(mod)) return;
825
- seen.add(mod);
826
- if (mod.buildMeta && mod.buildMeta.async) {
827
- innerAsyncDependencies.add(mod);
828
- } else {
829
- for (const dep of mod.dependencies) {
830
- const module = moduleGraph.getModule(dep);
831
- if (module) {
832
- gatherInnerAsyncDependencies(module);
833
- }
834
- }
835
- }
836
- })(module);
837
- }
822
+ /** @type {Set<Module>} */
823
+ const outgoingAsyncModules = defer
824
+ ? getOutgoingAsyncModules(moduleGraph, module)
825
+ : new Set();
838
826
 
839
827
  if (chunkGraph.getModuleId(module) === null) {
840
828
  if (weak) {
@@ -877,13 +865,14 @@ class RuntimeTemplate {
877
865
  this,
878
866
  exportsType,
879
867
  moduleId,
880
- Array.from(innerAsyncDependencies, mod => chunkGraph.getModuleId(mod))
868
+ Array.from(outgoingAsyncModules, mod => chunkGraph.getModuleId(mod))
881
869
  )};\n`;
882
- } else {
883
- importContent = `/* harmony import */ ${optDeclaration}${importVar} = ${RuntimeGlobals.require}(${moduleId});\n`;
870
+
871
+ return [importContent, ""];
884
872
  }
873
+ importContent = `/* harmony import */ ${optDeclaration}${importVar} = ${RuntimeGlobals.require}(${moduleId});\n`;
885
874
 
886
- if (exportsType === "dynamic" && !defer) {
875
+ if (exportsType === "dynamic") {
887
876
  runtimeRequirements.add(RuntimeGlobals.compatGetDefaultExport);
888
877
  return [
889
878
  importContent,
@@ -438,6 +438,13 @@ class WebpackOptionsApply extends OptionsApply {
438
438
  new HttpUriPlugin(httpOptions).apply(compiler);
439
439
  }
440
440
 
441
+ if (options.experiments.deferImport) {
442
+ const JavascriptParser = require("./javascript/JavascriptParser");
443
+ const importPhases = require("acorn-import-phases");
444
+
445
+ JavascriptParser.extend(importPhases({ source: false }));
446
+ }
447
+
441
448
  new EntryOptionPlugin().apply(compiler);
442
449
  compiler.hooks.entryOption.call(
443
450
  /** @type {string} */
@@ -57,8 +57,8 @@ const nonNumericOnlyHash = require("../util/nonNumericOnlyHash");
57
57
  /**
58
58
  * @template T
59
59
  * @template U
60
- * @param {string | Array<T> | Set<T> | undefined} a a
61
- * @param {string | Array<U> | Set<U> | undefined} b b
60
+ * @param {null | string | Array<T> | Set<T> | undefined} a a
61
+ * @param {null | string | Array<U> | Set<U> | undefined} b b
62
62
  * @returns {Array<T> & Array<U>} array
63
63
  */
64
64
  const mergeMaybeArrays = (a, b) => {
@@ -0,0 +1,50 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ Author Haijie Xie @hai-x
4
+ */
5
+
6
+ "use strict";
7
+
8
+ const HarmonyImportDependency = require("../dependencies/HarmonyImportDependency");
9
+
10
+ /** @typedef {import("../ModuleGraph")} ModuleGraph */
11
+ /** @typedef {import("../Module")} Module */
12
+
13
+ /**
14
+ * @param {ModuleGraph} moduleGraph module graph
15
+ * @param {Module} module module
16
+ * @returns {Set<Module>} set of modules
17
+ */
18
+ const getOutgoingAsyncModules = (moduleGraph, module) => {
19
+ /** @type {Set<Module>} */
20
+ const set = new Set();
21
+ /** @type {Set<Module>} */
22
+ const seen = new Set();
23
+ (function g(/** @type {Module} */ module) {
24
+ if (!moduleGraph.isAsync(module) || seen.has(module)) return;
25
+ seen.add(module);
26
+ if (module.buildMeta && module.buildMeta.async) {
27
+ set.add(module);
28
+ } else {
29
+ const outgoingConnectionMap =
30
+ moduleGraph.getOutgoingConnectionsByModule(module);
31
+ if (outgoingConnectionMap) {
32
+ for (const [module, connections] of outgoingConnectionMap) {
33
+ if (
34
+ connections.some(
35
+ c =>
36
+ c.dependency instanceof HarmonyImportDependency &&
37
+ c.isTargetActive(undefined)
38
+ ) &&
39
+ module
40
+ ) {
41
+ g(module);
42
+ }
43
+ }
44
+ }
45
+ }
46
+ })(module);
47
+ return set;
48
+ };
49
+
50
+ module.exports.getOutgoingAsyncModules = getOutgoingAsyncModules;
@@ -77,12 +77,7 @@ module.exports = class HarmonyExportDependencyParserPlugin {
77
77
  clearDep.loc = /** @type {DependencyLocation} */ (statement.loc);
78
78
  clearDep.loc.index = -1;
79
79
  parser.state.module.addPresentationalDependency(clearDep);
80
- const { defer } = getImportMode(
81
- parser,
82
- statement,
83
- this.deferImport,
84
- true
85
- );
80
+ const { defer } = getImportMode(parser, statement);
86
81
  if (defer) {
87
82
  const error = new WebpackError(
88
83
  "Deferred re-export (`export defer * as namespace from '...'`) is not a part of the Import Defer proposal.\nUse the following code instead:\n import defer * as namespace from '...';\n export { namespace };"
@@ -207,12 +202,7 @@ module.exports = class HarmonyExportDependencyParserPlugin {
207
202
  parser.state.harmonyStarExports || new HarmonyStarExportsList();
208
203
  }
209
204
  const attributes = getImportAttributes(statement);
210
- const { defer } = getImportMode(
211
- parser,
212
- statement,
213
- this.deferImport,
214
- false
215
- );
205
+ const { defer } = getImportMode(parser, statement);
216
206
  const dep = new HarmonyExportImportedSpecifierDependency(
217
207
  /** @type {string} */
218
208
  (source),
@@ -7,7 +7,6 @@
7
7
 
8
8
  const CommentCompilationWarning = require("../CommentCompilationWarning");
9
9
  const HotModuleReplacementPlugin = require("../HotModuleReplacementPlugin");
10
- const UnsupportedFeatureWarning = require("../UnsupportedFeatureWarning");
11
10
  const WebpackError = require("../WebpackError");
12
11
  const { getImportAttributes } = require("../javascript/JavascriptParser");
13
12
  const InnerGraph = require("../optimize/InnerGraph");
@@ -125,12 +124,7 @@ module.exports = class HarmonyImportDependencyParserPlugin {
125
124
  parser.state.module.addPresentationalDependency(clearDep);
126
125
  parser.unsetAsiPosition(/** @type {Range} */ (statement.range)[1]);
127
126
  const attributes = getImportAttributes(statement);
128
- const { defer } = getImportMode(
129
- parser,
130
- statement,
131
- this.deferImport,
132
- true
133
- );
127
+ const { defer } = getImportMode(parser, statement);
134
128
  if (
135
129
  defer &&
136
130
  (statement.specifiers.length !== 1 ||
@@ -156,12 +150,7 @@ module.exports = class HarmonyImportDependencyParserPlugin {
156
150
  PLUGIN_NAME,
157
151
  (statement, source, id, name) => {
158
152
  const ids = id === null ? [] : [id];
159
- const { defer } = getImportMode(
160
- parser,
161
- statement,
162
- this.deferImport,
163
- false
164
- );
153
+ const { defer } = getImportMode(parser, statement);
165
154
  parser.tagVariable(name, harmonySpecifierTag, {
166
155
  name,
167
156
  source,
@@ -398,23 +387,10 @@ module.exports = class HarmonyImportDependencyParserPlugin {
398
387
  /**
399
388
  * @param {JavascriptParser} parser parser
400
389
  * @param {ExportNamedDeclaration | ExportAllDeclaration | ImportDeclaration} node node
401
- * @param {boolean | undefined} deferImportEnabled defer import enabled
402
- * @param {boolean} reportSyntaxError report syntax error
403
390
  * @returns {{defer: boolean}} import attributes
404
391
  */
405
- function getImportMode(parser, node, deferImportEnabled, reportSyntaxError) {
406
- const result = { defer: false };
407
- if ("phase" in node && node.phase === "defer") {
408
- if (deferImportEnabled) {
409
- result.defer = true;
410
- } else if (reportSyntaxError) {
411
- const error = new WebpackError(
412
- "Deferred import syntax (`import defer * as namespace from '...'`) cannot be used unless experimental.deferImport is true."
413
- );
414
- error.loc = node.loc || undefined;
415
- parser.state.current.addError(error);
416
- }
417
- }
392
+ function getImportMode(parser, node) {
393
+ const result = { defer: "phase" in node && node.phase === "defer" };
418
394
  if (!node.range) {
419
395
  return result;
420
396
  }
@@ -437,7 +413,7 @@ function getImportMode(parser, node, deferImportEnabled, reportSyntaxError) {
437
413
  result.defer = options.webpackDefer;
438
414
  } else if (node.loc) {
439
415
  parser.state.module.addWarning(
440
- new UnsupportedFeatureWarning(
416
+ new CommentCompilationWarning(
441
417
  "webpackDefer magic comment expected a boolean value.",
442
418
  node.loc
443
419
  )
@@ -61,11 +61,13 @@ class ModuleDependency extends Dependency {
61
61
  * @returns {Module} ignored module
62
62
  */
63
63
  createIgnoredModule(context) {
64
- return new RawModule(
64
+ const module = new RawModule(
65
65
  "/* (ignored) */",
66
66
  `ignored|${context}|${this.request}`,
67
67
  `${this.request} (ignored)`
68
68
  );
69
+ module.factoryMeta = { sideEffectFree: true };
70
+ return module;
69
71
  }
70
72
 
71
73
  /**
@@ -7,7 +7,6 @@
7
7
 
8
8
  const vm = require("vm");
9
9
  const { Parser: AcornParser, tokTypes } = require("acorn");
10
- const acornImportPhases = require("acorn-import-phases");
11
10
  const { HookMap, SyncBailHook } = require("tapable");
12
11
  const Parser = require("../Parser");
13
12
  const StackedMap = require("../util/StackedMap");
@@ -182,10 +181,7 @@ const importAssertions = Parser =>
182
181
  };
183
182
 
184
183
  // Syntax: https://developer.mozilla.org/en/SpiderMonkey/Parser_API
185
- const parser = AcornParser.extend(
186
- importAssertions,
187
- acornImportPhases({ source: false })
188
- );
184
+ let parser = AcornParser.extend(importAssertions);
189
185
 
190
186
  /** @typedef {Record<string, string> & { _isLegacyAssert?: boolean }} ImportAttributes */
191
187
 
@@ -5135,6 +5131,15 @@ class JavascriptParser extends Parser {
5135
5131
 
5136
5132
  return /** @type {Program} */ (ast);
5137
5133
  }
5134
+
5135
+ /**
5136
+ * @param {((BaseParser: typeof AcornParser) => typeof AcornParser)[]} plugins parser plugin
5137
+ * @returns {typeof JavascriptParser} parser
5138
+ */
5139
+ static extend(...plugins) {
5140
+ parser = parser.extend(...plugins);
5141
+ return JavascriptParser;
5142
+ }
5138
5143
  }
5139
5144
 
5140
5145
  module.exports = JavascriptParser;
@@ -320,8 +320,17 @@ class SideEffectsFlagPlugin {
320
320
  ({ module }) =>
321
321
  module.getSideEffectsConnectionState(moduleGraph) ===
322
322
  false,
323
- ({ module: newModule, export: exportName }) => {
323
+ ({
324
+ module: newModule,
325
+ export: exportName,
326
+ connection: targetConnection
327
+ }) => {
324
328
  moduleGraph.updateModule(dep, newModule);
329
+ moduleGraph.updateParent(
330
+ dep,
331
+ targetConnection,
332
+ /** @type {Module} */ (connection.originModule)
333
+ );
325
334
  moduleGraph.addExplanation(
326
335
  dep,
327
336
  "(skipped side-effect-free modules)"
@@ -353,6 +362,13 @@ class SideEffectsFlagPlugin {
353
362
  if (!target) continue;
354
363
 
355
364
  moduleGraph.updateModule(dep, target.module);
365
+ moduleGraph.updateParent(
366
+ dep,
367
+ /** @type {ModuleGraphConnection} */ (
368
+ target.connection
369
+ ),
370
+ /** @type {Module} */ (connection.originModule)
371
+ );
356
372
  moduleGraph.addExplanation(
357
373
  dep,
358
374
  "(skipped side-effect-free modules)"
@@ -10,6 +10,7 @@ const { SyncHook } = require("tapable");
10
10
  /** @typedef {import("../../declarations/WebpackOptions").Falsy} Falsy */
11
11
  /** @typedef {import("../../declarations/WebpackOptions").RuleSetLoaderOptions} RuleSetLoaderOptions */
12
12
  /** @typedef {import("../../declarations/WebpackOptions").RuleSetRule} RuleSetRule */
13
+ /** @typedef {import("../NormalModule").LoaderItem} LoaderItem */
13
14
 
14
15
  /** @typedef {(Falsy | RuleSetRule)[]} RuleSetRules */
15
16
 
@@ -54,12 +55,22 @@ const { SyncHook } = require("tapable");
54
55
  * @property {CompiledRule[]=} oneOf
55
56
  */
56
57
 
58
+ /** @typedef {"use" | "use-pre" | "use-post"} EffectUseType */
59
+
57
60
  /**
58
- * @typedef {object} Effect
61
+ * @typedef {object} EffectUse
62
+ * @property {EffectUseType} type
63
+ * @property {{ loader: string, options?: string | null | Record<string, EXPECTED_ANY>, ident?: string }} value
64
+ */
65
+
66
+ /**
67
+ * @typedef {object} EffectBasic
59
68
  * @property {string} type
60
- * @property {TODO} value
69
+ * @property {EXPECTED_ANY} value
61
70
  */
62
71
 
72
+ /** @typedef {EffectUse | EffectBasic} Effect */
73
+
63
74
  /** @typedef {Map<string, RuleSetLoaderOptions>} References */
64
75
 
65
76
  /**
@@ -16,6 +16,7 @@ const util = require("util");
16
16
  /** @typedef {import("./RuleSetCompiler")} RuleSetCompiler */
17
17
  /** @typedef {import("./RuleSetCompiler").Effect} Effect */
18
18
  /** @typedef {import("./RuleSetCompiler").EffectData} EffectData */
19
+ /** @typedef {import("./RuleSetCompiler").EffectUseType} EffectUseType */
19
20
 
20
21
  const PLUGIN_NAME = "UseEffectRulePlugin";
21
22
 
@@ -52,7 +53,9 @@ class UseEffectRulePlugin {
52
53
  const use = /** @type {RuleSetUse} */ (rule.use);
53
54
  const enforce = rule.enforce;
54
55
 
55
- const type = enforce ? `use-${enforce}` : "use";
56
+ const type =
57
+ /** @type {EffectUseType} */
58
+ (enforce ? `use-${enforce}` : "use");
56
59
 
57
60
  /**
58
61
  * @param {string} path options path
@@ -89,7 +92,7 @@ class UseEffectRulePlugin {
89
92
  }
90
93
  };
91
94
  }
92
- const loader = item.loader;
95
+ const loader = /** @type {string} */ (item.loader);
93
96
  const options = item.options;
94
97
  let ident = item.ident;
95
98
  if (options && typeof options === "object") {
@@ -207,12 +210,15 @@ class UseEffectRulePlugin {
207
210
 
208
211
  const ident =
209
212
  options && typeof options === "object" ? path : undefined;
210
- references.set(
211
- /** @type {TODO} */
212
- (ident),
213
- /** @type {RuleSetLoaderOptions} */
214
- (options)
215
- );
213
+
214
+ if (ident) {
215
+ references.set(
216
+ ident,
217
+ /** @type {RuleSetLoaderOptions} */
218
+ (options)
219
+ );
220
+ }
221
+
216
222
  result.effects.push({
217
223
  type: enforce ? `use-${enforce}` : "use",
218
224
  value: {
@@ -796,6 +796,7 @@ const SIMPLE_EXTRACTORS = {
796
796
  ? relatedEntry
797
797
  : [relatedEntry];
798
798
  for (const dep of deps) {
799
+ if (!dep) continue;
799
800
  const depItem = assetMap.get(dep);
800
801
  if (!depItem) continue;
801
802
  assets.delete(depItem);