webpack 5.108.4 → 5.109.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.
Files changed (186) hide show
  1. package/lib/APIPlugin.js +48 -29
  2. package/lib/CacheFacade.js +8 -0
  3. package/lib/ChunkGroup.js +1 -0
  4. package/lib/CompatibilityPlugin.js +31 -29
  5. package/lib/Compilation.js +49 -4
  6. package/lib/ConstPlugin.js +11 -11
  7. package/lib/ContextModule.js +239 -6
  8. package/lib/ContextModuleFactory.js +139 -14
  9. package/lib/DefinePlugin.js +396 -101
  10. package/lib/Entrypoint.js +1 -1
  11. package/lib/ExportsInfoApiPlugin.js +2 -2
  12. package/lib/ExternalModule.js +107 -5
  13. package/lib/ExternalModuleFactoryPlugin.js +20 -1
  14. package/lib/FileSystemInfo.js +130 -74
  15. package/lib/HotModuleReplacementPlugin.js +18 -15
  16. package/lib/Module.js +3 -0
  17. package/lib/ModuleFilenameHelpers.js +2 -2
  18. package/lib/ModuleTypeConstants.js +8 -1
  19. package/lib/MultiCompiler.js +13 -2
  20. package/lib/MultiWatching.js +1 -0
  21. package/lib/NodeStuffPlugin.js +51 -33
  22. package/lib/NormalModule.js +169 -401
  23. package/lib/NormalModuleFactory.js +76 -2
  24. package/lib/ProgressPlugin.js +211 -119
  25. package/lib/ProvidePlugin.js +2 -2
  26. package/lib/RuntimeGlobals.js +47 -0
  27. package/lib/RuntimePlugin.js +33 -0
  28. package/lib/RuntimeTemplate.js +304 -16
  29. package/lib/UseStrictPlugin.js +1 -1
  30. package/lib/WebpackIsIncludedPlugin.js +1 -1
  31. package/lib/WebpackOptionsApply.js +24 -19
  32. package/lib/asset/AssetGenerator.js +110 -28
  33. package/lib/asset/AssetModulesPlugin.js +92 -2
  34. package/lib/asset/WebManifestGenerator.js +164 -0
  35. package/lib/asset/WebManifestParser.js +130 -0
  36. package/lib/async-modules/AwaitDependenciesInitFragment.js +14 -4
  37. package/lib/async-modules/isGeneratorLowered.js +26 -0
  38. package/lib/cache/PackFileCacheStrategy.js +9 -3
  39. package/lib/config/browserslistTargetHandler.js +40 -0
  40. package/lib/config/defaults.js +219 -29
  41. package/lib/config/normalization.js +26 -0
  42. package/lib/config/target.js +9 -1
  43. package/lib/css/CssGenerator.js +40 -31
  44. package/lib/css/CssLoadingRuntimeModule.js +5 -1
  45. package/lib/css/CssModulesPlugin.js +13 -0
  46. package/lib/css/CssParser.js +594 -263
  47. package/lib/css/syntax.js +875 -462
  48. package/lib/dependencies/AMDDefineDependencyParserPlugin.js +6 -6
  49. package/lib/dependencies/AMDPlugin.js +2 -2
  50. package/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js +13 -13
  51. package/lib/dependencies/CommonJsDependencyHelpers.js +39 -0
  52. package/lib/dependencies/CommonJsExportsDependency.js +47 -2
  53. package/lib/dependencies/CommonJsExportsParserPlugin.js +10 -10
  54. package/lib/dependencies/CommonJsImportsParserPlugin.js +18 -18
  55. package/lib/dependencies/CommonJsPlugin.js +2 -2
  56. package/lib/dependencies/CommonJsRequireDependency.js +26 -1
  57. package/lib/dependencies/CommonJsSelfReferenceDependency.js +32 -1
  58. package/lib/dependencies/ContextDependencyHelpers.js +3 -3
  59. package/lib/dependencies/CreateRequireParserPlugin.js +6 -6
  60. package/lib/dependencies/CssIcssExportDependency.js +162 -71
  61. package/lib/dependencies/CssUrlDependency.js +35 -4
  62. package/lib/dependencies/ExternalModuleInitFragmentDependency.js +2 -2
  63. package/lib/dependencies/HarmonyCompatibilityDependency.js +32 -14
  64. package/lib/dependencies/HarmonyDetectionParserPlugin.js +43 -13
  65. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +7 -19
  66. package/lib/dependencies/HarmonyImportDependency.js +12 -1
  67. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +11 -11
  68. package/lib/dependencies/HarmonyModulesPlugin.js +6 -0
  69. package/lib/dependencies/HarmonyTopLevelThisParserPlugin.js +1 -1
  70. package/lib/dependencies/HtmlEntryDependency.js +797 -172
  71. package/lib/dependencies/HtmlSourceDependency.js +26 -0
  72. package/lib/dependencies/ImportDependency.js +43 -1
  73. package/lib/dependencies/ImportMetaContextDependencyParserPlugin.js +31 -18
  74. package/lib/dependencies/ImportMetaContextPlugin.js +38 -7
  75. package/lib/dependencies/ImportMetaGlobDependency.js +81 -0
  76. package/lib/dependencies/ImportMetaGlobDependencyParserPlugin.js +78 -0
  77. package/lib/dependencies/ImportMetaGlobHelpers.js +660 -0
  78. package/lib/dependencies/ImportMetaPlugin.js +532 -180
  79. package/lib/dependencies/ImportMetaResolveDependency.js +90 -0
  80. package/lib/dependencies/ImportParserPlugin.js +80 -17
  81. package/lib/dependencies/ImportPhase.js +10 -8
  82. package/lib/dependencies/LoaderPlugin.js +5 -1
  83. package/lib/dependencies/RequireContextDependencyParserPlugin.js +1 -1
  84. package/lib/dependencies/RequireEnsureDependenciesBlockParserPlugin.js +3 -6
  85. package/lib/dependencies/RequireIncludeDependencyParserPlugin.js +4 -11
  86. package/lib/dependencies/SystemPlugin.js +2 -4
  87. package/lib/dependencies/TopLevelAwaitDependency.js +93 -0
  88. package/lib/dependencies/URLDependency.js +141 -21
  89. package/lib/dependencies/{WorkerPlugin.js → WorkerAndWorkletPlugin.js} +324 -112
  90. package/lib/dependencies/WorkerDependency.js +86 -18
  91. package/lib/dependencies/WorkletDependency.js +278 -0
  92. package/lib/dll/DelegatedModuleFactoryPlugin.js +19 -0
  93. package/lib/errors/EnvironmentNotSupportAsyncWarning.js +1 -1
  94. package/lib/errors/LoaderLoadingError.js +20 -0
  95. package/lib/errors/ModuleParseError.js +39 -22
  96. package/lib/errors/NodeStuffInWebError.js +1 -1
  97. package/lib/esm/ModuleChunkFormatPlugin.js +47 -14
  98. package/lib/esm/ModuleChunkLoadingPlugin.js +8 -1
  99. package/lib/esm/ModuleChunkLoadingRuntimeModule.js +29 -1
  100. package/lib/hmr/lazyCompilationBackend.js +32 -8
  101. package/lib/html/HtmlGenerator.js +887 -15
  102. package/lib/html/HtmlModule.js +2 -2
  103. package/lib/html/HtmlModulesPlugin.js +610 -166
  104. package/lib/html/HtmlParser.js +603 -247
  105. package/lib/html/favicon.svg +1 -0
  106. package/lib/html/syntax.js +1264 -661
  107. package/lib/ids/IdHelpers.js +1 -1
  108. package/lib/index.js +6 -0
  109. package/lib/javascript/ArrayPushCallbackChunkFormatPlugin.js +4 -5
  110. package/lib/javascript/BasicEvaluatedExpression.js +366 -48
  111. package/lib/javascript/JavascriptGenerator.js +197 -49
  112. package/lib/javascript/JavascriptModulesPlugin.js +178 -24
  113. package/lib/javascript/JavascriptParser.js +701 -355
  114. package/lib/javascript/JavascriptParserHelpers.js +3 -6
  115. package/lib/javascript/syntax.js +4380 -0
  116. package/lib/library/ModuleLibraryPlugin.js +38 -1
  117. package/lib/loaders/LoaderRunner.js +714 -0
  118. package/lib/loaders/loadLoader.js +100 -0
  119. package/lib/node/ReadFileCompileAsyncWasmPlugin.js +19 -0
  120. package/lib/node/ReadFileCompileWasmPlugin.js +14 -0
  121. package/lib/optimize/ConcatenatedModule.js +120 -16
  122. package/lib/optimize/FlagIncludedChunksPlugin.js +13 -3
  123. package/lib/optimize/InnerGraphPlugin.js +50 -30
  124. package/lib/optimize/ModuleConcatenationPlugin.js +69 -3
  125. package/lib/optimize/SideEffectsFlagPlugin.js +86 -43
  126. package/lib/prefetch/ChunkPrefetchPreloadPlugin.js +15 -0
  127. package/lib/prefetch/ChunkPreloadTriggerRuntimeModule.js +24 -13
  128. package/lib/prefetch/ResourceHintPlugin.js +663 -0
  129. package/lib/prefetch/ResourceHintRuntimeModule.js +149 -0
  130. package/lib/prefetch/StartupAssetHintRuntimeModule.js +210 -0
  131. package/lib/prefetch/parseResourceHintOptions.js +103 -0
  132. package/lib/rules/RuleSetCompiler.js +114 -0
  133. package/lib/runtime/AsyncModuleGeneratorRuntimeModule.js +56 -0
  134. package/lib/runtime/AsyncModuleRuntimeModule.js +24 -8
  135. package/lib/runtime/AutoPublicPathRuntimeModule.js +7 -1
  136. package/lib/runtime/CommonJsWrapRuntimeModule.js +37 -0
  137. package/lib/runtime/GetWorkletBootstrapRuntimeModule.js +59 -0
  138. package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +204 -8
  139. package/lib/runtime/SetAnonymousDefaultNameRuntimeModule.js +4 -1
  140. package/lib/schemes/HttpUriPlugin.js +40 -1
  141. package/lib/schemes/VirtualUrlPlugin.js +1 -2
  142. package/lib/serialization/FileMiddleware.js +29 -3
  143. package/lib/stats/DefaultStatsFactoryPlugin.js +32 -3
  144. package/lib/stats/DefaultStatsPresetPlugin.js +2 -0
  145. package/lib/stats/DefaultStatsPrinterPlugin.js +12 -2
  146. package/lib/stats/StatsFactory.js +15 -8
  147. package/lib/url/URLParserPlugin.js +66 -13
  148. package/lib/util/AsyncQueue.js +122 -72
  149. package/lib/util/SetHelpers.js +1 -1
  150. package/lib/util/StackedMap.js +122 -48
  151. package/lib/util/binarySearchBounds.js +2 -2
  152. package/lib/util/concatenate.js +40 -14
  153. package/lib/util/createHooksRegistry.js +13 -5
  154. package/lib/util/dataURL.js +2 -2
  155. package/lib/util/deterministicGrouping.js +7 -5
  156. package/lib/util/formatSize.js +6 -2
  157. package/lib/util/globUtils.js +710 -0
  158. package/lib/util/identifier.js +23 -6
  159. package/lib/util/implicitTypeLoaderFallback.js +62 -0
  160. package/lib/util/internalSerializables.js +88 -71
  161. package/lib/util/magicComment.js +121 -25
  162. package/lib/util/numberHash.js +2 -2
  163. package/lib/wasm-async/AsyncWasmCompileRuntimeModule.js +24 -18
  164. package/lib/wasm-async/AsyncWasmLoadingRuntimeModule.js +33 -22
  165. package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +79 -16
  166. package/lib/web/FetchCompileAsyncWasmPlugin.js +19 -0
  167. package/lib/web/FetchCompileWasmPlugin.js +14 -0
  168. package/lib/web/JsonpChunkLoadingRuntimeModule.js +2 -0
  169. package/lib/webpack.js +65 -0
  170. package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +3 -0
  171. package/module.d.ts +21 -0
  172. package/package.json +13 -12
  173. package/schemas/WebpackOptions.check.js +1 -1
  174. package/schemas/WebpackOptions.json +759 -36
  175. package/schemas/plugins/HtmlParserOptions.check.js +1 -1
  176. package/schemas/plugins/ProgressPlugin.check.js +1 -1
  177. package/schemas/plugins/ProgressPlugin.json +17 -1
  178. package/schemas/plugins/container/ContainerReferencePlugin.check.js +1 -1
  179. package/schemas/plugins/container/ContainerReferencePlugin.json +1 -0
  180. package/schemas/plugins/container/ExternalsType.check.js +1 -1
  181. package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
  182. package/schemas/plugins/container/ModuleFederationPlugin.json +1 -0
  183. package/schemas/plugins/css/CssAutoOrModuleParserOptions.check.js +1 -1
  184. package/schemas/plugins/css/CssModuleParserOptions.check.js +1 -1
  185. package/schemas/plugins/css/CssParserOptions.check.js +1 -1
  186. package/types.d.ts +1213 -96
@@ -86,6 +86,10 @@ class RuntimeValue {
86
86
  const buildInfo = /** @type {BuildInfo} */ (parser.state.module.buildInfo);
87
87
  if (this.options === true) {
88
88
  buildInfo.cacheable = false;
89
+ const reasons =
90
+ buildInfo.notCacheableReasons || (buildInfo.notCacheableReasons = []);
91
+ const reason = `DefinePlugin runtime value ${key}`;
92
+ if (!reasons.includes(reason)) reasons.push(reason);
89
93
  } else {
90
94
  if (this.options.fileDependencies) {
91
95
  for (const dep of this.options.fileDependencies) {
@@ -204,7 +208,7 @@ const stringifyObj = (
204
208
  code = `{${keys
205
209
  .map((key) => {
206
210
  const code = obj[key];
207
- return `${key === "__proto__" ? '["__proto__"]' : JSON.stringify(key)}:${toCode(
211
+ return `${toPropertyKey(key)}:${toCode(
208
212
  code,
209
213
  parser,
210
214
  valueCacheVersions,
@@ -350,10 +354,279 @@ const PLUGIN_NAME = "DefinePlugin";
350
354
  const VALUE_DEP_PREFIX = `webpack/${PLUGIN_NAME} `;
351
355
  const VALUE_DEP_MAIN = `webpack/${PLUGIN_NAME}_hash`;
352
356
  const TYPEOF_OPERATOR_REGEXP = /^typeof\s+/;
357
+ const EMPTY_OBJECT = {};
358
+
359
+ /** @typedef {Map<string, MergedDefinitionNode>} MergedDefinitionMap */
360
+ /** @typedef {CodeValue | MergedDefinitionMap} MergedDefinitionNode */
361
+
362
+ /**
363
+ * Merged view of the definitions of every DefinePlugin instance.
364
+ * @typedef {object} MergedDefinitions
365
+ * @property {Compilation} compilation the compilation
366
+ * @property {Definitions} definitions flat definitions
367
+ * @property {MergedDefinitionMap} root nested view (dotted keys expanded)
368
+ * @property {Map<string, Set<string>>} finalByNestedKey final key segments by nested object key
369
+ * @property {Map<string, Set<string>>} nestedByFinalKey nested object keys by final key segment
370
+ * @property {Map<string, string[]>} keysByPrefix definition keys below each dotted-key prefix
371
+ * @property {boolean} hasRuntimeValue renders are module-dependent (RuntimeValue present)
372
+ * @property {WeakMap<MergedDefinitionMap, string>} codeCache rendered code per node (static trees only)
373
+ * @property {Logger} logger the logger
374
+ */
375
+
376
+ /** @type {WeakMap<Compilation, MergedDefinitions>} */
377
+ const mergedDefinitionsMap = new WeakMap();
378
+
379
+ /**
380
+ * Whether a definition value is a plain object to expand into the nested view.
381
+ * @param {CodeValue} code definition value
382
+ * @returns {code is Definitions} true for a plain object
383
+ */
384
+ const isPlainObjectDefinition = (code) => {
385
+ if (!code || typeof code !== "object" || Array.isArray(code)) return false;
386
+ const proto = Object.getPrototypeOf(code);
387
+ return proto === Object.prototype || proto === null;
388
+ };
389
+
390
+ /**
391
+ * Object literal key code; `__proto__` must be computed to stay an own property.
392
+ * @param {string} key property key
393
+ * @returns {string} property key code
394
+ */
395
+ const toPropertyKey = (key) =>
396
+ key === "__proto__" ? '["__proto__"]' : JSON.stringify(key);
397
+
398
+ /**
399
+ * Whether a definition value contains a RuntimeValue (module-dependent code).
400
+ * @param {CodeValue} value definition value
401
+ * @returns {boolean} true when a RuntimeValue is contained
402
+ */
403
+ const containsRuntimeValue = (value) => {
404
+ if (value instanceof RuntimeValue) return true;
405
+ if (isObjectDefinition(value)) {
406
+ for (const key of Object.keys(value)) {
407
+ if (containsRuntimeValue(value[key])) return true;
408
+ }
409
+ }
410
+ return false;
411
+ };
412
+
413
+ /**
414
+ * Sets a definition value on a node of the nested view, merging plain objects.
415
+ * @param {MergedDefinitionMap} node node
416
+ * @param {string} key key
417
+ * @param {CodeValue} value definition value
418
+ */
419
+ const setMergedValue = (node, key, value) => {
420
+ const existing = node.get(key);
421
+ if (isPlainObjectDefinition(value)) {
422
+ const map =
423
+ existing instanceof Map
424
+ ? existing
425
+ : /** @type {MergedDefinitionMap} */ (new Map());
426
+ if (map !== existing) node.set(key, map);
427
+ for (const k of Object.keys(value)) setMergedValue(map, k, value[k]);
428
+ } else {
429
+ node.set(key, value);
430
+ }
431
+ };
432
+
433
+ /**
434
+ * Inserts a definition key path into the nested view.
435
+ * @param {MergedDefinitionMap} root root node
436
+ * @param {string[]} path dot-separated key path
437
+ * @param {CodeValue} value definition value
438
+ */
439
+ const insertMergedDefinition = (root, path, value) => {
440
+ let node = root;
441
+ for (let i = 0; i < path.length - 1; i++) {
442
+ let next = node.get(path[i]);
443
+ if (next === undefined && !node.has(path[i])) {
444
+ next = /** @type {MergedDefinitionMap} */ (new Map());
445
+ node.set(path[i], next);
446
+ } else if (!(next instanceof Map)) {
447
+ // deeper keys cannot merge into a non-object value
448
+ return;
449
+ }
450
+ node = next;
451
+ }
452
+ setMergedValue(node, path[path.length - 1], value);
453
+ };
454
+
455
+ /**
456
+ * Returns the merged view of all definitions (built once per compilation).
457
+ * @param {Compilation} compilation the compilation
458
+ * @returns {MergedDefinitions} merged definitions
459
+ */
460
+ const getMergedDefinitions = (compilation) => {
461
+ const cached = mergedDefinitionsMap.get(compilation);
462
+ if (cached) return cached;
463
+
464
+ const definitions = DefinePlugin.getCompilationHooks(
465
+ compilation
466
+ ).definitions.call({});
467
+ /** @type {MergedDefinitionMap} */
468
+ const root = new Map();
469
+ /** @type {Map<string, Set<string>>} */
470
+ const finalByNestedKey = new Map();
471
+ /** @type {Map<string, Set<string>>} */
472
+ const nestedByFinalKey = new Map();
473
+ /**
474
+ * @param {Map<string, Set<string>>} map map
475
+ * @param {string} key key
476
+ * @param {string} value value
477
+ */
478
+ const addToMap = (map, key, value) => {
479
+ const set = map.get(key);
480
+ if (set) {
481
+ set.add(value);
482
+ } else {
483
+ map.set(key, new Set([value]));
484
+ }
485
+ };
486
+ let hasRuntimeValue = false;
487
+ /** @type {Map<string, string[]>} */
488
+ const keysByPrefix = new Map();
489
+ for (const key of Object.keys(definitions)) {
490
+ if (TYPEOF_OPERATOR_REGEXP.test(key)) continue;
491
+ const code = definitions[key];
492
+ insertMergedDefinition(root, key.split("."), code);
493
+ if (!hasRuntimeValue && containsRuntimeValue(code)) hasRuntimeValue = true;
494
+ // group this key under every ancestor prefix (value deps of object reads)
495
+ for (
496
+ let idx = key.indexOf(".");
497
+ idx !== -1;
498
+ idx = key.indexOf(".", idx + 1)
499
+ ) {
500
+ const prefix = key.slice(0, idx);
501
+ const keys = keysByPrefix.get(prefix);
502
+ if (keys) {
503
+ keys.push(key);
504
+ } else {
505
+ keysByPrefix.set(prefix, [key]);
506
+ }
507
+ }
508
+ if (!code || typeof code === "object") continue;
509
+ const idx = key.lastIndexOf(".");
510
+ if (idx <= 0 || idx >= key.length - 1) continue;
511
+ const nested = key.slice(0, idx);
512
+ const final = key.slice(idx + 1);
513
+ addToMap(finalByNestedKey, nested, final);
514
+ addToMap(nestedByFinalKey, final, nested);
515
+ }
516
+ const result = {
517
+ compilation,
518
+ definitions,
519
+ root,
520
+ finalByNestedKey,
521
+ nestedByFinalKey,
522
+ keysByPrefix,
523
+ hasRuntimeValue,
524
+ codeCache: new WeakMap(),
525
+ logger: compilation.getLogger("webpack.DefinePlugin")
526
+ };
527
+ mergedDefinitionsMap.set(compilation, result);
528
+ return result;
529
+ };
530
+
531
+ /**
532
+ * Returns the merged definition node for a definition key.
533
+ * @param {Compilation} compilation the compilation
534
+ * @param {string} key definition key
535
+ * @returns {MergedDefinitionNode | undefined} merged node
536
+ */
537
+ const getMergedDefinitionNode = (compilation, key) => {
538
+ /** @type {MergedDefinitionNode | undefined} */
539
+ let node = getMergedDefinitions(compilation).root;
540
+ for (const part of key.split(".")) {
541
+ if (!(node instanceof Map)) return;
542
+ node = node.get(part);
543
+ }
544
+ return node;
545
+ };
546
+
547
+ /**
548
+ * Returns a merged map node converted to an object literal code string
549
+ * (no ASI wrapping). Static renders (no key filter, no RuntimeValue) are
550
+ * cached per compilation.
551
+ * @param {MergedDefinitions} merged merged definitions
552
+ * @param {MergedDefinitionMap} node merged map node
553
+ * @param {JavascriptParser} parser Parser
554
+ * @param {string} key the defined key
555
+ * @param {ObjKeys=} objKeys used keys
556
+ * @returns {string} code
557
+ */
558
+ const stringifyMergedNode = (merged, node, parser, key, objKeys) => {
559
+ const cacheable = objKeys === undefined && !merged.hasRuntimeValue;
560
+ if (cacheable) {
561
+ const cached = merged.codeCache.get(node);
562
+ if (cached !== undefined) return cached;
563
+ }
564
+ let keys = [...node.keys()];
565
+ if (objKeys) {
566
+ keys = objKeys.size === 0 ? [] : keys.filter((k) => objKeys.has(k));
567
+ }
568
+ const code = `{${keys
569
+ .map((k) => {
570
+ const value = /** @type {MergedDefinitionNode} */ (node.get(k));
571
+ return `${toPropertyKey(k)}:${
572
+ value instanceof Map
573
+ ? stringifyMergedNode(merged, value, parser, k)
574
+ : toCode(
575
+ value,
576
+ parser,
577
+ merged.compilation.valueCacheVersions,
578
+ k,
579
+ merged.compilation.runtimeTemplate,
580
+ merged.logger,
581
+ null
582
+ )
583
+ }`;
584
+ })
585
+ .join(",")}}`;
586
+ if (cacheable) merged.codeCache.set(node, code);
587
+ return code;
588
+ };
589
+
590
+ /**
591
+ * Renders a merged definition node to raw code (object literal for map nodes).
592
+ * @param {Compilation} compilation the compilation
593
+ * @param {JavascriptParser} parser Parser
594
+ * @param {MergedDefinitionNode} node merged node
595
+ * @param {string} key the defined key
596
+ * @param {ObjKeys=} objKeys used keys
597
+ * @returns {string} code
598
+ */
599
+ const stringifyMergedDefinition = (compilation, parser, node, key, objKeys) => {
600
+ const merged = getMergedDefinitions(compilation);
601
+ return node instanceof Map
602
+ ? stringifyMergedNode(merged, node, parser, key, objKeys)
603
+ : toCode(
604
+ node,
605
+ parser,
606
+ compilation.valueCacheVersions,
607
+ key,
608
+ compilation.runtimeTemplate,
609
+ merged.logger,
610
+ null
611
+ );
612
+ };
613
+
353
614
  const WEBPACK_REQUIRE_FUNCTION_REGEXP = new RegExp(
354
615
  `${RuntimeGlobals.require}\\s*(!?\\.)`
355
616
  );
356
- const WEBPACK_REQUIRE_IDENTIFIER_REGEXP = new RegExp(RuntimeGlobals.require);
617
+
618
+ /**
619
+ * Runtime requirements of replacement code referencing the require function.
620
+ * @param {string} code replacement code
621
+ * @returns {string[] | undefined} runtime requirements
622
+ */
623
+ const getRuntimeRequirements = (code) => {
624
+ // fast path: most replacement code never references the require function
625
+ if (!code.includes(RuntimeGlobals.require)) return;
626
+ return WEBPACK_REQUIRE_FUNCTION_REGEXP.test(code)
627
+ ? [RuntimeGlobals.require]
628
+ : [RuntimeGlobals.requireScope];
629
+ };
357
630
 
358
631
  /**
359
632
  * Defines the define plugin hooks type used by this module.
@@ -400,15 +673,6 @@ class DefinePlugin {
400
673
  ...definitions
401
674
  }));
402
675
 
403
- /**
404
- * @type {Map<string, Set<string>>}
405
- */
406
- const finalByNestedKey = new Map();
407
- /**
408
- * @type {Map<string, Set<string>>}
409
- */
410
- const nestedByFinalKey = new Map();
411
-
412
676
  const logger = compilation.getLogger("webpack.DefinePlugin");
413
677
  compilation.dependencyTemplates.set(
414
678
  ConstDependency,
@@ -428,6 +692,9 @@ class DefinePlugin {
428
692
  * @returns {void}
429
693
  */
430
694
  const handler = (parser) => {
695
+ // built lazily here: every definitions hook is tapped by the time
696
+ // parsers are created, and the result is cached per compilation
697
+ const mergedDefinitions = getMergedDefinitions(compilation);
431
698
  /** @type {Set<string>} */
432
699
  const hooked = new Set();
433
700
  const mainValue =
@@ -506,6 +773,10 @@ class DefinePlugin {
506
773
  const firstKey = splittedKey[0];
507
774
  for (const [i, _] of splittedKey.slice(1).entries()) {
508
775
  const fullKey = prefix + splittedKey.slice(0, i + 1).join(".");
776
+ // `import.meta` is a MetaProperty, not an identifier that can be
777
+ // aliased: an alias declaration would keep the raw MetaProperty
778
+ // in the output, so never enable renaming for its prefixes
779
+ if (fullKey === "import" || fullKey === "import.meta") continue;
509
780
  parser.hooks.canRename.for(fullKey).tap(PLUGIN_NAME, () => {
510
781
  addValueDependency(key);
511
782
  if (
@@ -518,7 +789,9 @@ class DefinePlugin {
518
789
  }
519
790
  if (prefix === "") {
520
791
  const final = splittedKey[splittedKey.length - 1];
521
- const nestedSet = nestedByFinalKey.get(final);
792
+ // aggregated over all instances so keys split across
793
+ // several DefinePlugins can still be destructured together
794
+ const nestedSet = mergedDefinitions.nestedByFinalKey.get(final);
522
795
  if (!nestedSet || nestedSet.size <= 0) return;
523
796
  for (const nested of /** @type {Set<string>} */ (nestedSet)) {
524
797
  if (nested && !hooked.has(nested)) {
@@ -545,17 +818,19 @@ class DefinePlugin {
545
818
  }
546
819
  /** @type {Definitions} */
547
820
  const obj = Object.create(null);
548
- const finalSet = finalByNestedKey.get(nested);
821
+ const finalSet =
822
+ mergedDefinitions.finalByNestedKey.get(nested);
549
823
  for (const { id } of destructed) {
550
824
  const fullKey = `${nested}.${id}`;
551
825
  if (
552
826
  !finalSet ||
553
827
  !finalSet.has(id) ||
554
- !definitions[fullKey]
828
+ !mergedDefinitions.definitions[fullKey]
555
829
  ) {
556
830
  return;
557
831
  }
558
- obj[id] = definitions[fullKey];
832
+ addValueDependency(fullKey);
833
+ obj[id] = mergedDefinitions.definitions[fullKey];
559
834
  }
560
835
  let strCode = stringifyObj(
561
836
  obj,
@@ -643,16 +918,11 @@ class DefinePlugin {
643
918
  strCode = `${parser.scope.inShorthand}:${strCode}`;
644
919
  }
645
920
 
646
- if (WEBPACK_REQUIRE_FUNCTION_REGEXP.test(strCode)) {
647
- return toConstantDependency(parser, strCode, [
648
- RuntimeGlobals.require
649
- ])(expr);
650
- } else if (WEBPACK_REQUIRE_IDENTIFIER_REGEXP.test(strCode)) {
651
- return toConstantDependency(parser, strCode, [
652
- RuntimeGlobals.requireScope
653
- ])(expr);
654
- }
655
- return toConstantDependency(parser, strCode)(expr);
921
+ return toConstantDependency(
922
+ parser,
923
+ strCode,
924
+ getRuntimeRequirements(strCode)
925
+ )(expr);
656
926
  });
657
927
  }
658
928
  parser.hooks.evaluateTypeof.for(key).tap(PLUGIN_NAME, (expr) => {
@@ -710,6 +980,27 @@ class DefinePlugin {
710
980
  * @returns {void}
711
981
  */
712
982
  const applyObjectDefine = (key, obj) => {
983
+ const mergedNode = getMergedDefinitionNode(compilation, key);
984
+ /** @type {MergedDefinitionNode} */
985
+ const definition =
986
+ mergedNode === undefined
987
+ ? /** @type {CodeValue} */ (obj)
988
+ : mergedNode;
989
+ // value dependencies of a whole-object read: the key itself and
990
+ // every dotted definition key below it (from any instance)
991
+ /** @type {[string, ValueCacheVersion][]} */
992
+ const objectValueDependencies = [];
993
+ for (const defKey of [
994
+ key,
995
+ ...(mergedDefinitions.keysByPrefix.get(key) || [])
996
+ ]) {
997
+ const name = VALUE_DEP_PREFIX + defKey;
998
+ objectValueDependencies.push([
999
+ name,
1000
+ /** @type {ValueCacheVersion} */
1001
+ (compilation.valueCacheVersions.get(name))
1002
+ ]);
1003
+ }
713
1004
  parser.hooks.canRename.for(key).tap(PLUGIN_NAME, () => {
714
1005
  addValueDependency(key);
715
1006
  return true;
@@ -737,32 +1028,55 @@ class DefinePlugin {
737
1028
  }
738
1029
  );
739
1030
  parser.hooks.expression.for(key).tap(PLUGIN_NAME, (expr) => {
740
- addValueDependency(key);
741
- let strCode = stringifyObj(
742
- obj,
743
- parser,
744
- compilation.valueCacheVersions,
745
- key,
746
- runtimeTemplate,
747
- logger,
748
- !parser.isAsiPosition(/** @type {Range} */ (expr.range)[0]),
749
- getObjKeys(parser.destructuringAssignmentPropertiesFor(expr))
1031
+ const valueDependencies =
1032
+ /** @type {NonNullable<NormalModuleBuildInfo["valueDependencies"]>} */
1033
+ (
1034
+ /** @type {NormalModuleBuildInfo} */
1035
+ (parser.state.module.buildInfo).valueDependencies
1036
+ );
1037
+ for (const [name, version] of objectValueDependencies) {
1038
+ valueDependencies.set(name, version);
1039
+ }
1040
+ // render the merged view so dotted keys (of any instance)
1041
+ // are part of whole-object and destructured reads
1042
+ const objKeys = getObjKeys(
1043
+ parser.destructuringAssignmentPropertiesFor(expr)
1044
+ );
1045
+ const asiSafe = !parser.isAsiPosition(
1046
+ /** @type {Range} */ (expr.range)[0]
750
1047
  );
1048
+ let strCode;
1049
+ if (definition instanceof Map) {
1050
+ const code = stringifyMergedNode(
1051
+ mergedDefinitions,
1052
+ definition,
1053
+ parser,
1054
+ key,
1055
+ objKeys
1056
+ );
1057
+ strCode = asiSafe ? `(${code})` : `;(${code})`;
1058
+ } else {
1059
+ strCode = toCode(
1060
+ definition,
1061
+ parser,
1062
+ compilation.valueCacheVersions,
1063
+ key,
1064
+ runtimeTemplate,
1065
+ logger,
1066
+ asiSafe,
1067
+ objKeys
1068
+ );
1069
+ }
751
1070
 
752
1071
  if (parser.scope.inShorthand) {
753
1072
  strCode = `${parser.scope.inShorthand}:${strCode}`;
754
1073
  }
755
1074
 
756
- if (WEBPACK_REQUIRE_FUNCTION_REGEXP.test(strCode)) {
757
- return toConstantDependency(parser, strCode, [
758
- RuntimeGlobals.require
759
- ])(expr);
760
- } else if (WEBPACK_REQUIRE_IDENTIFIER_REGEXP.test(strCode)) {
761
- return toConstantDependency(parser, strCode, [
762
- RuntimeGlobals.requireScope
763
- ])(expr);
764
- }
765
- return toConstantDependency(parser, strCode)(expr);
1075
+ return toConstantDependency(
1076
+ parser,
1077
+ strCode,
1078
+ getRuntimeRequirements(strCode)
1079
+ )(expr);
766
1080
  });
767
1081
  // A property access not defined on the object resolves to `undefined`
768
1082
  // and the whole object is never inlined (issue #15559). Keyed by the
@@ -775,10 +1089,11 @@ class DefinePlugin {
775
1089
  const chainPrefix = chainParts.slice(isMeta ? 2 : 1);
776
1090
  /**
777
1091
  * Whether a member chain reads a property that is not defined.
1092
+ * Walks the merged view so dotted keys of every instance count.
778
1093
  * Collects every define key consulted so the caller can record a
779
1094
  * value dependency on each (a sibling key like `OBJECT.SUB2` affects
780
1095
  * the result even though `OBJECT` registered the handler).
781
- * `member in value` keeps inherited members (e.g. `toString`) defined.
1096
+ * Inherited members (e.g. `toString`) stay defined.
782
1097
  * @param {Members} members chain members (after the root)
783
1098
  * @param {string[]} deps consulted define keys (mutated)
784
1099
  * @returns {boolean} true when the access resolves to `undefined`
@@ -788,24 +1103,40 @@ class DefinePlugin {
788
1103
  for (let i = 0; i < chainPrefix.length; i++) {
789
1104
  if (members[i] !== chainPrefix[i]) return false;
790
1105
  }
791
- /** @type {CodeValue} */
792
- let value = /** @type {CodeValue} */ (obj);
1106
+ /** @type {MergedDefinitionNode | undefined} */
1107
+ let value = definition;
793
1108
  let path = key;
794
1109
  for (let i = chainPrefix.length; i < members.length; i++) {
795
- // a leaf with members left is a real property access on a value
796
- if (!isObjectDefinition(value)) return false;
797
1110
  const member = members[i];
798
1111
  const nextPath = `${path}.${member}`;
799
- if (member in value) {
800
- value = value[member];
801
- } else if (
802
- Object.prototype.hasOwnProperty.call(definitions, nextPath)
803
- ) {
804
- // defined via a dotted sibling key, e.g. `OBJECT.SUB2`
805
- deps.push(nextPath);
806
- value = definitions[nextPath];
1112
+ if (value instanceof Map) {
1113
+ if (value.has(member)) {
1114
+ deps.push(nextPath);
1115
+ value = value.get(member);
1116
+ } else if (member in EMPTY_OBJECT) {
1117
+ return false;
1118
+ } else {
1119
+ return true;
1120
+ }
1121
+ } else if (isObjectDefinition(value)) {
1122
+ // non-expandable object leaf (e.g. an array)
1123
+ if (member in value) {
1124
+ value = /** @type {Definitions} */ (value)[member];
1125
+ } else if (
1126
+ Object.prototype.hasOwnProperty.call(
1127
+ mergedDefinitions.definitions,
1128
+ nextPath
1129
+ )
1130
+ ) {
1131
+ // defined via a dotted sibling key, e.g. `OBJECT.SUB2`
1132
+ deps.push(nextPath);
1133
+ value = mergedDefinitions.definitions[nextPath];
1134
+ } else {
1135
+ return true;
1136
+ }
807
1137
  } else {
808
- return true;
1138
+ // a leaf with members left is a real property access on a value
1139
+ return false;
809
1140
  }
810
1141
  path = nextPath;
811
1142
  }
@@ -891,48 +1222,6 @@ class DefinePlugin {
891
1222
  }
892
1223
  };
893
1224
 
894
- /**
895
- * Walk definitions for keys.
896
- * @param {Definitions} definitions Definitions map
897
- * @returns {void}
898
- */
899
- const walkDefinitionsForKeys = (definitions) => {
900
- /**
901
- * Adds the provided map to the define plugin.
902
- * @param {Map<string, Set<string>>} map Map
903
- * @param {string} key key
904
- * @param {string} value v
905
- * @returns {void}
906
- */
907
- const addToMap = (map, key, value) => {
908
- if (map.has(key)) {
909
- /** @type {Set<string>} */
910
- (map.get(key)).add(value);
911
- } else {
912
- map.set(key, new Set([value]));
913
- }
914
- };
915
- for (const key of Object.keys(definitions)) {
916
- const code = definitions[key];
917
- if (
918
- !code ||
919
- typeof code === "object" ||
920
- TYPEOF_OPERATOR_REGEXP.test(key)
921
- ) {
922
- continue;
923
- }
924
- const idx = key.lastIndexOf(".");
925
- if (idx <= 0 || idx >= key.length - 1) {
926
- continue;
927
- }
928
- const nested = key.slice(0, idx);
929
- const final = key.slice(idx + 1);
930
- addToMap(finalByNestedKey, nested, final);
931
- addToMap(nestedByFinalKey, final, nested);
932
- }
933
- };
934
-
935
- walkDefinitionsForKeys(definitions);
936
1225
  walkDefinitionsForValues(definitions, "");
937
1226
 
938
1227
  compilation.valueCacheVersions.set(
@@ -952,3 +1241,9 @@ DefinePlugin.getCompilationHooks = createHooksRegistry(
952
1241
  );
953
1242
 
954
1243
  module.exports = DefinePlugin;
1244
+ module.exports.VALUE_DEP_MAIN = VALUE_DEP_MAIN;
1245
+ module.exports.VALUE_DEP_PREFIX = VALUE_DEP_PREFIX;
1246
+ module.exports.getMergedDefinitionNode = getMergedDefinitionNode;
1247
+ module.exports.getRuntimeRequirements = getRuntimeRequirements;
1248
+ module.exports.stringifyMergedDefinition = stringifyMergedDefinition;
1249
+ module.exports.toPropertyKey = toPropertyKey;
package/lib/Entrypoint.js CHANGED
@@ -11,7 +11,7 @@ const SortableSet = require("./util/SortableSet");
11
11
  /** @typedef {import("../declarations/WebpackOptions").EntryDescriptionNormalized} EntryDescription */
12
12
  /** @typedef {import("./Chunk")} Chunk */
13
13
 
14
- /** @typedef {{ name?: string } & Omit<EntryDescription, "import">} EntryOptions */
14
+ /** @typedef {{ name?: string, worklet?: boolean } & Omit<EntryDescription, "import">} EntryOptions */
15
15
 
16
16
  /**
17
17
  * Entrypoint serves as an encapsulation primitive for chunks that are
@@ -55,7 +55,7 @@ class ExportsInfoApiPlugin {
55
55
  null,
56
56
  members[0]
57
57
  );
58
- dep.loc = /** @type {DependencyLocation} */ (expr.loc);
58
+ dep.loc = parser.getLocation(expr);
59
59
  parser.state.module.addDependency(dep);
60
60
  return true;
61
61
  });
@@ -66,7 +66,7 @@ class ExportsInfoApiPlugin {
66
66
  "true",
67
67
  /** @type {Range} */ (expr.range)
68
68
  );
69
- dep.loc = /** @type {DependencyLocation} */ (expr.loc);
69
+ dep.loc = parser.getLocation(expr);
70
70
  parser.state.module.addPresentationalDependency(dep);
71
71
  return true;
72
72
  });