webpack 5.112.0 → 5.112.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (263) hide show
  1. package/bin/webpack.js +13 -7
  2. package/lib/Compilation.js +198 -61
  3. package/lib/Compiler.js +12 -25
  4. package/lib/asset/AssetBytesGenerator.js +14 -6
  5. package/lib/asset/AssetBytesParser.js +10 -8
  6. package/lib/asset/AssetGenerator.js +36 -48
  7. package/lib/asset/AssetModule.js +11 -0
  8. package/lib/asset/AssetModulesPlugin.js +5 -4
  9. package/lib/asset/AssetParser.js +8 -8
  10. package/lib/asset/AssetSourceGenerator.js +16 -8
  11. package/lib/asset/AssetSourceParser.js +10 -8
  12. package/lib/asset/WebManifestGenerator.js +11 -6
  13. package/lib/asset/WebManifestParser.js +3 -3
  14. package/lib/async-modules/AsyncModuleHelpers.js +8 -2
  15. package/lib/async-modules/InferAsyncModulesPlugin.js +7 -2
  16. package/lib/cache/CacheFacade.js +1 -1
  17. package/lib/cache/PackFileCacheStrategy.js +6 -10
  18. package/lib/cache/ResolverCachePlugin.js +58 -8
  19. package/lib/config/WebpackOptionsApply.js +8 -28
  20. package/lib/config/cli.js +9 -6
  21. package/lib/config/defaults.js +24 -13
  22. package/lib/config/getClaimedAssetTypes.js +2 -2
  23. package/lib/config/target.js +1 -1
  24. package/lib/context/ContextModule.js +1 -1
  25. package/lib/context/ContextModuleFactory.js +1 -1
  26. package/lib/context/ContextReplacementPlugin.js +3 -9
  27. package/lib/css/CssGenerator.js +40 -47
  28. package/lib/css/CssModule.js +10 -0
  29. package/lib/css/CssModulesPlugin.js +13 -6
  30. package/lib/css/CssParser.js +33 -32
  31. package/lib/css/conventions.js +1 -1
  32. package/lib/css/data.js +224 -219
  33. package/lib/css/syntax-parser.js +1312 -312
  34. package/lib/css/syntax-printer.js +1142 -1025
  35. package/lib/debug/ProfilingPlugin.js +65 -43
  36. package/lib/define/DefinePlugin.js +10 -15
  37. package/lib/define/DotenvPlugin.js +10 -6
  38. package/lib/define/EnvironmentPlugin.js +4 -2
  39. package/lib/dependencies/amd/AMDDefineDependencyParserPlugin.js +1 -2
  40. package/lib/dependencies/amd/AMDRequireDependenciesBlockParserPlugin.js +4 -1
  41. package/lib/dependencies/commonjs/CommonJsExportRequireDependency.js +1 -4
  42. package/lib/dependencies/commonjs/CommonJsExportsParserPlugin.js +18 -33
  43. package/lib/dependencies/commonjs/CommonJsImportsParserPlugin.js +1 -3
  44. package/lib/dependencies/commonjs/CommonJsObjectExportDependency.js +4 -4
  45. package/lib/dependencies/commonjs/CommonJsPlugin.js +2 -5
  46. package/lib/dependencies/commonjs/RequireEnsureDependenciesBlockParserPlugin.js +4 -1
  47. package/lib/dependencies/context/ImportMetaContextDependencyParserPlugin.js +1 -2
  48. package/lib/dependencies/context/ImportMetaGlobDependencyParserPlugin.js +4 -7
  49. package/lib/dependencies/context/ImportMetaGlobHelpers.js +8 -10
  50. package/lib/dependencies/core/CachedConstDependency.js +9 -6
  51. package/lib/dependencies/css/CssIcssExportDependency.js +6 -7
  52. package/lib/dependencies/css/CssIcssImportDependency.js +1 -3
  53. package/lib/dependencies/css/CssUrlDependency.js +2 -6
  54. package/lib/dependencies/esm/ESMDetectionParserPlugin.js +2 -4
  55. package/lib/dependencies/esm/ESMExportExpressionDependency.js +2 -2
  56. package/lib/dependencies/esm/ESMExportImportedSpecifierDependency.js +16 -18
  57. package/lib/dependencies/esm/ESMExportSpecifierDependency.js +20 -3
  58. package/lib/dependencies/esm/ESMExports.js +2 -10
  59. package/lib/dependencies/esm/ESMImportDependency.js +17 -2
  60. package/lib/dependencies/esm/ESMImportDependencyParserPlugin.js +6 -17
  61. package/lib/dependencies/esm/ESMImportGuard.js +11 -23
  62. package/lib/dependencies/esm/ESMImportSideEffectDependency.js +1 -1
  63. package/lib/dependencies/esm/ESMImportSpecifierDependency.js +4 -1
  64. package/lib/dependencies/esm/ESMLiveExportDependency.js +311 -0
  65. package/lib/dependencies/esm/ESMLiveExportParserPlugin.js +862 -0
  66. package/lib/dependencies/esm/ESMModulesPlugin.js +1 -3
  67. package/lib/dependencies/esm/TopLevelAwaitDependency.js +1 -8
  68. package/lib/dependencies/helpers/DynamicExports.js +4 -6
  69. package/lib/dependencies/html/HtmlEntryDependency.js +5 -14
  70. package/lib/dependencies/html/HtmlInlineHtmlDependency.js +1 -4
  71. package/lib/dependencies/html/HtmlInlineScriptDependency.js +2 -6
  72. package/lib/dependencies/html/HtmlInlineStyleDependency.js +1 -4
  73. package/lib/dependencies/import/ImportParserPlugin.js +3 -6
  74. package/lib/dependencies/import-meta/ImportMetaPlugin.js +4 -6
  75. package/lib/dependencies/url/URLParserPlugin.js +1 -1
  76. package/lib/dependencies/worker/WorkerAndWorkletPlugin.js +51 -20
  77. package/lib/devtool/ModuleFilenameHelpers.js +1 -1
  78. package/lib/devtool/SourceMapDevToolPlugin.js +1 -1
  79. package/lib/dll/DelegatedModule.js +3 -3
  80. package/lib/dll/DllModule.js +3 -1
  81. package/lib/dll/DllReferencePlugin.js +1 -4
  82. package/lib/errors/AbstractMethodError.js +1 -1
  83. package/lib/errors/ErrorHelpers.js +2 -1
  84. package/lib/errors/HookWebpackError.js +2 -1
  85. package/lib/errors/JSONParseError.js +4 -4
  86. package/lib/errors/WebpackError.js +3 -2
  87. package/lib/esm/ModuleChunkFormatPlugin.js +36 -1
  88. package/lib/externals/ExternalModule.js +12 -9
  89. package/lib/externals/ExternalModuleFactoryPlugin.js +1 -2
  90. package/lib/externals/ExternalsPlugin.js +1 -1
  91. package/lib/fs/FileSystemInfo.js +4 -4
  92. package/lib/graph/AsyncDependenciesBlock.js +1 -1
  93. package/lib/graph/ChunkGraph.js +5 -0
  94. package/lib/graph/Dependency.js +8 -2
  95. package/lib/graph/ExportsInfo.js +1 -1
  96. package/lib/graph/ModuleGraph.js +14 -3
  97. package/lib/graph/buildChunkGraph.js +17 -19
  98. package/lib/graph/findGraphRoots.js +1 -1
  99. package/lib/hmr/HotModuleReplacement.runtime.js +10 -9
  100. package/lib/hmr/HotModuleReplacementPlugin.js +5 -11
  101. package/lib/hmr/JavascriptHotModuleReplacement.runtime.js +16 -19
  102. package/lib/hmr/LazyCompilationPlugin.js +1 -7
  103. package/lib/html/HtmlGenerator.js +25 -17
  104. package/lib/html/HtmlModule.js +11 -1
  105. package/lib/html/HtmlModulesPlugin.js +12 -11
  106. package/lib/html/HtmlParser.js +10 -9
  107. package/lib/html/builtinEmbeddedRenderer.js +31 -33
  108. package/lib/html/data.js +42 -21
  109. package/lib/html/htmlMinify.js +4 -1
  110. package/lib/html/syntax-parser.js +34 -35
  111. package/lib/html/syntax-printer.js +2 -3
  112. package/lib/html/xmlMinify.js +4 -1
  113. package/lib/ids/HashedModuleIdsPlugin.js +1 -1
  114. package/lib/index.js +13 -12
  115. package/lib/javascript/APIPlugin.js +7 -13
  116. package/lib/javascript/BasicEvaluatedExpression.js +5 -5
  117. package/lib/javascript/CommonJsChunkFormatPlugin.js +2 -7
  118. package/lib/javascript/ConstPlugin.js +1 -1
  119. package/lib/javascript/JavascriptGenerator.js +16 -11
  120. package/lib/javascript/JavascriptMetaInfoPlugin.js +3 -15
  121. package/lib/javascript/JavascriptModule.js +10 -0
  122. package/lib/javascript/JavascriptModulesPlugin.js +2 -4
  123. package/lib/javascript/JavascriptParser.js +99 -11
  124. package/lib/javascript/ScopeAnalyzer.js +183 -107
  125. package/lib/javascript/UseStrictPlugin.js +2 -5
  126. package/lib/javascript/jsMinify.js +1 -1
  127. package/lib/javascript/regexp.js +2 -2
  128. package/lib/javascript/syntax-parser.js +2114 -1506
  129. package/lib/javascript/syntax-printer-data.js +167 -1
  130. package/lib/javascript/syntax-printer.js +9554 -2782
  131. package/lib/json/JsonGenerator.js +15 -7
  132. package/lib/json/JsonModule.js +11 -0
  133. package/lib/json/JsonParser.js +7 -6
  134. package/lib/library/AssignLibraryPlugin.js +1 -1
  135. package/lib/library/JsonpLibraryPlugin.js +1 -1
  136. package/lib/library/ModuleLibraryPlugin.js +399 -23
  137. package/lib/loaders/LoaderRunner.js +76 -38
  138. package/lib/loaders/loadLoader.js +16 -10
  139. package/lib/module/Generator.js +17 -9
  140. package/lib/module/Module.js +2 -2
  141. package/lib/module/NormalModule.js +7 -5
  142. package/lib/module/NormalModuleFactory.js +11 -17
  143. package/lib/module/Parser.js +9 -2
  144. package/lib/module/extractSourceMap.js +69 -18
  145. package/lib/module/findCaseMismatch.js +2 -2
  146. package/lib/node/ExternalModuleInitFragment.js +2 -2
  147. package/lib/node/ReadFileCompileAsyncWasmPlugin.js +4 -12
  148. package/lib/node/ReadFileCompileWasmPlugin.js +2 -6
  149. package/lib/node/nodeConsole.js +4 -3
  150. package/lib/optimize/CircularModulesPlugin.js +1 -1
  151. package/lib/optimize/ConcatenatedModule.js +4 -8
  152. package/lib/optimize/FlagDependencyExportsPlugin.js +6 -11
  153. package/lib/optimize/FlagDependencyUsagePlugin.js +28 -3
  154. package/lib/optimize/InlineExports.js +4 -7
  155. package/lib/optimize/LazyBarrels.js +41 -5
  156. package/lib/optimize/ModuleConcatenationPlugin.js +8 -10
  157. package/lib/optimize/RealContentHashPlugin.js +2 -6
  158. package/lib/optimize/SideEffectsFlagPlugin.js +7 -21
  159. package/lib/optimize/SplitChunksPlugin.js +11 -24
  160. package/lib/optimize/TupleQueue.js +1 -1
  161. package/lib/output/CleanPlugin.js +3 -1
  162. package/lib/output/CopyPlugin.js +3 -4
  163. package/lib/performance/EvalUsagePlugin.js +1 -3
  164. package/lib/performance/HotspotsPlugin.js +33 -9
  165. package/lib/performance/PureAnnotationsPlugin.js +16 -10
  166. package/lib/performance/TopLevelThisPlugin.js +17 -9
  167. package/lib/prefetch/ResourceHintPlugin.js +1 -1
  168. package/lib/provide/ProvidedDependency.js +36 -4
  169. package/lib/rules/BasicEffectRulePlugin.js +1 -1
  170. package/lib/rules/RuleSetCompiler.js +15 -5
  171. package/lib/rules/UseEffectRulePlugin.js +1 -3
  172. package/lib/runtime/AsyncModuleRuntimeModule.js +7 -1
  173. package/lib/runtime/GetChunkFilenameRuntimeModule.js +1 -5
  174. package/lib/runtime/RuntimeGlobals.js +6 -0
  175. package/lib/runtime/RuntimePlugin.js +2 -0
  176. package/lib/schemes/HttpUriPlugin.js +1 -2
  177. package/lib/schemes/VirtualUrlPlugin.js +3 -1
  178. package/lib/serialization/AggregateErrorSerializer.js +3 -3
  179. package/lib/serialization/BinaryMiddleware.js +4 -1
  180. package/lib/serialization/ErrorObjectSerializer.js +2 -5
  181. package/lib/serialization/ObjectMiddleware.js +17 -15
  182. package/lib/serialization/PlainObjectSerializer.js +3 -7
  183. package/lib/serialization/Serializer.js +21 -11
  184. package/lib/serialization/SerializerMiddleware.js +8 -6
  185. package/lib/stats/DefaultStatsFactoryPlugin.js +35 -35
  186. package/lib/stats/DefaultStatsPresetPlugin.js +2 -6
  187. package/lib/stats/DefaultStatsPrinterPlugin.js +12 -11
  188. package/lib/stats/StatsFactory.js +194 -24
  189. package/lib/stats/StatsPrinter.js +126 -13
  190. package/lib/template/DependencyTemplate.js +1 -1
  191. package/lib/template/RuntimeTemplate.js +13 -32
  192. package/lib/template/Template.js +1 -1
  193. package/lib/util/SourceProcessor.js +146 -29
  194. package/lib/util/WeakTupleMap.js +10 -4
  195. package/lib/util/cleverMerge.js +61 -33
  196. package/lib/util/comparators.js +9 -5
  197. package/lib/util/dataURL.js +2 -0
  198. package/lib/util/deprecation.js +4 -3
  199. package/lib/util/globUtils.js +1 -4
  200. package/lib/util/internalSerializables.js +2 -0
  201. package/lib/util/makeSerializable.js +6 -4
  202. package/lib/util/memoize.js +1 -1
  203. package/lib/util/parseJson.js +2 -2
  204. package/lib/util/serialization.js +31 -27
  205. package/lib/wasm/AsyncWasmModule.js +12 -2
  206. package/lib/wasm/AsyncWebAssemblyGenerator.js +12 -4
  207. package/lib/wasm/AsyncWebAssemblyJavascriptGenerator.js +13 -5
  208. package/lib/wasm/AsyncWebAssemblyParser.js +7 -5
  209. package/lib/wasm/UniversalCompileAsyncWasmPlugin.js +2 -6
  210. package/lib/wasm-sync/SyncWasmModule.js +16 -1
  211. package/lib/wasm-sync/WebAssemblyGenerator.js +15 -10
  212. package/lib/wasm-sync/WebAssemblyJavascriptGenerator.js +13 -5
  213. package/lib/wasm-sync/WebAssemblyParser.js +10 -12
  214. package/lib/web/FetchCompileAsyncWasmPlugin.js +4 -12
  215. package/lib/web/FetchCompileWasmPlugin.js +2 -6
  216. package/package.json +18 -19
  217. package/schemas/WebpackOptions.check.js +3 -3
  218. package/schemas/WebpackOptions.json +2 -2
  219. package/schemas/plugins/BannerPlugin.check.js +3 -3
  220. package/schemas/plugins/HtmlGeneratorOptions.check.js +3 -3
  221. package/schemas/plugins/HtmlParserOptions.check.js +3 -3
  222. package/schemas/plugins/IgnorePlugin.check.js +3 -3
  223. package/schemas/plugins/LoaderOptionsPlugin.check.js +3 -3
  224. package/schemas/plugins/ManifestPlugin.check.js +3 -3
  225. package/schemas/plugins/ProgressPlugin.check.js +3 -3
  226. package/schemas/plugins/SSRManifestPlugin.check.js +3 -3
  227. package/schemas/plugins/SourceMapDevToolPlugin.check.js +3 -3
  228. package/schemas/plugins/WatchIgnorePlugin.check.js +3 -3
  229. package/schemas/plugins/asset/AssetGeneratorOptions.check.js +3 -3
  230. package/schemas/plugins/asset/AssetInlineGeneratorOptions.check.js +3 -3
  231. package/schemas/plugins/asset/AssetParserOptions.check.js +3 -3
  232. package/schemas/plugins/asset/AssetResourceGeneratorOptions.check.js +3 -3
  233. package/schemas/plugins/container/ContainerPlugin.check.js +3 -3
  234. package/schemas/plugins/container/ContainerReferencePlugin.check.js +3 -3
  235. package/schemas/plugins/container/ExternalsType.check.js +3 -3
  236. package/schemas/plugins/container/ModuleFederationPlugin.check.js +3 -3
  237. package/schemas/plugins/css/CssAutoOrModuleParserOptions.check.js +3 -3
  238. package/schemas/plugins/css/CssGeneratorOptions.check.js +3 -3
  239. package/schemas/plugins/css/CssModuleGeneratorOptions.check.js +3 -3
  240. package/schemas/plugins/css/CssModuleParserOptions.check.js +3 -3
  241. package/schemas/plugins/css/CssParserOptions.check.js +3 -3
  242. package/schemas/plugins/debug/ProfilingPlugin.check.js +3 -3
  243. package/schemas/plugins/define/DotenvPluginOptions.check.js +7 -0
  244. package/schemas/plugins/define/DotenvPluginOptions.json +3 -0
  245. package/schemas/plugins/dll/DllPlugin.check.js +3 -3
  246. package/schemas/plugins/dll/DllReferencePlugin.check.js +3 -3
  247. package/schemas/plugins/ids/HashedModuleIdsPlugin.check.js +3 -3
  248. package/schemas/plugins/ids/OccurrenceChunkIdsPlugin.check.js +3 -3
  249. package/schemas/plugins/ids/OccurrenceModuleIdsPlugin.check.js +3 -3
  250. package/schemas/plugins/json/JsonModulesPluginGenerator.check.js +3 -3
  251. package/schemas/plugins/json/JsonModulesPluginParser.check.js +3 -3
  252. package/schemas/plugins/optimize/AggressiveSplittingPlugin.check.js +3 -3
  253. package/schemas/plugins/optimize/LimitChunkCountPlugin.check.js +3 -3
  254. package/schemas/plugins/optimize/MergeDuplicateChunksPlugin.check.js +3 -3
  255. package/schemas/plugins/optimize/MinChunkSizePlugin.check.js +3 -3
  256. package/schemas/plugins/output/CleanOptions.check.js +7 -0
  257. package/schemas/plugins/output/CleanOptions.json +3 -0
  258. package/schemas/plugins/schemes/HttpUriPlugin.check.js +3 -3
  259. package/schemas/plugins/schemes/VirtualUrlPlugin.check.js +3 -3
  260. package/schemas/plugins/sharing/ConsumeSharedPlugin.check.js +3 -3
  261. package/schemas/plugins/sharing/ProvideSharedPlugin.check.js +3 -3
  262. package/schemas/plugins/sharing/SharePlugin.check.js +3 -3
  263. package/types.d.ts +1482 -358
@@ -12,6 +12,7 @@ const { JAVASCRIPT_TYPES } = require("../module/ModuleSourceTypeConstants");
12
12
  const ConcatenationScope = require("../optimize/ConcatenationScope");
13
13
  const RuntimeGlobals = require("../runtime/RuntimeGlobals");
14
14
 
15
+ /** @import { JsonNormalModule } from "./JsonModule" */
15
16
  /** @import { Source } from "webpack-sources" */
16
17
  /** @import { JsonGeneratorOptions } from "../../declarations/WebpackOptions" */
17
18
  /** @import ExportsInfo from "../graph/ExportsInfo" */
@@ -24,7 +25,6 @@ const RuntimeGlobals = require("../runtime/RuntimeGlobals");
24
25
  * SourceTypes
25
26
  * } from "../module/Module"
26
27
  */
27
- /** @import NormalModule from "../module/NormalModule" */
28
28
  /** @import { RuntimeSpec } from "../util/runtime" */
29
29
  /** @import { JsonArray, JsonObject, JsonValue } from "../fs/fs" */
30
30
 
@@ -145,6 +145,14 @@ const createObjectForExportsInfo = (data, exportsInfo, runtime) => {
145
145
  return reducedData;
146
146
  };
147
147
 
148
+ /**
149
+ * The module type the JSDoc inherited from `Generator` names.
150
+ * @typedef {JsonNormalModule} TModule
151
+ */
152
+
153
+ /**
154
+ * @extends {Generator<TModule>}
155
+ */
148
156
  class JsonGenerator extends Generator {
149
157
  /**
150
158
  * Creates an instance of JsonGenerator.
@@ -158,7 +166,7 @@ class JsonGenerator extends Generator {
158
166
 
159
167
  /**
160
168
  * Returns the source types available for this module.
161
- * @param {NormalModule} module fresh module
169
+ * @param {TModule} module fresh module
162
170
  * @returns {SourceTypes} available types (do not mutate)
163
171
  */
164
172
  getTypes(module) {
@@ -167,7 +175,7 @@ class JsonGenerator extends Generator {
167
175
 
168
176
  /**
169
177
  * Returns the estimated size for the requested source type.
170
- * @param {NormalModule} module the module
178
+ * @param {TModule} module the module
171
179
  * @param {SourceType=} type source type
172
180
  * @returns {number} estimate size of the module
173
181
  */
@@ -183,7 +191,7 @@ class JsonGenerator extends Generator {
183
191
 
184
192
  /**
185
193
  * Returns the reason this module cannot be concatenated, when one exists.
186
- * @param {NormalModule} module module for which the bailout reason should be determined
194
+ * @param {TModule} module module for which the bailout reason should be determined
187
195
  * @param {ConcatenationBailoutReasonContext} context context
188
196
  * @returns {string | undefined} reason why this module can't be concatenated, undefined when it can be concatenated
189
197
  */
@@ -193,7 +201,7 @@ class JsonGenerator extends Generator {
193
201
 
194
202
  /**
195
203
  * Generates generated code for this runtime module.
196
- * @param {NormalModule} module module for which the code should be generated
204
+ * @param {TModule} module module for which the code should be generated
197
205
  * @param {GenerateContext} generateContext context for generate
198
206
  * @returns {Source | null} generated code
199
207
  */
@@ -254,7 +262,7 @@ class JsonGenerator extends Generator {
254
262
  /**
255
263
  * Generates fallback output for the provided error condition.
256
264
  * @param {Error} error the error
257
- * @param {NormalModule} module module for which the code should be generated
265
+ * @param {TModule} module module for which the code should be generated
258
266
  * @param {GenerateContext} generateContext context for generate
259
267
  * @returns {Source | null} generated code
260
268
  */
@@ -271,7 +279,7 @@ class JsonGenerator extends Generator {
271
279
  /**
272
280
  * Updates the hash with the data contributed by this instance.
273
281
  * @param {Hash} hash hash that will be modified
274
- * @param {UpdateHashContext} updateHashContext context for updating hash
282
+ * @param {UpdateHashContext<TModule>} updateHashContext context for updating hash
275
283
  */
276
284
  updateHash(hash, updateHashContext) {
277
285
  if (this.options.JSONParse) {
@@ -14,6 +14,7 @@ const makeSerializable = require("../util/makeSerializable");
14
14
  * } from "../module/NormalModule"
15
15
  */
16
16
  /** @import JsonData from "./JsonData" */
17
+ /** @import { BuildMeta } from "../module/Module" */
17
18
 
18
19
  /**
19
20
  * Defines the build info properties specific to json modules.
@@ -23,6 +24,16 @@ const makeSerializable = require("../util/makeSerializable");
23
24
 
24
25
  /** @typedef {NormalModuleBuildInfo & KnownJsonModuleBuildInfo} JsonModuleBuildInfo */
25
26
 
27
+ /**
28
+ * A json module before or after its build, typed with its build info.
29
+ * @typedef {NormalModule & { buildInfo?: JsonModuleBuildInfo }} JsonNormalModule
30
+ */
31
+
32
+ /**
33
+ * A built json module, typed with its build info and build meta.
34
+ * @typedef {NormalModule & { buildInfo: JsonModuleBuildInfo, buildMeta: BuildMeta }} BuiltJsonModule
35
+ */
36
+
26
37
  /**
27
38
  * Module class for `json` modules. JSON-specific properties should live here instead of `NormalModule`.
28
39
  */
@@ -10,9 +10,8 @@ const parseJson = require("../util/parseJson");
10
10
  const JsonData = require("./JsonData");
11
11
  const JsonExportsDependency = require("./JsonExportsDependency");
12
12
 
13
+ /** @import { BuiltJsonModule } from "./JsonModule" */
13
14
  /** @import { JsonParserOptions } from "../../declarations/WebpackOptions" */
14
- /** @import { JsonModuleBuildInfo } from "./JsonModule" */
15
- /** @import { BuildMeta } from "../module/Module" */
16
15
  /** @import { ParserState, PreparsedAst } from "../module/Parser" */
17
16
  /** @import { JsonValue } from "../fs/fs" */
18
17
 
@@ -24,6 +23,9 @@ const JsonExportsDependency = require("./JsonExportsDependency");
24
23
  * @typedef {import("../util/memoize").FunctionReturning<T>} FunctionReturning
25
24
  */
26
25
 
26
+ /**
27
+ * @extends {Parser<BuiltJsonModule>}
28
+ */
27
29
  class JsonParser extends Parser {
28
30
  /**
29
31
  * Creates an instance of JsonParser.
@@ -53,13 +55,12 @@ class JsonParser extends Parser {
53
55
  typeof source === "object"
54
56
  ? source
55
57
  : parseFn(source[0] === "\uFEFF" ? source.slice(1) : source);
56
- const jsonData = new JsonData(/** @type {Buffer | JsonValue} */ (data));
57
- const buildInfo = /** @type {JsonModuleBuildInfo} */ (
58
- state.module.buildInfo
58
+ const jsonData = new JsonData(data);
59
+ const { buildInfo, buildMeta } = /** @type {BuiltJsonModule} */ (
60
+ state.module
59
61
  );
60
62
  buildInfo.jsonData = jsonData;
61
63
  buildInfo.strict = true;
62
- const buildMeta = /** @type {BuildMeta} */ (state.module.buildMeta);
63
64
  buildMeta.exportsType = "default";
64
65
  buildMeta.defaultObject =
65
66
  typeof data === "object"
@@ -46,7 +46,7 @@ const AbstractLibraryPlugin = require("./AbstractLibraryPlugin");
46
46
  const KEYWORD_REGEX =
47
47
  /^(?:await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|false|finally|for|function|if|implements|import|in|instanceof|interface|let|new|null|package|private|protected|public|return|super|switch|static|this|throw|try|true|typeof|var|void|while|with|yield)$/;
48
48
  const IDENTIFIER_REGEX =
49
- /^[\p{L}\p{Nl}$_][\p{L}\p{Nl}$\p{Mn}\p{Mc}\p{Nd}\p{Pc}]*$/iu;
49
+ /^[\p{L}\p{Nl}$_][\p{L}\p{Nl}$\p{Mn}\p{Mc}\p{Nd}\p{Pc}]*$/u;
50
50
 
51
51
  /**
52
52
  * Validates the library name by checking for keywords and valid characters
@@ -67,7 +67,7 @@ class JsonpLibraryPlugin extends AbstractLibraryPlugin {
67
67
  `Jsonp library name must be a simple string. ${AbstractLibraryPlugin.COMMON_LIBRARY_NAME_MESSAGE}`
68
68
  );
69
69
  }
70
- const _name = /** @type {string} */ (name);
70
+ const _name = name;
71
71
  return {
72
72
  name: _name
73
73
  };
@@ -6,6 +6,8 @@
6
6
  "use strict";
7
7
 
8
8
  const { ConcatSource } = require("webpack-sources");
9
+ const ESMLiveExportDependency = require("../dependencies/esm/ESMLiveExportDependency");
10
+ const ESMLiveExportParserPlugin = require("../dependencies/esm/ESMLiveExportParserPlugin");
9
11
  const ExternalStarReexportError = require("../errors/ExternalStarReexportError");
10
12
  const { UsageState } = require("../graph/ExportsInfo");
11
13
  const isDependencyKind = require("../graph/isDependencyKind");
@@ -15,20 +17,28 @@ const {
15
17
  mergedEntryModules
16
18
  } = require("../javascript/MergedEntryExports");
17
19
  const { JAVASCRIPT_TYPE } = require("../module/ModuleSourceTypeConstants");
20
+ const {
21
+ JAVASCRIPT_MODULE_TYPE_AUTO,
22
+ JAVASCRIPT_MODULE_TYPE_ESM
23
+ } = require("../module/ModuleTypeConstants");
18
24
  const { isInlinedUsedName } = require("../optimize/InlineExports");
19
25
  const RuntimeGlobals = require("../runtime/RuntimeGlobals");
20
26
  const Template = require("../template/Template");
21
27
  const { someInIterable } = require("../util/IterableHelpers");
22
28
  const { renameIdentifiers } = require("../util/concatenate");
29
+ const { SAFE_IDENTIFIER, propertyAccess } = require("../util/property");
23
30
  const {
24
- RESERVED_IDENTIFIER,
25
- SAFE_IDENTIFIER,
26
- propertyAccess
27
- } = require("../util/property");
28
- const { getEntryRuntime, intersectRuntime } = require("../util/runtime");
31
+ getEntryRuntime,
32
+ getRuntimeKey,
33
+ intersectRuntime
34
+ } = require("../util/runtime");
29
35
  const AbstractLibraryPlugin = require("./AbstractLibraryPlugin");
30
36
 
31
37
  /** @import ExternalModule from "../externals/ExternalModule" */
38
+ /** @import { ExportInfo } from "../graph/ExportsInfo" */
39
+ /** @import Chunk from "../graph/Chunk" */
40
+ /** @import ESMExportSpecifierDependency from "../dependencies/esm/ESMExportSpecifierDependency" */
41
+ /** @import NormalModuleFactory from "../module/NormalModuleFactory" */
32
42
  /** @import { InlinedUsedName } from "../optimize/InlineExports" */
33
43
  /** @import { Source } from "webpack-sources" */
34
44
  /**
@@ -41,8 +51,10 @@ const AbstractLibraryPlugin = require("./AbstractLibraryPlugin");
41
51
  /** @import CodeGenerationResults from "../module/CodeGenerationResults" */
42
52
  /** @import Compilation from "../Compilation" */
43
53
  /** @import Compiler from "../Compiler" */
44
- /** @import ModuleGraph from "../graph/ModuleGraph" */
54
+ /** @import ModuleGraph, { LiveBinding } from "../graph/ModuleGraph" */
45
55
  /** @import Module from "../module/Module" */
56
+ /** @import ChunkGraph from "../graph/ChunkGraph" */
57
+ /** @import RuntimeTemplate from "../template/RuntimeTemplate" */
46
58
  /**
47
59
  * @import {
48
60
  * StartupRenderContext,
@@ -84,6 +96,102 @@ const PLUGIN_NAME = "ModuleLibraryPlugin";
84
96
  */
85
97
  const libraryEntryModules = new WeakMap();
86
98
 
99
+ /**
100
+ * @typedef {object} ChunkLiveExports
101
+ * @property {string[]} names the names the chunk's scope declares
102
+ * @property {Map<InstanceType<ExportInfo>, string>} exports the name each live export binds to
103
+ * @property {[string, string, string, string | false, boolean][]} setters the module id, local name, declared name, used export name and async status of each binding a module writes through a setter
104
+ * @property {boolean} hasAsync whether any setter belongs to an async module
105
+ */
106
+
107
+ /**
108
+ * @typedef {object} LiveExportCandidate
109
+ * @property {Module} module the module declaring the binding
110
+ * @property {ESMLiveExportDependency} declaration its declaration
111
+ * @property {InstanceType<ExportInfo>} exportInfo the library's export of it
112
+ * @property {string} localName the local name the export binds to
113
+ * @property {boolean} mirrored whether the module keeps its declaration and mirrors each write
114
+ */
115
+
116
+ /** @type {WeakMap<Chunk, ChunkLiveExports>} */
117
+ const chunkLiveExports = new WeakMap();
118
+
119
+ /** @type {WeakSet<NormalModuleFactory>} */
120
+ const liveExportFactories = new WeakSet();
121
+
122
+ /** @type {WeakMap<Compilation, Set<string>>} */
123
+ const hoistedNames = new WeakMap();
124
+
125
+ /**
126
+ * @typedef {object} ModuleLocalExports
127
+ * @property {Map<string, ESMExportSpecifierDependency>} specifiers each local export by its name
128
+ * @property {Map<string, ESMLiveExportDependency>} declarations each live `let` by a name it declares
129
+ */
130
+
131
+ /**
132
+ * Indexes the local exports and live `let` declarations of a module, once per module.
133
+ * @param {Module} module the module
134
+ * @param {Map<Module, ModuleLocalExports>} cache the indexes built so far
135
+ * @returns {ModuleLocalExports} the module's index
136
+ */
137
+ const getModuleLocalExports = (module, cache) => {
138
+ let result = cache.get(module);
139
+ if (result !== undefined) return result;
140
+ result = { specifiers: new Map(), declarations: new Map() };
141
+ for (const dependency of module.dependencies) {
142
+ if (isDependencyKind(dependency, "esm-export-specifier")) {
143
+ result.specifiers.set(dependency.name, dependency);
144
+ } else if (isDependencyKind(dependency, "esm-live-export")) {
145
+ for (const name of dependency.names) {
146
+ result.declarations.set(name, dependency);
147
+ }
148
+ }
149
+ }
150
+ cache.set(module, result);
151
+ return result;
152
+ };
153
+
154
+ /**
155
+ * Why a module's exported module-level bindings cannot move to the chunk's scope.
156
+ * @param {Module} module the module declaring them
157
+ * @param {Module} entry the entry module exporting them
158
+ * @param {ESMLiveExportDependency} declaration one of its declarations
159
+ * @returns {string | null} the reason they stay and mirror, empty where they are live already, null where they can move
160
+ */
161
+ const getHoistRefusal = (module, entry, declaration) => {
162
+ // A concatenation puts its modules' bindings in one scope already.
163
+ if (
164
+ module.is("concatenated") ||
165
+ (entry !== module &&
166
+ someInIterable(entry.getSourceModules(), (source) => source === module))
167
+ ) {
168
+ return "";
169
+ }
170
+ if (declaration.readByEval) {
171
+ return "the module calls eval(), and a function it creates may write a binding later";
172
+ }
173
+ return null;
174
+ };
175
+
176
+ /**
177
+ * Whether a module's code runs where the chunk's scope is not: in a hot update, or in
178
+ * another chunk of the runtime, so it can reach the declared names only through setters.
179
+ * @param {Module} module the module declaring them
180
+ * @param {ESMLiveExportDependency} declaration one of its declarations
181
+ * @param {Chunk} chunk the library's chunk
182
+ * @param {ChunkGraph} chunkGraph the chunk graph
183
+ * @returns {boolean} true when the module needs the setters
184
+ */
185
+ const needsSetters = (module, declaration, chunk, chunkGraph) =>
186
+ declaration.hot ||
187
+ !chunkGraph.isModuleInChunk(module, chunk) ||
188
+ someInIterable(
189
+ chunkGraph.getModuleChunksIterable(module),
190
+ (other) =>
191
+ other !== chunk &&
192
+ intersectRuntime(other.runtime, chunk.runtime) !== undefined
193
+ );
194
+
87
195
  /**
88
196
  * Whether the library reads every export of the entry off its exports object, never
89
197
  * binding one to a declaration of the inlined body, so no definition can be left out.
@@ -109,14 +217,6 @@ const noNativeExports = (module, moduleGraph) => {
109
217
  const toExportName = (name) =>
110
218
  SAFE_IDENTIFIER.test(name) ? name : JSON.stringify(name);
111
219
 
112
- /**
113
- * Whether the export name can also be used as the declared binding name.
114
- * @param {string} name export name
115
- * @returns {boolean} true, when the name can be declared
116
- */
117
- const isDeclarableExportName = (name) =>
118
- SAFE_IDENTIFIER.test(name) && !RESERVED_IDENTIFIER.has(name);
119
-
120
220
  /**
121
221
  * Represents the module library plugin runtime component.
122
222
  * @typedef {ModuleLibraryPluginParsed} T
@@ -142,10 +242,34 @@ class ModuleLibraryPlugin extends AbstractLibraryPlugin {
142
242
  apply(compiler) {
143
243
  super.apply(compiler);
144
244
 
245
+ // Both library types apply this plugin, and one parser tap records everything.
246
+ compiler.hooks.normalModuleFactory.tap(
247
+ PLUGIN_NAME,
248
+ (normalModuleFactory) => {
249
+ if (liveExportFactories.has(normalModuleFactory)) return;
250
+ liveExportFactories.add(normalModuleFactory);
251
+ for (const type of [
252
+ JAVASCRIPT_MODULE_TYPE_AUTO,
253
+ JAVASCRIPT_MODULE_TYPE_ESM
254
+ ]) {
255
+ normalModuleFactory.hooks.parser
256
+ .for(type)
257
+ .tap(PLUGIN_NAME, (parser) => {
258
+ new ESMLiveExportParserPlugin().apply(parser);
259
+ });
260
+ }
261
+ }
262
+ );
263
+
145
264
  compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => {
146
265
  const javascriptHooks =
147
266
  JavascriptModulesPlugin.getCompilationHooks(compilation);
148
267
 
268
+ compilation.dependencyTemplates.set(
269
+ ESMLiveExportDependency,
270
+ new ESMLiveExportDependency.Template()
271
+ );
272
+
149
273
  compilation.hooks.beforeCodeGeneration.tap(PLUGIN_NAME, () => {
150
274
  const entries = libraryEntryModules.get(compilation);
151
275
  if (entries === undefined) return;
@@ -164,8 +288,214 @@ class ModuleLibraryPlugin extends AbstractLibraryPlugin {
164
288
  }
165
289
  });
166
290
 
291
+ // An exported module-level `let` or `var` of a module the chunk runs as a function
292
+ // moves to the chunk's scope under a reserved name, which the library then
293
+ // exports itself; decided before hashing, as the module's code changes.
294
+ compilation.hooks.beforeModuleHash.tap(PLUGIN_NAME, () => {
295
+ const entries = libraryEntryModules.get(compilation);
296
+ if (entries === undefined) return;
297
+ const { chunkGraph, moduleGraph } = compilation;
298
+ /** @type {Map<Module, ModuleLocalExports>} */
299
+ const localExports = new Map();
300
+ // Both library types name bindings in one compilation, so they share it.
301
+ let usedNames = hoistedNames.get(compilation);
302
+ if (usedNames === undefined) {
303
+ usedNames = new Set();
304
+ hoistedNames.set(compilation, usedNames);
305
+ }
306
+ /** @type {Map<Module, Set<string>>} */
307
+ const registeredRuntimes = new Map();
308
+ /** @type {{ chunk: Chunk, runtimeKey: string, candidates: LiveExportCandidate[] }[]} */
309
+ const chunkCandidates = [];
310
+ for (const chunk of compilation.chunks) {
311
+ if (chunkGraph.getNumberOfEntryModules(chunk) === 0) continue;
312
+ const entryOptions = chunk.getEntryOptions();
313
+ const library =
314
+ entryOptions && entryOptions.library !== undefined
315
+ ? entryOptions.library
316
+ : compilation.outputOptions.library;
317
+ if (this._parseOptionsCached(library) === false) continue;
318
+ const runtimeKey = getRuntimeKey(chunk.runtime);
319
+ /** @type {LiveExportCandidate[]} */
320
+ const candidates = [];
321
+ // why each module keeps its bindings, null where they move
322
+ /** @type {Map<Module, string | null>} */
323
+ const refusals = new Map();
324
+ for (const entry of chunkGraph.getChunkEntryModulesIterable(chunk)) {
325
+ if (!entries.has(entry.getRootModule())) continue;
326
+ for (const exportInfo of moduleGraph.getExportsInfo(entry)
327
+ .orderedExports) {
328
+ if (!exportInfo.provided) continue;
329
+ const target = exportInfo.getTarget(moduleGraph);
330
+ if (target && (!target.export || target.export.length !== 1)) {
331
+ continue;
332
+ }
333
+ const module = target ? target.module : entry;
334
+ const { specifiers, declarations } = getModuleLocalExports(
335
+ module,
336
+ localExports
337
+ );
338
+ const local = specifiers.get(
339
+ target
340
+ ? /** @type {string[]} */ (target.export)[0]
341
+ : exportInfo.name
342
+ );
343
+ const declaration = local && declarations.get(local.id);
344
+ if (!declaration) continue;
345
+ let refusal = refusals.get(module);
346
+ if (refusal === undefined) {
347
+ refusal = getHoistRefusal(module, entry, declaration);
348
+ refusals.set(module, refusal);
349
+ if (refusal) {
350
+ compilation.runtimeTemplate.analyzableBailout(
351
+ module,
352
+ `a module library may export a stale binding, since ${refusal}`
353
+ );
354
+ }
355
+ }
356
+ if (refusal === "") continue;
357
+ candidates.push({
358
+ module,
359
+ declaration,
360
+ exportInfo,
361
+ localName: local.id,
362
+ mirrored: declaration.earlyUse || refusal !== null
363
+ });
364
+ // A module runs once per runtime, so one library of it needing the
365
+ // setters makes every library of that runtime register them.
366
+ if (needsSetters(module, declaration, chunk, chunkGraph)) {
367
+ let runtimes = registeredRuntimes.get(module);
368
+ if (runtimes === undefined) {
369
+ runtimes = new Set();
370
+ registeredRuntimes.set(module, runtimes);
371
+ }
372
+ runtimes.add(runtimeKey);
373
+ }
374
+ }
375
+ }
376
+ if (candidates.length > 0) {
377
+ chunkCandidates.push({ chunk, runtimeKey, candidates });
378
+ }
379
+ }
380
+ for (const { chunk, runtimeKey, candidates } of chunkCandidates) {
381
+ /** @type {string[]} */
382
+ const names = [];
383
+ /** @type {Set<LiveBinding>} */
384
+ const declared = new Set();
385
+ /** @type {ChunkLiveExports["exports"]} */
386
+ const exports = new Map();
387
+ /** @type {ChunkLiveExports["setters"]} */
388
+ const setters = [];
389
+ /** @type {Map<Module, { runtimeKeys: string[], usedExports: Map<string, string> }>} */
390
+ const moduleRuntimeInfo = new Map();
391
+ let hasAsync = false;
392
+ for (const {
393
+ module,
394
+ declaration,
395
+ exportInfo,
396
+ localName,
397
+ mirrored
398
+ } of candidates) {
399
+ const runtimes = registeredRuntimes.get(module);
400
+ const registered =
401
+ runtimes !== undefined && runtimes.has(runtimeKey);
402
+ const isAsync = registered && moduleGraph.isAsync(module);
403
+ const meta = moduleGraph.getMeta(module);
404
+ // Renaming takes the module's own declaration, which an early use needs in
405
+ // order to throw and eval() to read, so such a module mirrors each write.
406
+ const bindings =
407
+ registered || mirrored
408
+ ? meta.liveSetters || (meta.liveSetters = new Map())
409
+ : meta.liveBindings || (meta.liveBindings = new Map());
410
+ for (const name of declaration.names) {
411
+ let binding = bindings.get(name);
412
+ if (binding === undefined) {
413
+ let hoisted = `__webpack_live_${name}__`;
414
+ for (let i = 1; usedNames.has(hoisted); i++) {
415
+ hoisted = `__webpack_live_${name}_${i}__`;
416
+ }
417
+ usedNames.add(hoisted);
418
+ binding = {
419
+ name: hoisted,
420
+ runtimes: new Set(),
421
+ registered: new Set()
422
+ };
423
+ bindings.set(name, binding);
424
+ }
425
+ if (declared.has(binding)) continue;
426
+ declared.add(binding);
427
+ binding.runtimes.add(runtimeKey);
428
+ names.push(binding.name);
429
+ if (!registered) continue;
430
+ binding.registered.add(runtimeKey);
431
+ let runtimeInfo = moduleRuntimeInfo.get(module);
432
+ if (runtimeInfo === undefined) {
433
+ runtimeInfo = { runtimeKeys: [], usedExports: new Map() };
434
+ // Shared chunks generate the module for a union of runtimes;
435
+ // guarded setters apply when any of them registers this binding.
436
+ for (const runtime of chunkGraph.getModuleRuntimes(module)) {
437
+ if (intersectRuntime(runtime, chunk.runtime) === undefined) {
438
+ continue;
439
+ }
440
+ runtimeInfo.runtimeKeys.push(getRuntimeKey(runtime));
441
+ }
442
+ const exportsInfo = moduleGraph.getExportsInfo(module);
443
+ for (const [exportName, specifier] of getModuleLocalExports(
444
+ module,
445
+ localExports
446
+ ).specifiers) {
447
+ // A module that already ran seeds the binding from its first used alias.
448
+ if (runtimeInfo.usedExports.has(specifier.id)) continue;
449
+ const usedName = exportsInfo.getUsedName(
450
+ exportName,
451
+ chunk.runtime
452
+ );
453
+ if (typeof usedName === "string") {
454
+ runtimeInfo.usedExports.set(specifier.id, usedName);
455
+ }
456
+ }
457
+ moduleRuntimeInfo.set(module, runtimeInfo);
458
+ }
459
+ for (const key of runtimeInfo.runtimeKeys) {
460
+ binding.runtimes.add(key);
461
+ binding.registered.add(key);
462
+ }
463
+ const used = runtimeInfo.usedExports.get(name);
464
+ hasAsync = hasAsync || isAsync;
465
+ setters.push([
466
+ JSON.stringify(chunkGraph.getModuleId(module)),
467
+ name,
468
+ binding.name,
469
+ used === undefined ? false : used,
470
+ isAsync
471
+ ]);
472
+ }
473
+ exports.set(
474
+ exportInfo,
475
+ /** @type {LiveBinding} */ (bindings.get(localName)).name
476
+ );
477
+ }
478
+ if (names.length > 0) {
479
+ chunkLiveExports.set(chunk, { names, exports, setters, hasAsync });
480
+ }
481
+ }
482
+ });
483
+
167
484
  // The stashed exports source is re-emitted only where the entry is wrapped;
168
485
  // inlined directly, the helpers it pulled in have no reader and can go.
486
+ compilation.hooks.additionalChunkRuntimeRequirements.tap(
487
+ PLUGIN_NAME,
488
+ (chunk, set) => {
489
+ const live = chunkLiveExports.get(chunk);
490
+ if (live && live.setters.length > 0) {
491
+ set.add(RuntimeGlobals.moduleCache);
492
+ if (live.hasAsync) {
493
+ set.add(RuntimeGlobals.asyncModuleExportSymbol);
494
+ }
495
+ }
496
+ }
497
+ );
498
+
169
499
  compilation.hooks.additionalChunkRuntimeRequirements.tap(
170
500
  PLUGIN_NAME,
171
501
  (chunk, set, { chunkGraph, codeGenerationResults }) => {
@@ -550,7 +880,15 @@ class ModuleLibraryPlugin extends AbstractLibraryPlugin {
550
880
  exportsAwaited,
551
881
  runtimeTemplate
552
882
  } = renderContext;
553
- let result = new ConcatSource(source);
883
+ const live = chunkLiveExports.get(chunk);
884
+ // Declared before the startup runs the module functions assigning them
885
+ let result = live
886
+ ? new ConcatSource(
887
+ `${runtimeTemplate.renderLet()} ${live.names.join(", ")};\n`,
888
+ this._renderLiveExportSetters(live, runtimeTemplate),
889
+ source
890
+ )
891
+ : new ConcatSource(source);
554
892
  // A merged entry exposes what its modules expose together, so the ESM
555
893
  // export list is theirs rather than the last module's alone.
556
894
  const mergedModules = mergedEntryModules(chunk, chunkGraph, compilation);
@@ -707,7 +1045,13 @@ class ModuleLibraryPlugin extends AbstractLibraryPlugin {
707
1045
  /** @type {string | undefined} */
708
1046
  let finalName;
709
1047
 
710
- if (definition) {
1048
+ const liveName = live && live.exports.get(exportInfo);
1049
+
1050
+ if (liveName) {
1051
+ finalName = liveName;
1052
+ // the body still defines an export it does not leave out on the object
1053
+ if (!definition) needExportsDeclaration = true;
1054
+ } else if (definition) {
711
1055
  finalName = definition;
712
1056
  } else {
713
1057
  // Fallback to `__webpack_exports__` property access
@@ -777,13 +1121,8 @@ class ModuleLibraryPlugin extends AbstractLibraryPlugin {
777
1121
  );
778
1122
 
779
1123
  for (const [exportName, final] of exports) {
780
- if (isDeclarableExportName(exportName)) {
781
- result.add(
782
- `export ${runtimeTemplate.renderConst()} ${exportName} = ${final};\n`
783
- );
784
- continue;
785
- }
786
- // Bind to a generated name, the export name can't be declared
1124
+ // A declaration under the export's own name would shadow a global of that
1125
+ // name every module of the chunk may read, so a generated name binds it.
787
1126
  const name = toLocalName(exportName);
788
1127
  result.add(
789
1128
  `${runtimeTemplate.renderConst()} ${name} = ${final};\nexport { ${name} as ${toExportName(exportName)} };\n`
@@ -797,6 +1136,43 @@ class ModuleLibraryPlugin extends AbstractLibraryPlugin {
797
1136
  return result;
798
1137
  }
799
1138
 
1139
+ /**
1140
+ * Renders the setters through which hot modules, an update included, write the
1141
+ * bindings the chunk's scope declares; a list per name, as several libraries may.
1142
+ * A module that ran before the chunk loaded hands over its value through its exports.
1143
+ * @param {ChunkLiveExports} live the chunk's live bindings
1144
+ * @param {RuntimeTemplate} runtimeTemplate the runtime template
1145
+ * @returns {string} the registrations
1146
+ */
1147
+ _renderLiveExportSetters({ setters, hasAsync }, runtimeTemplate) {
1148
+ if (setters.length === 0) return "";
1149
+ const exports = hasAsync
1150
+ ? `(isAsync ? module.exports[${RuntimeGlobals.asyncModuleExportSymbol}] : module.exports)`
1151
+ : "module.exports";
1152
+ const register = "__webpack_live_register__";
1153
+ return Template.asString([
1154
+ `var ${register} = ${runtimeTemplate.basicFunction(
1155
+ hasAsync ? "id, name, set, key, isAsync" : "id, name, set, key",
1156
+ [
1157
+ `var setters = ${RuntimeGlobals.liveExportSetters} = ${RuntimeGlobals.liveExportSetters} || {};`,
1158
+ "setters = setters[id] = setters[id] || {};",
1159
+ "(setters[name] = setters[name] || []).push(set);",
1160
+ `var module = ${RuntimeGlobals.moduleCache}[id];`,
1161
+ // A module still before its declaration throws, and hands the value over later.
1162
+ `if (module && key) try { set(${exports}[key]); } catch (e) {}`
1163
+ ]
1164
+ )};`,
1165
+ ...setters.map(
1166
+ ([id, name, hoisted, used, isAsync]) =>
1167
+ `${register}(${id}, ${JSON.stringify(name)}, ${runtimeTemplate.basicFunction(
1168
+ "value",
1169
+ `${hoisted} = value;`
1170
+ )}${used ? `, ${JSON.stringify(used)}${isAsync ? ", 1" : ""}` : ""});`
1171
+ ),
1172
+ ""
1173
+ ]);
1174
+ }
1175
+
800
1176
  /**
801
1177
  * Renders module content.
802
1178
  * @param {Source} source source