webpack 5.2.1 → 5.3.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.

package/lib/ChunkGraph.js CHANGED
@@ -200,6 +200,8 @@ class ChunkGraph {
200
200
  this._chunks = new WeakMap();
201
201
  /** @private @type {WeakMap<AsyncDependenciesBlock, ChunkGroup>} */
202
202
  this._blockChunkGroups = new WeakMap();
203
+ /** @private @type {Map<string, string | number>} */
204
+ this._runtimeIds = new Map();
203
205
  /** @type {ModuleGraph} */
204
206
  this.moduleGraph = moduleGraph;
205
207
 
@@ -1144,6 +1146,23 @@ class ChunkGraph {
1144
1146
  cgm.id = id;
1145
1147
  }
1146
1148
 
1149
+ /**
1150
+ * @param {string} runtime runtime
1151
+ * @returns {string | number} the id of the runtime
1152
+ */
1153
+ getRuntimeId(runtime) {
1154
+ return this._runtimeIds.get(runtime);
1155
+ }
1156
+
1157
+ /**
1158
+ * @param {string} runtime runtime
1159
+ * @param {string | number} id the id of the runtime
1160
+ * @returns {void}
1161
+ */
1162
+ setRuntimeId(runtime, id) {
1163
+ this._runtimeIds.set(runtime, id);
1164
+ }
1165
+
1147
1166
  /**
1148
1167
  * @param {Module} module the module
1149
1168
  * @param {RuntimeSpec} runtime the runtime
@@ -1939,6 +1939,8 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
1939
1939
  this.hooks.optimizeChunkIds.call(this.chunks);
1940
1940
  this.hooks.afterOptimizeChunkIds.call(this.chunks);
1941
1941
 
1942
+ this.assignRuntimeIds();
1943
+
1942
1944
  this.sortItemsWithChunkIds();
1943
1945
 
1944
1946
  if (shouldRecord) {
@@ -2556,6 +2558,21 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
2556
2558
  }
2557
2559
  }
2558
2560
 
2561
+ assignRuntimeIds() {
2562
+ const { chunkGraph } = this;
2563
+ const processEntrypoint = ep => {
2564
+ const runtime = ep.options.runtime || ep.name;
2565
+ const chunk = ep.getRuntimeChunk();
2566
+ chunkGraph.setRuntimeId(runtime, chunk.id);
2567
+ };
2568
+ for (const ep of this.entrypoints.values()) {
2569
+ processEntrypoint(ep);
2570
+ }
2571
+ for (const ep of this.asyncEntrypoints) {
2572
+ processEntrypoint(ep);
2573
+ }
2574
+ }
2575
+
2559
2576
  sortItemsWithChunkIds() {
2560
2577
  for (const chunkGroup of this.chunkGroups) {
2561
2578
  chunkGroup.sortItems();
@@ -2592,7 +2609,7 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
2592
2609
 
2593
2610
  createModuleHashes() {
2594
2611
  let statModulesHashed = 0;
2595
- const chunkGraph = this.chunkGraph;
2612
+ const { chunkGraph, runtimeTemplate } = this;
2596
2613
  const { hashFunction, hashDigest, hashDigestLength } = this.outputOptions;
2597
2614
  for (const module of this.modules) {
2598
2615
  for (const runtime of chunkGraph.getModuleRuntimes(module)) {
@@ -2600,7 +2617,8 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
2600
2617
  const moduleHash = createHash(hashFunction);
2601
2618
  module.updateHash(moduleHash, {
2602
2619
  chunkGraph,
2603
- runtime
2620
+ runtime,
2621
+ runtimeTemplate
2604
2622
  });
2605
2623
  const moduleHashDigest = /** @type {string} */ (moduleHash.digest(
2606
2624
  hashDigest
@@ -2623,6 +2641,7 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
2623
2641
  createHash() {
2624
2642
  this.logger.time("hashing: initialize hash");
2625
2643
  const chunkGraph = this.chunkGraph;
2644
+ const runtimeTemplate = this.runtimeTemplate;
2626
2645
  const outputOptions = this.outputOptions;
2627
2646
  const hashFunction = outputOptions.hashFunction;
2628
2647
  const hashDigest = outputOptions.hashDigest;
@@ -2707,7 +2726,8 @@ This prevents using hashes of each other and should be avoided.`
2707
2726
  const moduleHash = createHash(hashFunction);
2708
2727
  module.updateHash(moduleHash, {
2709
2728
  chunkGraph,
2710
- runtime: chunk.runtime
2729
+ runtime: chunk.runtime,
2730
+ runtimeTemplate
2711
2731
  });
2712
2732
  const moduleHashDigest = /** @type {string} */ (moduleHash.digest(
2713
2733
  hashDigest
@@ -2769,7 +2789,8 @@ This prevents using hashes of each other and should be avoided.`
2769
2789
  const moduleHash = createHash(hashFunction);
2770
2790
  module.updateHash(moduleHash, {
2771
2791
  chunkGraph,
2772
- runtime: chunk.runtime
2792
+ runtime: chunk.runtime,
2793
+ runtimeTemplate
2773
2794
  });
2774
2795
  const moduleHashDigest = /** @type {string} */ (moduleHash.digest(
2775
2796
  hashDigest
@@ -0,0 +1,109 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ Author Tobias Koppers @sokra
4
+ */
5
+
6
+ "use strict";
7
+
8
+ const { ConcatSource, PrefixSource } = require("webpack-sources");
9
+ const InitFragment = require("./InitFragment");
10
+ const Template = require("./Template");
11
+ const { mergeRuntime } = require("./util/runtime");
12
+
13
+ /** @typedef {import("webpack-sources").Source} Source */
14
+ /** @typedef {import("./Generator").GenerateContext} GenerateContext */
15
+ /** @typedef {import("./util/runtime").RuntimeSpec} RuntimeSpec */
16
+
17
+ const wrapInCondition = (condition, source) => {
18
+ if (typeof source === "string") {
19
+ return Template.asString([
20
+ `if (${condition}) {`,
21
+ Template.indent(source),
22
+ "}",
23
+ ""
24
+ ]);
25
+ } else {
26
+ return new ConcatSource(
27
+ `if (${condition}) {\n`,
28
+ new PrefixSource("\t", source),
29
+ "}\n"
30
+ );
31
+ }
32
+ };
33
+
34
+ class ConditionalInitFragment extends InitFragment {
35
+ /**
36
+ * @param {string|Source} content the source code that will be included as initialization code
37
+ * @param {number} stage category of initialization code (contribute to order)
38
+ * @param {number} position position in the category (contribute to order)
39
+ * @param {string} key unique key to avoid emitting the same initialization code twice
40
+ * @param {RuntimeSpec | boolean} runtimeCondition in which runtime this fragment should be executed
41
+ * @param {string|Source=} endContent the source code that will be included at the end of the module
42
+ */
43
+ constructor(
44
+ content,
45
+ stage,
46
+ position,
47
+ key,
48
+ runtimeCondition = true,
49
+ endContent
50
+ ) {
51
+ super(content, stage, position, key, endContent);
52
+ this.runtimeCondition = runtimeCondition;
53
+ }
54
+
55
+ /**
56
+ * @param {GenerateContext} generateContext context for generate
57
+ * @returns {string|Source} the source code that will be included as initialization code
58
+ */
59
+ getContent(generateContext) {
60
+ if (this.runtimeCondition === false || !this.content) return "";
61
+ if (this.runtimeCondition === true) return this.content;
62
+ const expr = generateContext.runtimeTemplate.runtimeConditionExpression({
63
+ chunkGraph: generateContext.chunkGraph,
64
+ runtimeRequirements: generateContext.runtimeRequirements,
65
+ runtime: generateContext.runtime,
66
+ runtimeCondition: this.runtimeCondition
67
+ });
68
+ if (expr === "true") return this.content;
69
+ return wrapInCondition(expr, this.content);
70
+ }
71
+
72
+ /**
73
+ * @param {GenerateContext} generateContext context for generate
74
+ * @returns {string|Source=} the source code that will be included at the end of the module
75
+ */
76
+ getEndContent(generateContext) {
77
+ if (this.runtimeCondition === false || !this.endContent) return "";
78
+ if (this.runtimeCondition === true) return this.endContent;
79
+ const expr = generateContext.runtimeTemplate.runtimeConditionExpression({
80
+ chunkGraph: generateContext.chunkGraph,
81
+ runtimeRequirements: generateContext.runtimeRequirements,
82
+ runtime: generateContext.runtime,
83
+ runtimeCondition: this.runtimeCondition
84
+ });
85
+ if (expr === "true") return this.endContent;
86
+ return wrapInCondition(expr, this.endContent);
87
+ }
88
+
89
+ merge(other) {
90
+ if (this.runtimeCondition === true) return this;
91
+ if (other.runtimeCondition === true) return other;
92
+ if (this.runtimeCondition === false) return other;
93
+ if (other.runtimeCondition === false) return this;
94
+ const runtimeCondition = mergeRuntime(
95
+ this.runtimeCondition,
96
+ other.runtimeCondition
97
+ );
98
+ return new ConditionalInitFragment(
99
+ this.content,
100
+ this.stage,
101
+ this.position,
102
+ this.key,
103
+ runtimeCondition,
104
+ this.endContent
105
+ );
106
+ }
107
+ }
108
+
109
+ module.exports = ConditionalInitFragment;
package/lib/Dependency.js CHANGED
@@ -21,6 +21,7 @@
21
21
  * @typedef {Object} UpdateHashContext
22
22
  * @property {ChunkGraph} chunkGraph
23
23
  * @property {RuntimeSpec} runtime
24
+ * @property {RuntimeTemplate=} runtimeTemplate
24
25
  */
25
26
 
26
27
  /**
@@ -173,6 +173,11 @@ exports.loadScript = "__webpack_require__.l";
173
173
  */
174
174
  exports.chunkName = "__webpack_require__.cn";
175
175
 
176
+ /**
177
+ * the runtime id of the current runtime
178
+ */
179
+ exports.runtimeId = "__webpack_require__.j";
180
+
176
181
  /**
177
182
  * the filename of the script part of the chunk
178
183
  */
@@ -21,6 +21,7 @@ const HasOwnPropertyRuntimeModule = require("./runtime/HasOwnPropertyRuntimeModu
21
21
  const LoadScriptRuntimeModule = require("./runtime/LoadScriptRuntimeModule");
22
22
  const MakeNamespaceObjectRuntimeModule = require("./runtime/MakeNamespaceObjectRuntimeModule");
23
23
  const PublicPathRuntimeModule = require("./runtime/PublicPathRuntimeModule");
24
+ const RuntimeIdRuntimeModule = require("./runtime/RuntimeIdRuntimeModule");
24
25
  const SystemContextRuntimeModule = require("./runtime/SystemContextRuntimeModule");
25
26
  const ShareRuntimeModule = require("./sharing/ShareRuntimeModule");
26
27
  const StringXor = require("./util/StringXor");
@@ -31,6 +32,7 @@ const StringXor = require("./util/StringXor");
31
32
 
32
33
  const GLOBALS_ON_REQUIRE = [
33
34
  RuntimeGlobals.chunkName,
35
+ RuntimeGlobals.runtimeId,
34
36
  RuntimeGlobals.compatGetDefaultExport,
35
37
  RuntimeGlobals.createFakeNamespaceObject,
36
38
  RuntimeGlobals.definePropertyGetters,
@@ -156,6 +158,12 @@ class RuntimePlugin {
156
158
  );
157
159
  return true;
158
160
  });
161
+ compilation.hooks.runtimeRequirementInTree
162
+ .for(RuntimeGlobals.runtimeId)
163
+ .tap("RuntimePlugin", chunk => {
164
+ compilation.addRuntimeModule(chunk, new RuntimeIdRuntimeModule());
165
+ return true;
166
+ });
159
167
  compilation.hooks.runtimeRequirementInTree
160
168
  .for(RuntimeGlobals.publicPath)
161
169
  .tap("RuntimePlugin", (chunk, set) => {
@@ -9,7 +9,9 @@ const InitFragment = require("./InitFragment");
9
9
  const RuntimeGlobals = require("./RuntimeGlobals");
10
10
  const Template = require("./Template");
11
11
  const { equals } = require("./util/ArrayHelpers");
12
+ const compileBooleanMatcher = require("./util/compileBooleanMatcher");
12
13
  const propertyAccess = require("./util/propertyAccess");
14
+ const { forEachRuntime, subtractRuntime } = require("./util/runtime");
13
15
 
14
16
  /** @typedef {import("../declarations/WebpackOptions").OutputNormalized} OutputOptions */
15
17
  /** @typedef {import("./AsyncDependenciesBlock")} AsyncDependenciesBlock */
@@ -562,6 +564,39 @@ class RuntimeTemplate {
562
564
  return `${promise || "Promise.resolve()"}${appending}`;
563
565
  }
564
566
 
567
+ /**
568
+ * @param {Object} options options object
569
+ * @param {ChunkGraph} options.chunkGraph the chunk graph
570
+ * @param {RuntimeSpec=} options.runtime runtime for which this code will be generated
571
+ * @param {RuntimeSpec | boolean=} options.runtimeCondition only execute the statement in some runtimes
572
+ * @param {Set<string>} options.runtimeRequirements if set, will be filled with runtime requirements
573
+ * @returns {string} expression
574
+ */
575
+ runtimeConditionExpression({
576
+ chunkGraph,
577
+ runtimeCondition,
578
+ runtime,
579
+ runtimeRequirements
580
+ }) {
581
+ if (runtimeCondition === undefined) return "true";
582
+ if (typeof runtimeCondition === "boolean") return `${runtimeCondition}`;
583
+ /** @type {Set<string>} */
584
+ const positiveRuntimeIds = new Set();
585
+ forEachRuntime(runtimeCondition, runtime =>
586
+ positiveRuntimeIds.add(`${chunkGraph.getRuntimeId(runtime)}`)
587
+ );
588
+ /** @type {Set<string>} */
589
+ const negativeRuntimeIds = new Set();
590
+ forEachRuntime(subtractRuntime(runtime, runtimeCondition), runtime =>
591
+ negativeRuntimeIds.add(`${chunkGraph.getRuntimeId(runtime)}`)
592
+ );
593
+ runtimeRequirements.add(RuntimeGlobals.runtimeId);
594
+ return compileBooleanMatcher.fromLists(
595
+ Array.from(positiveRuntimeIds),
596
+ Array.from(negativeRuntimeIds)
597
+ )(RuntimeGlobals.runtimeId);
598
+ }
599
+
565
600
  /**
566
601
  *
567
602
  * @param {Object} options options object
@@ -572,6 +607,8 @@ class RuntimeTemplate {
572
607
  * @param {string} options.importVar name of the import variable
573
608
  * @param {Module} options.originModule module in which the statement is emitted
574
609
  * @param {boolean=} options.weak true, if this is a weak dependency
610
+ * @param {RuntimeSpec=} options.runtime runtime for which this code will be generated
611
+ * @param {RuntimeSpec | boolean=} options.runtimeCondition only execute the statement in some runtimes
575
612
  * @param {Set<string>} options.runtimeRequirements if set, will be filled with runtime requirements
576
613
  * @returns {[string, string]} the import statement and the compat statement
577
614
  */
@@ -308,7 +308,9 @@ class WebpackOptionsApply extends OptionsApply {
308
308
  }
309
309
  if (options.optimization.sideEffects) {
310
310
  const SideEffectsFlagPlugin = require("./optimize/SideEffectsFlagPlugin");
311
- new SideEffectsFlagPlugin().apply(compiler);
311
+ new SideEffectsFlagPlugin(
312
+ options.optimization.sideEffects === true
313
+ ).apply(compiler);
312
314
  }
313
315
  if (options.optimization.providedExports) {
314
316
  const FlagDependencyExportsPlugin = require("./FlagDependencyExportsPlugin");
@@ -848,7 +848,7 @@ const applyOptimizationDefaults = (
848
848
  if (development) return "named";
849
849
  return "natural";
850
850
  });
851
- D(optimization, "sideEffects", true);
851
+ F(optimization, "sideEffects", () => (production ? true : "flag"));
852
852
  D(optimization, "providedExports", true);
853
853
  D(optimization, "usedExports", production);
854
854
  D(optimization, "innerGraph", production);
@@ -5,6 +5,7 @@
5
5
 
6
6
  "use strict";
7
7
 
8
+ const Template = require("../Template");
8
9
  const makeSerializable = require("../util/makeSerializable");
9
10
  const HarmonyImportDependency = require("./HarmonyImportDependency");
10
11
  const NullDependency = require("./NullDependency");
@@ -62,14 +63,41 @@ HarmonyAcceptDependency.Template = class HarmonyAcceptDependencyTemplate extends
62
63
  */
63
64
  apply(dependency, source, templateContext) {
64
65
  const dep = /** @type {HarmonyAcceptDependency} */ (dependency);
65
- const { module, runtimeTemplate } = templateContext;
66
+ const {
67
+ module,
68
+ runtime,
69
+ runtimeRequirements,
70
+ runtimeTemplate,
71
+ moduleGraph,
72
+ chunkGraph
73
+ } = templateContext;
66
74
  const content = dep.dependencies
67
- .filter(dependency =>
68
- HarmonyImportDependency.Template.isImportEmitted(dependency, module)
69
- )
70
75
  .map(dependency => {
76
+ const referencedModule = moduleGraph.getModule(dependency);
77
+ return {
78
+ dependency,
79
+ runtimeCondition: referencedModule
80
+ ? HarmonyImportDependency.Template.getImportEmittedRuntime(
81
+ module,
82
+ referencedModule
83
+ )
84
+ : false
85
+ };
86
+ })
87
+ .filter(({ runtimeCondition }) => runtimeCondition !== false)
88
+ .map(({ dependency, runtimeCondition }) => {
89
+ const condition = runtimeTemplate.runtimeConditionExpression({
90
+ chunkGraph,
91
+ runtime,
92
+ runtimeCondition,
93
+ runtimeRequirements
94
+ });
71
95
  const s = dependency.getImportStatement(true, templateContext);
72
- return s[0] + s[1];
96
+ const code = s[0] + s[1];
97
+ if (condition !== "true") {
98
+ return `if (${condition}) {\n${Template.indent(code)}\n}\n`;
99
+ }
100
+ return code;
73
101
  })
74
102
  .join("");
75
103
 
@@ -5,11 +5,13 @@
5
5
 
6
6
  "use strict";
7
7
 
8
+ const ConditionalInitFragment = require("../ConditionalInitFragment");
8
9
  const Dependency = require("../Dependency");
9
10
  const HarmonyLinkingError = require("../HarmonyLinkingError");
10
11
  const InitFragment = require("../InitFragment");
11
12
  const Template = require("../Template");
12
13
  const AwaitDependenciesInitFragment = require("../async-modules/AwaitDependenciesInitFragment");
14
+ const { filterRuntime, mergeRuntime } = require("../util/runtime");
13
15
  const ModuleDependency = require("./ModuleDependency");
14
16
 
15
17
  /** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
@@ -199,21 +201,38 @@ class HarmonyImportDependency extends ModuleDependency {
199
201
  * @returns {void}
200
202
  */
201
203
  updateHash(hash, context) {
202
- const { chunkGraph } = context;
204
+ const { chunkGraph, runtime, runtimeTemplate } = context;
203
205
  const { moduleGraph } = chunkGraph;
204
206
  super.updateHash(hash, context);
205
- const importedModule = moduleGraph.getModule(this);
206
- if (importedModule) {
207
- const parentModule = moduleGraph.getParentModule(this);
208
- hash.update(
209
- importedModule.getExportsType(
210
- moduleGraph,
211
- parentModule.buildMeta && parentModule.buildMeta.strictHarmonyModule
212
- )
213
- );
214
- if (moduleGraph.isAsync(importedModule)) hash.update("async");
215
- }
216
207
  hash.update(`${this.sourceOrder}`);
208
+ const connection = moduleGraph.getConnection(this);
209
+ if (connection) {
210
+ const importedModule = connection.module;
211
+ if (importedModule) {
212
+ const parentModule = moduleGraph.getParentModule(this);
213
+ hash.update(
214
+ importedModule.getExportsType(
215
+ moduleGraph,
216
+ parentModule.buildMeta && parentModule.buildMeta.strictHarmonyModule
217
+ )
218
+ );
219
+ if (moduleGraph.isAsync(importedModule)) hash.update("async");
220
+ }
221
+ if (runtimeTemplate) {
222
+ const runtimeRequirements = new Set();
223
+ hash.update(
224
+ runtimeTemplate.runtimeConditionExpression({
225
+ chunkGraph,
226
+ runtimeCondition: filterRuntime(runtime, runtime => {
227
+ return connection.isTargetActive(runtime);
228
+ }),
229
+ runtime,
230
+ runtimeRequirements
231
+ })
232
+ );
233
+ for (const rr of runtimeRequirements) hash.update(rr);
234
+ }
235
+ }
217
236
  }
218
237
 
219
238
  serialize(context) {
@@ -231,6 +250,7 @@ class HarmonyImportDependency extends ModuleDependency {
231
250
 
232
251
  module.exports = HarmonyImportDependency;
233
252
 
253
+ /** @type {WeakMap<Module, WeakMap<Module, RuntimeSpec | boolean>>} */
234
254
  const importEmittedMap = new WeakMap();
235
255
 
236
256
  HarmonyImportDependency.Template = class HarmonyImportDependencyTemplate extends ModuleDependency.Template {
@@ -265,23 +285,42 @@ HarmonyImportDependency.Template = class HarmonyImportDependencyTemplate extends
265
285
  : dep.request;
266
286
  const key = `harmony import ${moduleKey}`;
267
287
 
268
- if (module) {
269
- let emittedModules = importEmittedMap.get(dep);
288
+ const runtimeCondition = dep.weak
289
+ ? false
290
+ : connection
291
+ ? filterRuntime(runtime, r => connection.isTargetActive(r))
292
+ : true;
293
+
294
+ if (module && referencedModule) {
295
+ let emittedModules = importEmittedMap.get(module);
270
296
  if (emittedModules === undefined) {
271
- emittedModules = new WeakSet();
272
- importEmittedMap.set(dep, emittedModules);
297
+ emittedModules = new WeakMap();
298
+ importEmittedMap.set(module, emittedModules);
299
+ }
300
+ let mergedRuntimeCondition = runtimeCondition;
301
+ const oldRuntimeCondition = emittedModules.get(referencedModule) || false;
302
+ if (oldRuntimeCondition !== false && mergedRuntimeCondition !== true) {
303
+ if (mergedRuntimeCondition === false || oldRuntimeCondition === true) {
304
+ mergedRuntimeCondition = oldRuntimeCondition;
305
+ } else {
306
+ mergedRuntimeCondition = mergeRuntime(
307
+ oldRuntimeCondition,
308
+ mergedRuntimeCondition
309
+ );
310
+ }
273
311
  }
274
- emittedModules.add(module);
312
+ emittedModules.set(referencedModule, mergedRuntimeCondition);
275
313
  }
276
314
 
277
315
  const importStatement = dep.getImportStatement(false, templateContext);
278
316
  if (templateContext.moduleGraph.isAsync(referencedModule)) {
279
317
  templateContext.initFragments.push(
280
- new InitFragment(
318
+ new ConditionalInitFragment(
281
319
  importStatement[0],
282
320
  InitFragment.STAGE_HARMONY_IMPORTS,
283
321
  dep.sourceOrder,
284
- key
322
+ key,
323
+ runtimeCondition
285
324
  )
286
325
  );
287
326
  templateContext.initFragments.push(
@@ -290,20 +329,22 @@ HarmonyImportDependency.Template = class HarmonyImportDependencyTemplate extends
290
329
  )
291
330
  );
292
331
  templateContext.initFragments.push(
293
- new InitFragment(
332
+ new ConditionalInitFragment(
294
333
  importStatement[1],
295
334
  InitFragment.STAGE_ASYNC_HARMONY_IMPORTS,
296
335
  dep.sourceOrder,
297
- key + " compat"
336
+ key + " compat",
337
+ runtimeCondition
298
338
  )
299
339
  );
300
340
  } else {
301
341
  templateContext.initFragments.push(
302
- new InitFragment(
342
+ new ConditionalInitFragment(
303
343
  importStatement[0] + importStatement[1],
304
344
  InitFragment.STAGE_HARMONY_IMPORTS,
305
345
  dep.sourceOrder,
306
- key
346
+ key,
347
+ runtimeCondition
307
348
  )
308
349
  );
309
350
  }
@@ -311,12 +352,13 @@ HarmonyImportDependency.Template = class HarmonyImportDependencyTemplate extends
311
352
 
312
353
  /**
313
354
  *
314
- * @param {Dependency} dep the dependency
315
355
  * @param {Module} module the module
316
- * @returns {boolean} true, when for this dependency and module a import init fragment was created
356
+ * @param {Module} referencedModule the referenced module
357
+ * @returns {RuntimeSpec | boolean} runtimeCondition in which this import has been emitted
317
358
  */
318
- static isImportEmitted(dep, module) {
319
- const emittedModules = importEmittedMap.get(dep);
320
- return emittedModules !== undefined && emittedModules.has(module);
359
+ static getImportEmittedRuntime(module, referencedModule) {
360
+ const emittedModules = importEmittedMap.get(module);
361
+ if (emittedModules === undefined) return false;
362
+ return emittedModules.get(referencedModule) || false;
321
363
  }
322
364
  };
@@ -196,7 +196,7 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency {
196
196
  * @returns {void}
197
197
  */
198
198
  updateHash(hash, context) {
199
- const { chunkGraph } = context;
199
+ const { chunkGraph, runtime } = context;
200
200
  super.updateHash(hash, context);
201
201
  const moduleGraph = chunkGraph.moduleGraph;
202
202
  const importedModule = moduleGraph.getModule(this);
@@ -204,7 +204,7 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency {
204
204
  hash.update(ids.join());
205
205
  if (importedModule) {
206
206
  const exportsInfo = moduleGraph.getExportsInfo(importedModule);
207
- hash.update(`${exportsInfo.getUsedName(ids, context.runtime)}`);
207
+ hash.update(`${exportsInfo.getUsedName(ids, runtime)}`);
208
208
  }
209
209
  }
210
210
 
@@ -7,6 +7,7 @@
7
7
 
8
8
  const { UsageState } = require("../ExportsInfo");
9
9
  const makeSerializable = require("../util/makeSerializable");
10
+ const { filterRuntime } = require("../util/runtime");
10
11
  const NullDependency = require("./NullDependency");
11
12
 
12
13
  /** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
@@ -74,22 +75,45 @@ PureExpressionDependency.Template = class PureExpressionDependencyTemplate exten
74
75
  * @param {DependencyTemplateContext} templateContext the context object
75
76
  * @returns {void}
76
77
  */
77
- apply(dependency, source, { moduleGraph, runtime }) {
78
+ apply(
79
+ dependency,
80
+ source,
81
+ { chunkGraph, moduleGraph, runtime, runtimeTemplate, runtimeRequirements }
82
+ ) {
78
83
  const dep = /** @type {PureExpressionDependency} */ (dependency);
79
84
 
80
- if (dep.usedByExports !== false) {
85
+ const usedByExports = dep.usedByExports;
86
+ if (usedByExports !== false) {
81
87
  const selfModule = moduleGraph.getParentModule(dep);
82
88
  const exportsInfo = moduleGraph.getExportsInfo(selfModule);
83
- for (const exportName of dep.usedByExports) {
84
- if (exportsInfo.getUsed(exportName, runtime) !== UsageState.Unused) {
85
- return;
89
+ const runtimeCondition = filterRuntime(runtime, runtime => {
90
+ for (const exportName of usedByExports) {
91
+ if (exportsInfo.getUsed(exportName, runtime) !== UsageState.Unused) {
92
+ return true;
93
+ }
86
94
  }
95
+ return false;
96
+ });
97
+ if (runtimeCondition === true) return;
98
+ if (runtimeCondition !== false) {
99
+ const condition = runtimeTemplate.runtimeConditionExpression({
100
+ chunkGraph,
101
+ runtime,
102
+ runtimeCondition,
103
+ runtimeRequirements
104
+ });
105
+ source.insert(
106
+ dep.range[0],
107
+ `(/* runtime-dependent pure expression or super */ ${condition} ? (`
108
+ );
109
+ source.insert(dep.range[1], ") : null)");
110
+ return;
87
111
  }
88
112
  }
89
113
 
90
114
  source.insert(
91
115
  dep.range[0],
92
- "(/* unused pure expression or super */ null && ("
116
+ `(/* unused pure expression or super */ null && (`
93
117
  );
94
118
  source.insert(dep.range[1], "))");
95
119
  }
@@ -12,6 +12,7 @@ const UnsupportedFeatureWarning = require("../UnsupportedFeatureWarning");
12
12
  const formatLocation = require("../formatLocation");
13
13
  const EnableChunkLoadingPlugin = require("../javascript/EnableChunkLoadingPlugin");
14
14
  const { equals } = require("../util/ArrayHelpers");
15
+ const { contextify } = require("../util/identifier");
15
16
  const {
16
17
  harmonySpecifierTag
17
18
  } = require("./HarmonyImportDependencyParserPlugin");
@@ -48,6 +49,10 @@ class WorkerPlugin {
48
49
  if (this._chunkLoading) {
49
50
  new EnableChunkLoadingPlugin(this._chunkLoading).apply(compiler);
50
51
  }
52
+ const cachedContextify = contextify.bindContextCache(
53
+ compiler.context,
54
+ compiler.root
55
+ );
51
56
  compiler.hooks.thisCompilation.tap(
52
57
  "WorkerPlugin",
53
58
  (compilation, { normalModuleFactory }) => {
@@ -213,9 +218,9 @@ class WorkerPlugin {
213
218
  }
214
219
 
215
220
  if (!entryOptions.runtime) {
216
- entryOptions.runtime = `${parser.state.module.identifier()}|${formatLocation(
217
- expr.loc
218
- )}`;
221
+ entryOptions.runtime = `${cachedContextify(
222
+ parser.state.module.identifier()
223
+ )}|${formatLocation(expr.loc)}`;
219
224
  }
220
225
 
221
226
  const block = new AsyncDependenciesBlock({