webpack 5.110.3 → 5.111.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 (208) hide show
  1. package/README.md +5 -0
  2. package/lib/APIPlugin.js +23 -7
  3. package/lib/AutomaticPrefetchPlugin.js +1 -1
  4. package/lib/Cache.js +8 -3
  5. package/lib/CacheFacade.js +1 -1
  6. package/lib/CircularModulesPlugin.js +157 -55
  7. package/lib/CleanPlugin.js +2 -2
  8. package/lib/Compilation.js +320 -302
  9. package/lib/Compiler.js +209 -46
  10. package/lib/ContextModule.js +17 -81
  11. package/lib/ContextModuleFactory.js +1 -1
  12. package/lib/CopyPlugin.js +1054 -0
  13. package/lib/DefinePlugin.js +24 -8
  14. package/lib/ExternalModule.js +41 -14
  15. package/lib/FileSystemInfo.js +17 -14
  16. package/lib/FlagDependencyExportsPlugin.js +45 -21
  17. package/lib/HotModuleReplacementPlugin.js +53 -7
  18. package/lib/JavascriptMetaInfoPlugin.js +5 -3
  19. package/lib/MainTemplate.js +5 -1
  20. package/lib/Module.js +16 -7
  21. package/lib/MultiCompiler.js +1 -1
  22. package/lib/MultiWatching.js +1 -1
  23. package/lib/NormalModule.js +45 -12
  24. package/lib/NormalModuleFactory.js +1 -1
  25. package/lib/RuntimeGlobals.js +21 -7
  26. package/lib/RuntimeModule.js +28 -12
  27. package/lib/RuntimePlugin.js +30 -3
  28. package/lib/RuntimeTemplate.js +780 -475
  29. package/lib/SourceMapDevToolPlugin.js +1 -1
  30. package/lib/Watching.js +9 -0
  31. package/lib/WebpackOptionsApply.js +84 -91
  32. package/lib/asset/AssetGenerator.js +25 -8
  33. package/lib/asset/AssetModule.js +3 -0
  34. package/lib/asset/WebManifestParser.js +7 -5
  35. package/lib/cache/AddBuildDependenciesPlugin.js +33 -4
  36. package/lib/cache/IdleFileCachePlugin.js +2 -2
  37. package/lib/cache/PackFileCacheStrategy.js +14 -1
  38. package/lib/config/browserslistTargetHandler.js +19 -0
  39. package/lib/config/defaults.js +86 -50
  40. package/lib/config/normalization.js +82 -12
  41. package/lib/config/target.js +10 -0
  42. package/lib/container/ContainerReferencePlugin.js +6 -0
  43. package/lib/container/RemoteRuntimeModule.js +9 -0
  44. package/lib/container/declaredRemotes.js +39 -0
  45. package/lib/css/CssGenerator.js +8 -0
  46. package/lib/css/CssInjectStyleRuntimeModule.js +9 -0
  47. package/lib/css/CssLoadingRuntimeModule.js +94 -36
  48. package/lib/css/CssModule.js +1 -1
  49. package/lib/css/CssModulesPlugin.js +7 -6
  50. package/lib/css/CssParser.js +144 -11
  51. package/lib/css/CssServerStylesRuntimeModule.js +9 -0
  52. package/lib/css/cssMinify.js +11 -3
  53. package/lib/css/data.js +2814 -678
  54. package/lib/css/syntax.js +4082 -248
  55. package/lib/debug/ProfilingPlugin.js +4 -0
  56. package/lib/dependencies/AMDDefineDependencyParserPlugin.js +6 -3
  57. package/lib/dependencies/AMDRuntimeModules.js +18 -0
  58. package/lib/dependencies/CommonJsExportRequireDependency.js +3 -1
  59. package/lib/dependencies/CommonJsExportsParserPlugin.js +12 -13
  60. package/lib/dependencies/CommonJsImportsParserPlugin.js +1 -0
  61. package/lib/dependencies/CommonJsPlugin.js +19 -3
  62. package/lib/dependencies/CommonJsRequireDependency.js +14 -5
  63. package/lib/dependencies/CssIcssExportDependency.js +7 -1
  64. package/lib/dependencies/HarmonyCompatibilityDependency.js +58 -4
  65. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +8 -3
  66. package/lib/dependencies/HarmonyExportExpressionDependency.js +44 -29
  67. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +71 -13
  68. package/lib/dependencies/HarmonyExportInitFragment.js +99 -19
  69. package/lib/dependencies/HarmonyExportSpecifierDependency.js +18 -30
  70. package/lib/dependencies/HarmonyImportBareSideEffectDependency.js +59 -0
  71. package/lib/dependencies/HarmonyImportDependency.js +6 -1
  72. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +8 -1
  73. package/lib/dependencies/HarmonyImportSpecifierDependency.js +24 -1
  74. package/lib/dependencies/HarmonyModulesPlugin.js +20 -0
  75. package/lib/dependencies/HtmlEntryDependency.js +50 -0
  76. package/lib/dependencies/ImportMetaMainDependency.js +104 -0
  77. package/lib/dependencies/ImportMetaPlugin.js +59 -15
  78. package/lib/dependencies/SystemRuntimeModule.js +9 -0
  79. package/lib/dependencies/WorkerDependency.js +1 -2
  80. package/lib/dependencies/WorkletDependency.js +1 -2
  81. package/lib/dll/DelegatedModule.js +18 -1
  82. package/lib/dll/DllReferencePlugin.js +11 -8
  83. package/lib/dll/LibManifestPlugin.js +1 -1
  84. package/lib/errors/AnalyzableBailoutsWarning.js +41 -0
  85. package/lib/errors/DuplicateModulesWarning.js +12 -7
  86. package/lib/errors/EmptyCopyPatternWarning.js +26 -0
  87. package/lib/errors/ExternalStarReexportError.js +44 -0
  88. package/lib/errors/MissingSourceMapsWarning.js +36 -0
  89. package/lib/errors/ModuleParseError.js +2 -1
  90. package/lib/errors/UnusedAssetsWarning.js +36 -0
  91. package/lib/errors/UnusedFederationWarning.js +35 -0
  92. package/lib/errors/UnusedModulesWarning.js +38 -0
  93. package/lib/esm/ExportWebpackRequireRuntimeModule.js +9 -0
  94. package/lib/esm/ModuleChunkFormatPlugin.js +28 -3
  95. package/lib/esm/ModuleChunkLoadingPlugin.js +30 -11
  96. package/lib/esm/ModuleChunkLoadingRuntimeModule.js +92 -60
  97. package/lib/hmr/HotModuleReplacement.runtime.js +8 -2
  98. package/lib/hmr/HotModuleReplacementRuntimeModule.js +9 -0
  99. package/lib/html/HtmlGenerator.js +11 -5
  100. package/lib/html/HtmlModulesPlugin.js +331 -62
  101. package/lib/html/HtmlParser.js +13 -6
  102. package/lib/html/builtinEmbeddedRenderer.js +107 -0
  103. package/lib/html/data.js +121 -7
  104. package/lib/html/htmlMinify.js +84 -113
  105. package/lib/html/syntax.js +763 -426
  106. package/lib/ids/HashedModuleIdsPlugin.js +2 -1
  107. package/lib/index.js +3 -0
  108. package/lib/javascript/JavascriptModule.js +1 -0
  109. package/lib/javascript/JavascriptModulesPlugin.js +52 -24
  110. package/lib/javascript/JavascriptParser.js +1255 -728
  111. package/lib/javascript/StartupHelpers.js +27 -3
  112. package/lib/javascript/data.js +172 -0
  113. package/lib/javascript/grammar.js +5546 -0
  114. package/lib/javascript/parser.js +1494 -0
  115. package/lib/javascript/regexp.js +1762 -0
  116. package/lib/javascript/regexpData.js +51 -0
  117. package/lib/javascript/syntax.js +8696 -5225
  118. package/lib/library/ModuleLibraryPlugin.js +116 -5
  119. package/lib/node/ReadFileChunkLoadingRuntimeModule.js +22 -0
  120. package/lib/node/RequireChunkLoadingRuntimeModule.js +22 -0
  121. package/lib/optimize/ConcatenatedModule.js +97 -20
  122. package/lib/optimize/ConstExportsPlugin.js +50 -39
  123. package/lib/optimize/InlineExports.js +20 -123
  124. package/lib/optimize/MangleExportsPlugin.js +10 -0
  125. package/lib/optimize/ModuleConcatenationPlugin.js +24 -1
  126. package/lib/optimize/RealContentHashPlugin.js +68 -9
  127. package/lib/optimize/SideEffectsFlagPlugin.js +17 -9
  128. package/lib/performance/AnalyzableBailoutsPlugin.js +115 -0
  129. package/lib/performance/CacheEffectivenessPlugin.js +4 -3
  130. package/lib/performance/DuplicateModulesPlugin.js +57 -13
  131. package/lib/performance/EvalUsagePlugin.js +5 -2
  132. package/lib/performance/MissingSourceMapsPlugin.js +115 -0
  133. package/lib/performance/PureAnnotationsPlugin.js +6 -3
  134. package/lib/performance/TopLevelThisPlugin.js +5 -4
  135. package/lib/performance/UnusedAssetsPlugin.js +109 -0
  136. package/lib/performance/UnusedFederationPlugin.js +147 -0
  137. package/lib/performance/UnusedModulesPlugin.js +141 -0
  138. package/lib/performance/UnusedReexportsPlugin.js +1 -55
  139. package/lib/performance/isOnlyReexported.js +65 -0
  140. package/lib/prefetch/ChunkPrefetchFunctionRuntimeModule.js +25 -5
  141. package/lib/prefetch/ChunkPrefetchPreloadPlugin.js +2 -0
  142. package/lib/prefetch/ChunkPrefetchStartupRuntimeModule.js +9 -0
  143. package/lib/prefetch/ChunkPrefetchTriggerRuntimeModule.js +9 -0
  144. package/lib/prefetch/ChunkPreloadTriggerRuntimeModule.js +9 -0
  145. package/lib/prefetch/ResourceHintPlugin.js +1 -2
  146. package/lib/prefetch/ResourceHintRuntimeModule.js +9 -0
  147. package/lib/prefetch/StartupAssetHintRuntimeModule.js +9 -0
  148. package/lib/rules/RuleSetCompiler.js +211 -4
  149. package/lib/runtime/AsyncModuleRuntimeModule.js +100 -66
  150. package/lib/runtime/AutoPublicPathRuntimeModule.js +9 -0
  151. package/lib/runtime/BaseUriRuntimeModule.js +9 -0
  152. package/lib/runtime/ChunkNameRuntimeModule.js +9 -0
  153. package/lib/runtime/EnsureChunkRuntimeModule.js +35 -16
  154. package/lib/runtime/GetChunkFilenameRuntimeModule.js +9 -0
  155. package/lib/runtime/GetFullHashRuntimeModule.js +9 -0
  156. package/lib/runtime/GetMainFilenameRuntimeModule.js +9 -0
  157. package/lib/runtime/GetWorkletBootstrapRuntimeModule.js +9 -0
  158. package/lib/runtime/GlobalRuntimeModule.js +9 -0
  159. package/lib/runtime/HasOwnPropertyRuntimeModule.js +9 -0
  160. package/lib/runtime/HelperRuntimeModule.js +10 -0
  161. package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +330 -219
  162. package/lib/runtime/NonceRuntimeModule.js +9 -0
  163. package/lib/runtime/OnChunksLoadedRuntimeModule.js +67 -20
  164. package/lib/runtime/PublicPathRuntimeModule.js +9 -0
  165. package/lib/runtime/RuntimeIdRuntimeModule.js +9 -0
  166. package/lib/runtime/SpecNamespaceObjectRuntimeModule.js +90 -0
  167. package/lib/runtime/StartupChunkDependenciesRuntimeModule.js +9 -0
  168. package/lib/runtime/StartupEntrypointRuntimeModule.js +9 -0
  169. package/lib/runtime/SystemContextRuntimeModule.js +9 -0
  170. package/lib/runtime/ToBinaryRuntimeModule.js +9 -0
  171. package/lib/serialization/ObjectMiddleware.js +138 -106
  172. package/lib/sharing/ConsumeSharedPlugin.js +12 -0
  173. package/lib/sharing/ConsumeSharedRuntimeModule.js +11 -0
  174. package/lib/sharing/ShareRuntimeModule.js +9 -0
  175. package/lib/sharing/declaredShared.js +47 -0
  176. package/lib/stats/DefaultStatsFactoryPlugin.js +3 -1
  177. package/lib/stats/DefaultStatsPrinterPlugin.js +3 -0
  178. package/lib/util/SourceProcessor.js +76 -69
  179. package/lib/util/async.js +292 -0
  180. package/lib/util/buildDiagnostics.js +69 -0
  181. package/lib/util/fs.js +27 -1
  182. package/lib/util/handlerKeys.js +40 -0
  183. package/lib/util/identifier.js +20 -0
  184. package/lib/util/internalSerializables.js +4 -0
  185. package/lib/util/registerExternalSerializer.js +6 -45
  186. package/lib/wasm-async/AsyncWasmCompileRuntimeModule.js +9 -0
  187. package/lib/wasm-async/AsyncWasmLoadingRuntimeModule.js +9 -0
  188. package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +9 -0
  189. package/lib/web/JsonpChunkLoadingRuntimeModule.js +36 -0
  190. package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +19 -0
  191. package/package.json +22 -16
  192. package/schemas/WebpackOptions.check.js +1 -1
  193. package/schemas/WebpackOptions.json +379 -66
  194. package/schemas/plugins/LoaderOptionsPlugin.check.js +1 -1
  195. package/schemas/plugins/ManifestPlugin.check.js +1 -1
  196. package/schemas/plugins/SourceMapDevToolPlugin.check.js +1 -1
  197. package/schemas/plugins/asset/AssetGeneratorOptions.check.js +1 -1
  198. package/schemas/plugins/asset/AssetResourceGeneratorOptions.check.js +1 -1
  199. package/schemas/plugins/container/ContainerPlugin.check.js +1 -1
  200. package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
  201. package/schemas/plugins/debug/ProfilingPlugin.check.js +1 -1
  202. package/schemas/plugins/dll/DllReferencePlugin.check.js +1 -1
  203. package/schemas/plugins/ids/HashedModuleIdsPlugin.check.js +1 -1
  204. package/schemas/plugins/schemes/HttpUriPlugin.check.js +1 -1
  205. package/types.d.ts +1414 -314
  206. package/lib/dependencies/ExportBindingInitFragment.js +0 -191
  207. package/lib/errors/EntrypointOverlapWarning.js +0 -45
  208. package/lib/performance/EntrypointOverlapPlugin.js +0 -122
@@ -14,9 +14,11 @@ const Template = require("../Template");
14
14
  const {
15
15
  InlinedUsedName,
16
16
  isExportInlined,
17
- isInlineEnabled
17
+ isInlineEnabled,
18
+ isInlineExportsEnabled
18
19
  } = require("../optimize/InlineExports");
19
20
  const {
21
+ getKnownExportNames,
20
22
  getMakeDeferredNamespaceModeFromExportsType
21
23
  } = require("../runtime/MakeDeferredNamespaceObjectRuntime");
22
24
  const { countIterable } = require("../util/IterableHelpers");
@@ -29,6 +31,9 @@ const {
29
31
  keyToRuntime
30
32
  } = require("../util/runtime");
31
33
  const HarmonyExportInitFragment = require("./HarmonyExportInitFragment");
34
+
35
+ const { ExportBindingType } = HarmonyExportInitFragment;
36
+
32
37
  const HarmonyImportDependency = require("./HarmonyImportDependency");
33
38
  const HarmonyLinkingError = require("./HarmonyLinkingError");
34
39
  const { ImportPhaseUtils } = require("./ImportPhase");
@@ -44,7 +49,8 @@ const processExportInfo = require("./processExportInfo");
44
49
  * RawReferencedExports,
45
50
  * ReferencedExports,
46
51
  * TRANSITIVE,
47
- * ExportInfoName
52
+ * ExportInfoName,
53
+ * UpdateHashContext
48
54
  * } from "../Dependency"
49
55
  */
50
56
  /** @import { DependencyTemplateContext } from "../DependencyTemplate" */
@@ -58,6 +64,7 @@ const processExportInfo = require("./processExportInfo");
58
64
  * } from "../Module"
59
65
  */
60
66
  /** @import ModuleGraph from "../ModuleGraph" */
67
+ /** @import Hash from "../util/Hash" */
61
68
  /**
62
69
  * @import ModuleGraphConnection, {
63
70
  * ConnectionState
@@ -829,6 +836,31 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
829
836
  };
830
837
  }
831
838
 
839
+ /**
840
+ * Updates the hash with the data contributed by this instance.
841
+ * @param {Hash} hash hash to be updated
842
+ * @param {UpdateHashContext} context context
843
+ * @returns {void}
844
+ */
845
+ updateHash(hash, context) {
846
+ const { chunkGraph, runtime } = context;
847
+ const moduleGraph = chunkGraph.moduleGraph;
848
+ if (!isInlineExportsEnabled(moduleGraph)) return;
849
+ const module = moduleGraph.getModule(this);
850
+ if (!module || !isInlineEnabled(module)) return;
851
+ const mode = this.getMode(moduleGraph, runtime);
852
+ if (mode.type !== "normal-reexport") return;
853
+ const exportsInfo = moduleGraph.getExportsInfo(module);
854
+ for (const item of /** @type {NormalReexportItem[]} */ (mode.items)) {
855
+ if (item.hidden || item.checked) continue;
856
+ const usedName = exportsInfo.getUsedName(item.ids, runtime);
857
+ if (usedName instanceof InlinedUsedName) {
858
+ hash.update(`${item.name}:${item.ids.join(".")}:`);
859
+ usedName.updateHash(hash);
860
+ }
861
+ }
862
+ }
863
+
832
864
  /**
833
865
  * Gets module evaluation side effects state.
834
866
  * @param {ModuleGraph} moduleGraph the module graph
@@ -1581,7 +1613,19 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS
1581
1613
  );
1582
1614
  break;
1583
1615
 
1584
- case "reexport-namespace-object":
1616
+ case "reexport-namespace-object": {
1617
+ let value = namespaceImportVar;
1618
+
1619
+ // The re-exported binding is the namespace itself, so it has to be
1620
+ // the same object every importer of that module is handed.
1621
+ if (
1622
+ importedModule.buildInfo &&
1623
+ importedModule.buildInfo.specNamespaceObject
1624
+ ) {
1625
+ runtimeRequirements.add(RuntimeGlobals.specNamespaceObject);
1626
+ value = `${RuntimeGlobals.specNamespaceObject}(${value})`;
1627
+ }
1628
+
1585
1629
  initFragments.push(
1586
1630
  this.getReexportFragment(
1587
1631
  module,
@@ -1589,12 +1633,13 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS
1589
1633
  moduleGraph
1590
1634
  .getExportsInfo(module)
1591
1635
  .getUsedName(/** @type {string} */ (mode.name), runtime),
1592
- namespaceImportVar,
1636
+ value,
1593
1637
  "",
1594
1638
  runtimeRequirements
1595
1639
  )
1596
1640
  );
1597
1641
  break;
1642
+ }
1598
1643
 
1599
1644
  case "normal-reexport": {
1600
1645
  // loop-invariants hoisted out of the per-item loop below (a barrel
@@ -1729,7 +1774,10 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS
1729
1774
 
1730
1775
  /** @type {ExportMap} */
1731
1776
  const map = new Map();
1732
- map.set(key, `/* ${comment} */ ${returnValue}`);
1777
+ map.set(key, {
1778
+ value: `/* ${comment} */ ${returnValue}`,
1779
+ type: ExportBindingType.Getter
1780
+ });
1733
1781
 
1734
1782
  return new HarmonyExportInitFragment(module.exportsArgument, map);
1735
1783
  }
@@ -1756,12 +1804,12 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS
1756
1804
 
1757
1805
  /** @type {ExportMap} */
1758
1806
  const map = new Map();
1759
- map.set(
1760
- key,
1761
- `/* reexport fake namespace object from non-harmony */ ${name}_namespace_cache || (${name}_namespace_cache = ${
1807
+ map.set(key, {
1808
+ value: `/* reexport fake namespace object from non-harmony */ ${name}_namespace_cache || (${name}_namespace_cache = ${
1762
1809
  RuntimeGlobals.createFakeNamespaceObject
1763
- }(${name}${fakeType ? `, ${fakeType}` : ""}))`
1764
- );
1810
+ }(${name}${fakeType ? `, ${fakeType}` : ""}))`,
1811
+ type: ExportBindingType.Getter
1812
+ });
1765
1813
 
1766
1814
  return [
1767
1815
  new InitFragment(
@@ -1800,10 +1848,20 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS
1800
1848
  const map = new Map();
1801
1849
  const moduleId = JSON.stringify(chunkGraph.getModuleId(module));
1802
1850
  const mode = getMakeDeferredNamespaceModeFromExportsType(exportsType);
1803
- map.set(
1804
- key,
1805
- `/* reexport deferred namespace object */ ${name}_deferred_namespace_cache || (${name}_deferred_namespace_cache = ${RuntimeGlobals.makeDeferredNamespaceObject}(${moduleId}, ${mode}))`
1851
+ const names = getKnownExportNames(
1852
+ chunkGraph.moduleGraph,
1853
+ module,
1854
+ exportsType
1855
+ );
1856
+ runtimeRequirements.add(
1857
+ names
1858
+ ? RuntimeGlobals.hasSealedDeferredNamespace
1859
+ : RuntimeGlobals.hasSynthesizedDeferredNamespace
1806
1860
  );
1861
+ map.set(key, {
1862
+ value: `/* reexport deferred namespace object */ ${name}_deferred_namespace_cache || (${name}_deferred_namespace_cache = ${RuntimeGlobals.makeDeferredNamespaceObject}(${moduleId}, ${mode}${names ? `, ${JSON.stringify(names)}` : ""}))`,
1863
+ type: ExportBindingType.Getter
1864
+ });
1807
1865
 
1808
1866
  return [
1809
1867
  new InitFragment(
@@ -35,9 +35,19 @@ const joinIterableWithComma = (iterable) => {
35
35
  return str;
36
36
  };
37
37
 
38
- /** @typedef {Map<UsedName, string>} ExportMap */
38
+ const ExportBindingType = Object.freeze({
39
+ Getter: 0b00,
40
+ Value: 0b01
41
+ });
42
+
43
+ /** @typedef {Map<UsedName, { value: string, type: typeof ExportBindingType.Getter | typeof ExportBindingType.Value }>} ExportMap */
39
44
  /** @typedef {Set<string>} UnusedExports */
40
- /** @import { OnDemandGeneration } from "./ExportBindingInitFragment" */
45
+
46
+ /**
47
+ * Lets a consumer take over the rendered `d()` call at its required position.
48
+ * End-position value bindings cannot move before the module body.
49
+ * @typedef {(source: string, placeAtEnd: boolean) => boolean} OnDemandGeneration
50
+ */
41
51
 
42
52
  /** @type {ExportMap} */
43
53
  const EMPTY_MAP = new Map();
@@ -71,6 +81,49 @@ class HarmonyExportInitFragment extends InitFragment {
71
81
  this.unusedExports = unusedExports;
72
82
  /** @type {OnDemandGeneration | undefined} */
73
83
  this.onDemand = onDemand;
84
+
85
+ this._generated = false;
86
+ this._defsValue = undefined;
87
+ this._defsGetter = undefined;
88
+ }
89
+
90
+ /**
91
+ * Returns the source code that will be included as initialization code.
92
+ * @param {GenerateContext} context context
93
+ * @returns {void}
94
+ */
95
+ _generate({ runtimeTemplate }) {
96
+ if (this._generated) return;
97
+ this._generated = true;
98
+
99
+ if (this.exportMap.size > 0) {
100
+ /** @type {string[]} */
101
+ const _defsValue = [];
102
+ const _defsGetter = [];
103
+ const orderedExportMap =
104
+ this.exportMap.size > 1
105
+ ? [...this.exportMap].sort(([a], [b]) => (a < b ? -1 : 1))
106
+ : this.exportMap;
107
+ for (const [key, { value, type }] of orderedExportMap) {
108
+ switch (type) {
109
+ case ExportBindingType.Getter:
110
+ _defsGetter.push(
111
+ `\n/* harmony export */ ${propertyName(
112
+ /** @type {string} */ (key)
113
+ )}: ${runtimeTemplate.returningFunction(value)}`
114
+ );
115
+ break;
116
+
117
+ case ExportBindingType.Value:
118
+ _defsValue.push(
119
+ `\n/* harmony export */ ${JSON.stringify(key)}, 0, ${value}`
120
+ );
121
+ }
122
+ }
123
+
124
+ this._defsGetter = _defsGetter;
125
+ this._defsValue = _defsValue;
126
+ }
74
127
  }
75
128
 
76
129
  /**
@@ -85,12 +138,15 @@ class HarmonyExportInitFragment extends InitFragment {
85
138
  /** @type {undefined | UnusedExports} */
86
139
  let unusedExports;
87
140
  let unusedExportsOwned = false;
141
+ /** @type {OnDemandGeneration=} */
142
+ let onDemand;
88
143
 
89
144
  for (const fragment of fragments) {
90
145
  if (fragment.exportMap.size !== 0) {
91
146
  if (exportMap === undefined) {
92
147
  exportMap = fragment.exportMap;
93
148
  exportMapOwned = false;
149
+ onDemand = fragment.onDemand;
94
150
  } else {
95
151
  if (!exportMapOwned) {
96
152
  exportMap = new Map(exportMap);
@@ -98,6 +154,7 @@ class HarmonyExportInitFragment extends InitFragment {
98
154
  }
99
155
  for (const [key, value] of fragment.exportMap) {
100
156
  if (!exportMap.has(key)) exportMap.set(key, value);
157
+ onDemand = onDemand || fragment.onDemand;
101
158
  }
102
159
  }
103
160
  }
@@ -120,7 +177,7 @@ class HarmonyExportInitFragment extends InitFragment {
120
177
  this.exportsArgument,
121
178
  exportMap,
122
179
  unusedExports,
123
- this.onDemand
180
+ onDemand
124
181
  );
125
182
  }
126
183
 
@@ -167,7 +224,10 @@ class HarmonyExportInitFragment extends InitFragment {
167
224
  * @param {GenerateContext} context context
168
225
  * @returns {string | Source | undefined} the source code that will be included as initialization code
169
226
  */
170
- getContent({ runtimeTemplate, runtimeRequirements }) {
227
+ getContent(context) {
228
+ this._generate(context);
229
+
230
+ const { runtimeRequirements } = context;
171
231
  const unusedPart =
172
232
  this.unusedExports.size > 1
173
233
  ? `/* unused harmony exports ${joinIterableWithComma(
@@ -177,35 +237,55 @@ class HarmonyExportInitFragment extends InitFragment {
177
237
  ? `/* unused harmony export ${first(this.unusedExports)} */\n`
178
238
  : "";
179
239
  let definePart = "";
180
- if (this.exportMap.size > 0) {
181
- /** @type {string[]} */
182
- const definitions = [];
183
- const orderedExportMap =
184
- this.exportMap.size > 1
185
- ? [...this.exportMap].sort(([a], [b]) => (a < b ? -1 : 1))
186
- : this.exportMap;
187
- for (const [key, value] of orderedExportMap) {
188
- definitions.push(
189
- `\n/* harmony export */ ${propertyName(
190
- /** @type {string} */ (key)
191
- )}: ${runtimeTemplate.returningFunction(value)}`
192
- );
193
- }
240
+
241
+ if (this._defsGetter && this._defsGetter.length) {
194
242
  // Requested even when the call is taken over below: whoever took it may still
195
243
  // emit it, and by then the requirement set is closed.
196
244
  runtimeRequirements.add(RuntimeGlobals.exports);
197
245
  runtimeRequirements.add(RuntimeGlobals.definePropertyGetters);
198
246
  definePart = `/* harmony export */ ${
199
247
  RuntimeGlobals.definePropertyGetters
200
- }(${this.exportsArgument}, {${definitions.join(
248
+ }(${this.exportsArgument}, {${this._defsGetter.join(
201
249
  ","
202
250
  )}\n/* harmony export */ });\n`;
203
251
  if (this.onDemand !== undefined && this.onDemand(definePart, false)) {
204
252
  definePart = "";
205
253
  }
206
254
  }
255
+
207
256
  return `${definePart}${unusedPart}`;
208
257
  }
258
+
259
+ /**
260
+ * Returns the source code that will be included at the end of the module.
261
+ * @param {GenerateContext} context context
262
+ * @returns {string | Source | undefined} the source code that will be included at the end of the module
263
+ */
264
+ getEndContent({ runtimeRequirements }) {
265
+ let definePart = "";
266
+
267
+ if (this._defsValue && this._defsValue.length) {
268
+ // Requested even when the call is taken over below: whoever took it may still
269
+ // emit it, and by then the requirement set is closed.
270
+ runtimeRequirements.add(RuntimeGlobals.exports);
271
+ runtimeRequirements.add(RuntimeGlobals.definePropertyGetters);
272
+ // Only this fragment emits the array form, so the runtime helper drops the
273
+ // branch reading it unless this asks for it.
274
+ runtimeRequirements.add(RuntimeGlobals.definePropertyGettersFromArray);
275
+ const definition = `/* harmony export */ ${
276
+ RuntimeGlobals.definePropertyGetters
277
+ }(${this.exportsArgument}, [${this._defsValue.join(",")}\n/* harmony export */ ]);\n`;
278
+
279
+ definePart =
280
+ this.onDemand !== undefined && this.onDemand(definition, true)
281
+ ? definePart
282
+ : `\n${definition}`;
283
+ }
284
+
285
+ return definePart;
286
+ }
209
287
  }
210
288
 
211
289
  module.exports = HarmonyExportInitFragment;
290
+
291
+ HarmonyExportInitFragment.ExportBindingType = ExportBindingType;
@@ -9,8 +9,10 @@ const Dependency = require("../Dependency");
9
9
  const { InlinedUsedName } = require("../optimize/InlineExports");
10
10
  const makeSerializable = require("../util/makeSerializable");
11
11
  const memoize = require("../util/memoize");
12
- const ExportBindingInitFragment = require("./ExportBindingInitFragment");
13
12
  const HarmonyExportInitFragment = require("./HarmonyExportInitFragment");
13
+
14
+ const { ExportBindingType } = HarmonyExportInitFragment;
15
+
14
16
  const NullDependency = require("./NullDependency");
15
17
 
16
18
  /** @import { ReplaceSource } from "webpack-sources" */
@@ -180,7 +182,7 @@ HarmonyExportSpecifierDependency.Template = class HarmonyExportSpecifierDependen
180
182
  return;
181
183
  }
182
184
 
183
- const canUseValueBinding =
185
+ const valueFormat =
184
186
  dep.constValue !== undefined &&
185
187
  /** @type {import("../Module").BuildInfo} */ (module.buildInfo)
186
188
  .isCircular === false;
@@ -200,34 +202,20 @@ HarmonyExportSpecifierDependency.Template = class HarmonyExportSpecifierDependen
200
202
  ) === true
201
203
  : undefined;
202
204
 
203
- if (canUseValueBinding) {
204
- initFragments.push(
205
- new ExportBindingInitFragment(
206
- module.exportsArgument,
207
- [
208
- {
209
- name: used,
210
- value: `/* binding */ ${dep.id}`,
211
- bindingType: "value"
212
- }
213
- ],
214
- true,
215
- onDemand
216
- )
217
- );
218
- } else {
219
- /** @type {ExportMap} */
220
- const map = new Map();
221
- map.set(used, `/* binding */ ${dep.id}`);
222
- initFragments.push(
223
- new HarmonyExportInitFragment(
224
- module.exportsArgument,
225
- map,
226
- undefined,
227
- onDemand
228
- )
229
- );
230
- }
205
+ /** @type {ExportMap} */
206
+ const map = new Map();
207
+ map.set(used, {
208
+ value: `/* binding */ ${dep.id}`,
209
+ type: valueFormat ? ExportBindingType.Value : ExportBindingType.Getter
210
+ });
211
+ initFragments.push(
212
+ new HarmonyExportInitFragment(
213
+ module.exportsArgument,
214
+ map,
215
+ undefined,
216
+ onDemand
217
+ )
218
+ );
231
219
  }
232
220
  };
233
221
 
@@ -0,0 +1,59 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ Author Alexander Akait @alexander-akait
4
+ */
5
+
6
+ "use strict";
7
+
8
+ const { ASSET_TYPE } = require("../ModuleSourceTypeConstants");
9
+ const makeSerializable = require("../util/makeSerializable");
10
+ const HarmonyImportSideEffectDependency = require("./HarmonyImportSideEffectDependency");
11
+
12
+ /** @import Module from "../Module" */
13
+ /** @import ModuleGraph from "../ModuleGraph" */
14
+ /** @import { GetConditionFn } from "../Dependency" */
15
+
16
+ /**
17
+ * Whether a module is emitted as a file of its own, asked of the module so a
18
+ * plugin emitting the same way is treated alike. `buildInfo.filename` cannot
19
+ * serve here: generation sets it long after a connection has to know whether
20
+ * it is active.
21
+ * @param {Module} module the module to look up
22
+ * @returns {boolean} true when it emits a file
23
+ */
24
+ const emitsOwnFile = (module) => module.getSourceTypes().has(ASSET_TYPE);
25
+
26
+ /**
27
+ * An `import "..."` that declares no binding. It is a separate class rather
28
+ * than a flag so it costs nothing per instance, and the bound form — much the
29
+ * more common one — keeps the base class and its inline caches untouched.
30
+ */
31
+ class HarmonyImportBareSideEffectDependency extends HarmonyImportSideEffectDependency {
32
+ /**
33
+ * Returns function to determine if the connection is active.
34
+ * @param {ModuleGraph} moduleGraph module graph
35
+ * @returns {null | false | GetConditionFn} function to determine if the connection is active
36
+ */
37
+ getCondition(moduleGraph) {
38
+ return (connection) => {
39
+ const refModule = connection.resolvedModule;
40
+
41
+ if (!refModule) return true;
42
+ // Nothing reads the module, so emitting its file is the only thing the
43
+ // import can have been written for.
44
+ if (emitsOwnFile(refModule)) return true;
45
+
46
+ return refModule.getSideEffectsConnectionState(moduleGraph);
47
+ };
48
+ }
49
+ }
50
+
51
+ makeSerializable(
52
+ HarmonyImportBareSideEffectDependency,
53
+ "webpack/lib/dependencies/HarmonyImportBareSideEffectDependency"
54
+ );
55
+
56
+ HarmonyImportBareSideEffectDependency.Template =
57
+ HarmonyImportSideEffectDependency.Template;
58
+
59
+ module.exports = HarmonyImportBareSideEffectDependency;
@@ -114,7 +114,12 @@ const getDeferredExports = (module) => {
114
114
  for (const dep of module.dependencies) {
115
115
  // TODO remove in webpack 6
116
116
  // These may be missing on custom dependency types not extending the base Dependency
117
- if (!("getLazyUntil" in dep) || !("isLazy" in dep)) continue;
117
+ if (
118
+ typeof dep.getLazyUntil !== "function" ||
119
+ typeof dep.isLazy !== "function"
120
+ ) {
121
+ continue;
122
+ }
118
123
  if (!dep.isLazy()) continue;
119
124
  const until = dep.getLazyUntil();
120
125
  if (until === Dependency.LAZY_UNTIL_FALLBACK) return true;
@@ -18,6 +18,7 @@ const HarmonyAcceptDependency = require("./HarmonyAcceptDependency");
18
18
  const HarmonyAcceptImportDependency = require("./HarmonyAcceptImportDependency");
19
19
  const HarmonyEvaluatedImportSpecifierDependency = require("./HarmonyEvaluatedImportSpecifierDependency");
20
20
  const HarmonyExports = require("./HarmonyExports");
21
+ const HarmonyImportBareSideEffectDependency = require("./HarmonyImportBareSideEffectDependency");
21
22
  const {
22
23
  ExportPresenceModes,
23
24
  getNonOptionalPart
@@ -311,7 +312,13 @@ class HarmonyImportDependencyParserPlugin {
311
312
  parser.state.current.addError(error);
312
313
  }
313
314
 
314
- const sideEffectDep = new HarmonyImportSideEffectDependency(
315
+ // A declaration binding nothing was written for what importing produces,
316
+ // which for a module emitting its own file is that file.
317
+ const SideEffectDependency =
318
+ statement.specifiers.length === 0
319
+ ? HarmonyImportBareSideEffectDependency
320
+ : HarmonyImportSideEffectDependency;
321
+ const sideEffectDep = new SideEffectDependency(
315
322
  /** @type {string} */ (source),
316
323
  parser.state.lastHarmonyImportOrder,
317
324
  phase,
@@ -26,10 +26,11 @@ const HarmonyImportGuard = require("./HarmonyImportGuard");
26
26
  const { ImportPhaseUtils } = require("./ImportPhase");
27
27
 
28
28
  /** @import { ReplaceSource } from "webpack-sources" */
29
- /** @import { GetConditionFn, ReferencedExports } from "../Dependency" */
29
+ /** @import { GetConditionFn, ReferencedExports, UpdateHashContext } from "../Dependency" */
30
30
  /** @import { DependencyTemplateContext } from "../DependencyTemplate" */
31
31
  /** @import Module, { BuildMeta } from "../Module" */
32
32
  /** @import ModuleGraph from "../ModuleGraph" */
33
+ /** @import Hash from "../util/Hash" */
33
34
  /**
34
35
  * @import ModuleGraphConnection, {
35
36
  * ConnectionState
@@ -262,6 +263,28 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency {
262
263
  return condition;
263
264
  }
264
265
 
266
+ /**
267
+ * Updates the hash with the data contributed by this instance.
268
+ * @param {Hash} hash hash to be updated
269
+ * @param {UpdateHashContext} context context
270
+ * @returns {void}
271
+ */
272
+ updateHash(hash, context) {
273
+ const { chunkGraph, runtime } = context;
274
+ const moduleGraph = chunkGraph.moduleGraph;
275
+ if (!isInlineExportsEnabled(moduleGraph)) return;
276
+ const module = moduleGraph.getModule(this);
277
+ if (!module || !isInlineEnabled(module)) return;
278
+ const ids = this.getIds(moduleGraph);
279
+ if (ids.length === 0) return;
280
+ const exportsInfo = moduleGraph.getExportsInfo(module);
281
+ if (!exportsInfo.hasInlinedUsedName(ids, runtime)) return;
282
+ const usedName = exportsInfo.getUsedName(ids, runtime);
283
+ if (usedName instanceof InlinedUsedName) {
284
+ usedName.updateHash(hash);
285
+ }
286
+ }
287
+
265
288
  /**
266
289
  * Gets module evaluation side effects state.
267
290
  * @param {ModuleGraph} moduleGraph the module graph
@@ -20,6 +20,7 @@ const HarmonyExportExpressionDependency = require("./HarmonyExportExpressionDepe
20
20
  const HarmonyExportHeaderDependency = require("./HarmonyExportHeaderDependency");
21
21
  const HarmonyExportImportedSpecifierDependency = require("./HarmonyExportImportedSpecifierDependency");
22
22
  const HarmonyExportSpecifierDependency = require("./HarmonyExportSpecifierDependency");
23
+ const HarmonyImportBareSideEffectDependency = require("./HarmonyImportBareSideEffectDependency");
23
24
  const HarmonyImportDependencyParserPlugin = require("./HarmonyImportDependencyParserPlugin");
24
25
  const HarmonyImportSideEffectDependency = require("./HarmonyImportSideEffectDependency");
25
26
  const HarmonyImportSpecifierDependency = require("./HarmonyImportSpecifierDependency");
@@ -34,6 +35,7 @@ const TopLevelAwaitDependency = require("./TopLevelAwaitDependency");
34
35
  */
35
36
  /** @import Compiler from "../Compiler" */
36
37
  /** @import Parser from "../javascript/JavascriptParser" */
38
+ /** @import { BuildInfo } from "../Module" */
37
39
 
38
40
  /**
39
41
  * Defines the harmony modules plugin options type used by this module.
@@ -81,6 +83,15 @@ class HarmonyModulesPlugin {
81
83
  new HarmonyImportSideEffectDependency.Template()
82
84
  );
83
85
 
86
+ compilation.dependencyFactories.set(
87
+ HarmonyImportBareSideEffectDependency,
88
+ normalModuleFactory
89
+ );
90
+ compilation.dependencyTemplates.set(
91
+ HarmonyImportBareSideEffectDependency,
92
+ new HarmonyImportBareSideEffectDependency.Template()
93
+ );
94
+
84
95
  compilation.dependencyFactories.set(
85
96
  HarmonyImportSpecifierDependency,
86
97
  normalModuleFactory
@@ -149,6 +160,15 @@ class HarmonyModulesPlugin {
149
160
  return;
150
161
  }
151
162
 
163
+ if (parserOptions.specNamespaceObject) {
164
+ // Recorded on the module, because an importer asks the module it
165
+ // imports whether its namespace is a spec exotic object.
166
+ parser.hooks.program.tap(PLUGIN_NAME, () => {
167
+ /** @type {BuildInfo} */
168
+ (parser.state.module.buildInfo).specNamespaceObject = true;
169
+ });
170
+ }
171
+
152
172
  new HarmonyDetectionParserPlugin().apply(parser);
153
173
  new HarmonyImportDependencyParserPlugin(parserOptions).apply(parser);
154
174
  new HarmonyExportDependencyParserPlugin(parserOptions).apply(parser);
@@ -7,6 +7,7 @@
7
7
  const {
8
8
  CSS_IMPORT_TYPE,
9
9
  CSS_TYPE,
10
+ HTML_TYPE,
10
11
  JAVASCRIPT_TYPE
11
12
  } = require("../ModuleSourceTypeConstants");
12
13
  const ResourceHintPlugin = require("../prefetch/ResourceHintPlugin");
@@ -587,6 +588,47 @@ const buildLinkTag = (rel, attrs) =>
587
588
  : ""
588
589
  }>`;
589
590
 
591
+ /**
592
+ * The chunks a hint means when it names a page: a page loads no JavaScript of
593
+ * its own, so the hint follows the entries the parser extracted from it.
594
+ * @param {import("../Compilation")} compilation compilation
595
+ * @param {Chunk} chunk chunk a hint resolved to
596
+ * @returns {Chunk[]} the chunks to hint at
597
+ */
598
+ const resolvePageChunk = (compilation, chunk) => {
599
+ const { chunkGraph } = compilation;
600
+ const modules = chunkGraph.getChunkModulesIterableBySourceType(
601
+ chunk,
602
+ HTML_TYPE
603
+ );
604
+ // A page with a JavaScript side of its own (an `output.library` entry) is
605
+ // hinted too — `chunkHasJs` can't say so, it holds for any runtime chunk.
606
+ const javascript = chunkGraph.getChunkModulesIterableBySourceType(
607
+ chunk,
608
+ JAVASCRIPT_TYPE
609
+ );
610
+ /** @type {Chunk[]} */
611
+ const chunks = javascript === undefined ? [] : [chunk];
612
+ // A chunk carrying no page stands for itself; a page stands for the entries
613
+ // extracted from it, so one that extracted nothing hints nothing.
614
+ if (modules === undefined) return chunks.length === 0 ? [chunk] : chunks;
615
+ for (const module of modules) {
616
+ const { htmlEntries } =
617
+ /** @type {import("../html/HtmlModule").HtmlModuleBuildInfo} */ (
618
+ module.buildInfo
619
+ ) || {};
620
+ if (!htmlEntries) continue;
621
+ for (const group of Object.values(htmlEntries)) {
622
+ for (const { entryName } of group) {
623
+ const entrypoint = compilation.entrypoints.get(entryName);
624
+ const entryChunk = entrypoint && entrypoint.getEntrypointChunk();
625
+ if (entryChunk) chunks.push(entryChunk);
626
+ }
627
+ }
628
+ }
629
+ return chunks;
630
+ };
631
+
590
632
  /**
591
633
  * Resolve one `output.html.resourceHints` descriptor to zero or more `<link>`
592
634
  * tags. A `chunk`/`entry` reference becomes the emitted chunk URL (a sentinel
@@ -633,6 +675,14 @@ const resolveResourceHint = (desc, ctx) => {
633
675
  } else {
634
676
  return [];
635
677
  }
678
+ /** @type {Chunk[]} */
679
+ const hinted = [];
680
+ for (const chunk of chunks) {
681
+ for (const resolved of resolvePageChunk(ctx.compilation, chunk)) {
682
+ hinted.push(resolved);
683
+ }
684
+ }
685
+ chunks = hinted;
636
686
  const kind = desc.as === "style" ? "css" : "javascript";
637
687
  const as = desc.as || (rel === "modulepreload" ? undefined : "script");
638
688
  // A hint targeting another chunk must match how that chunk is fetched, so