webpack 5.108.4 → 5.109.1

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 (200) hide show
  1. package/bin/webpack.js +12 -0
  2. package/lib/APIPlugin.js +48 -29
  3. package/lib/CacheFacade.js +8 -0
  4. package/lib/ChunkGraph.js +17 -15
  5. package/lib/ChunkGroup.js +1 -0
  6. package/lib/CompatibilityPlugin.js +62 -29
  7. package/lib/Compilation.js +58 -6
  8. package/lib/ConstPlugin.js +11 -11
  9. package/lib/ContextModule.js +239 -6
  10. package/lib/ContextModuleFactory.js +139 -14
  11. package/lib/DefinePlugin.js +433 -112
  12. package/lib/Entrypoint.js +1 -1
  13. package/lib/ExportsInfo.js +22 -5
  14. package/lib/ExportsInfoApiPlugin.js +2 -2
  15. package/lib/ExternalModule.js +107 -5
  16. package/lib/ExternalModuleFactoryPlugin.js +20 -1
  17. package/lib/FileSystemInfo.js +256 -100
  18. package/lib/FlagDependencyUsagePlugin.js +33 -12
  19. package/lib/HotModuleReplacementPlugin.js +18 -15
  20. package/lib/InitFragment.js +20 -32
  21. package/lib/Module.js +3 -0
  22. package/lib/ModuleFilenameHelpers.js +2 -2
  23. package/lib/ModuleTypeConstants.js +8 -1
  24. package/lib/MultiCompiler.js +13 -2
  25. package/lib/MultiWatching.js +1 -0
  26. package/lib/NodeStuffPlugin.js +51 -33
  27. package/lib/NormalModule.js +175 -401
  28. package/lib/NormalModuleFactory.js +76 -2
  29. package/lib/ProgressPlugin.js +211 -119
  30. package/lib/ProvidePlugin.js +2 -2
  31. package/lib/RuntimeGlobals.js +47 -0
  32. package/lib/RuntimePlugin.js +67 -107
  33. package/lib/RuntimeTemplate.js +304 -16
  34. package/lib/Template.js +23 -3
  35. package/lib/UseStrictPlugin.js +1 -1
  36. package/lib/WebpackIsIncludedPlugin.js +1 -1
  37. package/lib/WebpackOptionsApply.js +24 -19
  38. package/lib/asset/AssetGenerator.js +110 -28
  39. package/lib/asset/AssetModulesPlugin.js +92 -2
  40. package/lib/asset/WebManifestGenerator.js +164 -0
  41. package/lib/asset/WebManifestParser.js +130 -0
  42. package/lib/async-modules/AwaitDependenciesInitFragment.js +14 -4
  43. package/lib/async-modules/isGeneratorLowered.js +26 -0
  44. package/lib/cache/PackFileCacheStrategy.js +9 -3
  45. package/lib/config/browserslistTargetHandler.js +40 -0
  46. package/lib/config/defaults.js +219 -29
  47. package/lib/config/normalization.js +26 -0
  48. package/lib/config/target.js +9 -1
  49. package/lib/container/HoistContainerReferencesPlugin.js +47 -55
  50. package/lib/css/CssGenerator.js +40 -31
  51. package/lib/css/CssLoadingRuntimeModule.js +5 -1
  52. package/lib/css/CssModulesPlugin.js +13 -0
  53. package/lib/css/CssParser.js +729 -313
  54. package/lib/css/syntax.js +1371 -861
  55. package/lib/dependencies/AMDDefineDependencyParserPlugin.js +6 -6
  56. package/lib/dependencies/AMDPlugin.js +2 -2
  57. package/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js +13 -13
  58. package/lib/dependencies/CommonJsDependencyHelpers.js +39 -0
  59. package/lib/dependencies/CommonJsExportRequireDependency.js +19 -0
  60. package/lib/dependencies/CommonJsExportsDependency.js +47 -2
  61. package/lib/dependencies/CommonJsExportsParserPlugin.js +10 -10
  62. package/lib/dependencies/CommonJsImportsParserPlugin.js +18 -18
  63. package/lib/dependencies/CommonJsPlugin.js +2 -2
  64. package/lib/dependencies/CommonJsRequireDependency.js +26 -1
  65. package/lib/dependencies/CommonJsSelfReferenceDependency.js +32 -1
  66. package/lib/dependencies/ContextDependencyHelpers.js +3 -3
  67. package/lib/dependencies/CreateRequireParserPlugin.js +6 -6
  68. package/lib/dependencies/CssIcssExportDependency.js +162 -71
  69. package/lib/dependencies/CssUrlDependency.js +35 -4
  70. package/lib/dependencies/ExternalModuleInitFragmentDependency.js +2 -2
  71. package/lib/dependencies/HarmonyCompatibilityDependency.js +32 -14
  72. package/lib/dependencies/HarmonyDetectionParserPlugin.js +43 -13
  73. package/lib/dependencies/HarmonyEvaluatedImportSpecifierDependency.js +2 -1
  74. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +7 -19
  75. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +17 -9
  76. package/lib/dependencies/HarmonyImportDependency.js +13 -2
  77. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +11 -11
  78. package/lib/dependencies/HarmonyImportSpecifierDependency.js +10 -7
  79. package/lib/dependencies/HarmonyModulesPlugin.js +6 -0
  80. package/lib/dependencies/HarmonyTopLevelThisParserPlugin.js +1 -1
  81. package/lib/dependencies/HtmlEntryDependency.js +797 -172
  82. package/lib/dependencies/HtmlSourceDependency.js +26 -0
  83. package/lib/dependencies/ImportDependency.js +43 -1
  84. package/lib/dependencies/ImportMetaContextDependencyParserPlugin.js +31 -18
  85. package/lib/dependencies/ImportMetaContextPlugin.js +38 -7
  86. package/lib/dependencies/ImportMetaGlobDependency.js +81 -0
  87. package/lib/dependencies/ImportMetaGlobDependencyParserPlugin.js +78 -0
  88. package/lib/dependencies/ImportMetaGlobHelpers.js +660 -0
  89. package/lib/dependencies/ImportMetaPlugin.js +532 -180
  90. package/lib/dependencies/ImportMetaResolveDependency.js +90 -0
  91. package/lib/dependencies/ImportParserPlugin.js +80 -17
  92. package/lib/dependencies/ImportPhase.js +10 -8
  93. package/lib/dependencies/LoaderPlugin.js +5 -1
  94. package/lib/dependencies/RequireContextDependencyParserPlugin.js +1 -1
  95. package/lib/dependencies/RequireEnsureDependenciesBlockParserPlugin.js +3 -6
  96. package/lib/dependencies/RequireIncludeDependencyParserPlugin.js +4 -11
  97. package/lib/dependencies/SystemPlugin.js +2 -4
  98. package/lib/dependencies/TopLevelAwaitDependency.js +93 -0
  99. package/lib/dependencies/URLDependency.js +141 -21
  100. package/lib/dependencies/{WorkerPlugin.js → WorkerAndWorkletPlugin.js} +324 -112
  101. package/lib/dependencies/WorkerDependency.js +86 -18
  102. package/lib/dependencies/WorkletDependency.js +278 -0
  103. package/lib/dll/DelegatedModuleFactoryPlugin.js +19 -0
  104. package/lib/errors/EnvironmentNotSupportAsyncWarning.js +1 -1
  105. package/lib/errors/LoaderLoadingError.js +20 -0
  106. package/lib/errors/ModuleParseError.js +39 -22
  107. package/lib/errors/NodeStuffInWebError.js +1 -1
  108. package/lib/esm/ModuleChunkFormatPlugin.js +47 -14
  109. package/lib/esm/ModuleChunkLoadingPlugin.js +8 -1
  110. package/lib/esm/ModuleChunkLoadingRuntimeModule.js +29 -1
  111. package/lib/hmr/lazyCompilationBackend.js +51 -12
  112. package/lib/html/HtmlGenerator.js +907 -15
  113. package/lib/html/HtmlModule.js +2 -2
  114. package/lib/html/HtmlModulesPlugin.js +610 -166
  115. package/lib/html/HtmlParser.js +603 -247
  116. package/lib/html/favicon.svg +1 -0
  117. package/lib/html/syntax.js +3451 -2762
  118. package/lib/ids/IdHelpers.js +25 -11
  119. package/lib/index.js +6 -0
  120. package/lib/javascript/ArrayPushCallbackChunkFormatPlugin.js +4 -5
  121. package/lib/javascript/BasicEvaluatedExpression.js +366 -48
  122. package/lib/javascript/JavascriptGenerator.js +197 -49
  123. package/lib/javascript/JavascriptModulesPlugin.js +178 -24
  124. package/lib/javascript/JavascriptParser.js +704 -355
  125. package/lib/javascript/JavascriptParserHelpers.js +3 -6
  126. package/lib/javascript/syntax.js +5037 -0
  127. package/lib/library/ModuleLibraryPlugin.js +38 -1
  128. package/lib/loaders/LoaderRunner.js +714 -0
  129. package/lib/loaders/loadLoader.js +100 -0
  130. package/lib/node/ReadFileCompileAsyncWasmPlugin.js +29 -2
  131. package/lib/node/ReadFileCompileWasmPlugin.js +24 -2
  132. package/lib/optimize/AggressiveMergingPlugin.js +19 -15
  133. package/lib/optimize/ConcatenatedModule.js +139 -31
  134. package/lib/optimize/FlagIncludedChunksPlugin.js +13 -3
  135. package/lib/optimize/InnerGraphPlugin.js +50 -30
  136. package/lib/optimize/ModuleConcatenationPlugin.js +139 -24
  137. package/lib/optimize/SideEffectsFlagPlugin.js +86 -43
  138. package/lib/optimize/SplitChunksPlugin.js +146 -44
  139. package/lib/prefetch/ChunkPrefetchPreloadPlugin.js +15 -0
  140. package/lib/prefetch/ChunkPreloadTriggerRuntimeModule.js +24 -13
  141. package/lib/prefetch/ResourceHintPlugin.js +687 -0
  142. package/lib/prefetch/ResourceHintRuntimeModule.js +149 -0
  143. package/lib/prefetch/StartupAssetHintRuntimeModule.js +210 -0
  144. package/lib/prefetch/parseResourceHintOptions.js +103 -0
  145. package/lib/rules/RuleSetCompiler.js +114 -0
  146. package/lib/runtime/AsyncModuleGeneratorRuntimeModule.js +56 -0
  147. package/lib/runtime/AsyncModuleRuntimeModule.js +24 -8
  148. package/lib/runtime/AutoPublicPathRuntimeModule.js +7 -1
  149. package/lib/runtime/CommonJsWrapRuntimeModule.js +37 -0
  150. package/lib/runtime/GetWorkletBootstrapRuntimeModule.js +59 -0
  151. package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +204 -8
  152. package/lib/runtime/SetAnonymousDefaultNameRuntimeModule.js +4 -1
  153. package/lib/schemes/HttpUriPlugin.js +40 -1
  154. package/lib/schemes/VirtualUrlPlugin.js +1 -2
  155. package/lib/serialization/BinaryMiddleware.js +270 -938
  156. package/lib/serialization/FileMiddleware.js +29 -3
  157. package/lib/stats/DefaultStatsFactoryPlugin.js +229 -194
  158. package/lib/stats/DefaultStatsPresetPlugin.js +2 -0
  159. package/lib/stats/DefaultStatsPrinterPlugin.js +36 -168
  160. package/lib/stats/StatsFactory.js +46 -17
  161. package/lib/url/URLParserPlugin.js +66 -13
  162. package/lib/util/AsyncQueue.js +122 -72
  163. package/lib/util/SetHelpers.js +1 -1
  164. package/lib/util/StackedMap.js +122 -48
  165. package/lib/util/binarySearchBounds.js +2 -2
  166. package/lib/util/concatenate.js +40 -14
  167. package/lib/util/createHooksRegistry.js +13 -5
  168. package/lib/util/dataURL.js +2 -2
  169. package/lib/util/deterministicGrouping.js +7 -5
  170. package/lib/util/formatSize.js +6 -2
  171. package/lib/util/globUtils.js +710 -0
  172. package/lib/util/identifier.js +23 -6
  173. package/lib/util/implicitTypeLoaderFallback.js +62 -0
  174. package/lib/util/internalSerializables.js +88 -71
  175. package/lib/util/magicComment.js +121 -25
  176. package/lib/util/numberHash.js +2 -2
  177. package/lib/wasm-async/AsyncWasmCompileRuntimeModule.js +24 -18
  178. package/lib/wasm-async/AsyncWasmLoadingRuntimeModule.js +33 -22
  179. package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +79 -16
  180. package/lib/web/FetchCompileAsyncWasmPlugin.js +19 -0
  181. package/lib/web/FetchCompileWasmPlugin.js +14 -0
  182. package/lib/web/JsonpChunkLoadingRuntimeModule.js +2 -0
  183. package/lib/webpack.js +65 -0
  184. package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +3 -0
  185. package/module.d.ts +21 -0
  186. package/package.json +12 -11
  187. package/schemas/WebpackOptions.check.js +1 -1
  188. package/schemas/WebpackOptions.json +759 -36
  189. package/schemas/plugins/HtmlParserOptions.check.js +1 -1
  190. package/schemas/plugins/ProgressPlugin.check.js +1 -1
  191. package/schemas/plugins/ProgressPlugin.json +17 -1
  192. package/schemas/plugins/container/ContainerReferencePlugin.check.js +1 -1
  193. package/schemas/plugins/container/ContainerReferencePlugin.json +1 -0
  194. package/schemas/plugins/container/ExternalsType.check.js +1 -1
  195. package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
  196. package/schemas/plugins/container/ModuleFederationPlugin.json +1 -0
  197. package/schemas/plugins/css/CssAutoOrModuleParserOptions.check.js +1 -1
  198. package/schemas/plugins/css/CssModuleParserOptions.check.js +1 -1
  199. package/schemas/plugins/css/CssParserOptions.check.js +1 -1
  200. package/types.d.ts +1212 -99
@@ -31,17 +31,25 @@ class AsyncModuleRuntimeModule extends HelperRuntimeModule {
31
31
  const defer = this._deferInterop;
32
32
  const cst = runtimeTemplate.renderConst();
33
33
  const lt = runtimeTemplate.renderLet();
34
+ const supportsSymbol = runtimeTemplate.supportsSymbol();
35
+ /** @type {(name: string, fallback: string) => string} */
36
+ const renderSymbol = (name, fallback) =>
37
+ supportsSymbol
38
+ ? `Symbol("${name}")`
39
+ : `hasSymbol ? Symbol("${name}") : "${fallback}"`;
34
40
  return Template.asString([
35
- `${cst} hasSymbol = typeof Symbol === "function";`,
36
- `${cst} webpackQueues = hasSymbol ? Symbol("webpack queues") : "__webpack_queues__";`,
41
+ ...(supportsSymbol
42
+ ? []
43
+ : [`${cst} hasSymbol = typeof Symbol === "function";`]),
44
+ `${cst} webpackQueues = ${renderSymbol("webpack queues", "__webpack_queues__")};`,
37
45
  `${cst} webpackExports = ${
38
46
  defer ? `${RuntimeGlobals.asyncModuleExportSymbol}= ` : ""
39
- }hasSymbol ? Symbol("webpack exports") : "${RuntimeGlobals.exports}";`,
40
- `${cst} webpackError = hasSymbol ? Symbol("webpack error") : "__webpack_error__";`,
47
+ }${renderSymbol("webpack exports", RuntimeGlobals.exports)};`,
48
+ `${cst} webpackError = ${renderSymbol("webpack error", "__webpack_error__")};`,
41
49
  defer
42
50
  ? Template.asString([
43
- `${cst} webpackDone = ${RuntimeGlobals.asyncModuleDoneSymbol} = hasSymbol ? Symbol("webpack done") : "__webpack_done__";`,
44
- `${cst} webpackDefer = ${RuntimeGlobals.deferredModuleAsyncTransitiveDependenciesSymbol} = hasSymbol ? Symbol("webpack defer") : "__webpack_defer__";`,
51
+ `${cst} webpackDone = ${RuntimeGlobals.asyncModuleDoneSymbol} = ${renderSymbol("webpack done", "__webpack_done__")};`,
52
+ `${cst} webpackDefer = ${RuntimeGlobals.deferredModuleAsyncTransitiveDependenciesSymbol} = ${renderSymbol("webpack defer", "__webpack_defer__")};`,
45
53
  `${RuntimeGlobals.deferredModuleAsyncTransitiveDependencies} = ${runtimeTemplate.basicFunction(
46
54
  "asyncDeps",
47
55
  [
@@ -176,7 +184,7 @@ class AsyncModuleRuntimeModule extends HelperRuntimeModule {
176
184
  "q !== queue && !depQueues.has(q) && (depQueues.add(q), q && !q.d && (fn.r++, q.push(fn)))",
177
185
  "q"
178
186
  )};`,
179
- `currentDeps.map(${runtimeTemplate.expressionFunction(
187
+ `currentDeps.forEach(${runtimeTemplate.expressionFunction(
180
188
  `${
181
189
  defer ? "dep[webpackDefer]||" : ""
182
190
  }dep[webpackQueues](fnQueue)`,
@@ -188,10 +196,18 @@ class AsyncModuleRuntimeModule extends HelperRuntimeModule {
188
196
  ])}`,
189
197
  `${cst} done = ${runtimeTemplate.expressionFunction(
190
198
  `(err ? reject(promise[webpackError] = err) : outerResolve(exports)), resolveQueue(queue)${
191
- defer ? ", promise[webpackDone] = true" : ""
199
+ defer
200
+ ? ", promise[webpackDone] = true, module.evaluatingAsync = false"
201
+ : ""
192
202
  }`,
193
203
  "err"
194
204
  )}`,
205
+ // Track the async body's whole lifetime (evaluating +
206
+ // evaluating-async states) with a dedicated flag — the sync require
207
+ // wrapper clears `module.evaluating` as soon as `.a` returns, so a
208
+ // deferred namespace reaching this module through a cycle relies on
209
+ // `evaluatingAsync` to keep throwing until it is fully evaluated.
210
+ defer ? "module.evaluatingAsync = true;" : "",
195
211
  "body(handle, done);",
196
212
  `${runtimeTemplate.optionalChaining("queue", "d < 0")} && (queue.d = 0);`
197
213
  ])};`
@@ -47,12 +47,18 @@ class AutoPublicPathRuntimeModule extends RuntimeModule {
47
47
  ? "globalThis"
48
48
  : RuntimeGlobals.global;
49
49
 
50
+ const entryOptions = chunk.getEntryOptions();
51
+ // A worklet chunk is always loaded as a module via `addModule`, so it can
52
+ // read `import.meta.url` directly instead of the worker-scope detection.
53
+ const fromImportMeta =
54
+ scriptType === "module" || Boolean(entryOptions && entryOptions.worklet);
55
+
50
56
  const runtimeTemplate = compilation.runtimeTemplate;
51
57
  const cst = runtimeTemplate.renderConst();
52
58
  const lt = runtimeTemplate.renderLet();
53
59
  return Template.asString([
54
60
  `${lt} scriptUrl;`,
55
- scriptType === "module"
61
+ fromImportMeta
56
62
  ? `if (typeof ${importMetaName}.url === "string") scriptUrl = ${importMetaName}.url`
57
63
  : Template.asString([
58
64
  `if (${global}.importScripts) scriptUrl = ${global}.location + "";`,
@@ -0,0 +1,37 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ */
4
+
5
+ "use strict";
6
+
7
+ const RuntimeGlobals = require("../RuntimeGlobals");
8
+ const Template = require("../Template");
9
+ const HelperRuntimeModule = require("./HelperRuntimeModule");
10
+
11
+ /** @typedef {import("../Compilation")} Compilation */
12
+
13
+ class CommonJsWrapRuntimeModule extends HelperRuntimeModule {
14
+ constructor() {
15
+ super("wrap commonjs module");
16
+ }
17
+
18
+ /**
19
+ * Generates runtime code for this runtime module.
20
+ * @returns {string | null} runtime code
21
+ */
22
+ generate() {
23
+ const compilation = /** @type {Compilation} */ (this.compilation);
24
+ const { runtimeTemplate } = compilation;
25
+ const fn = RuntimeGlobals.commonJsWrap;
26
+ return Template.asString([
27
+ "// execute a CommonJS module body with real module/exports objects, returning the final exports",
28
+ `${fn} = ${runtimeTemplate.basicFunction("body", [
29
+ `${runtimeTemplate.renderConst()} mod = { exports: {} };`,
30
+ "body.call(mod.exports, mod, mod.exports);",
31
+ "return mod.exports;"
32
+ ])};`
33
+ ]);
34
+ }
35
+ }
36
+
37
+ module.exports = CommonJsWrapRuntimeModule;
@@ -0,0 +1,59 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ Author sheo13666q
4
+ */
5
+
6
+ "use strict";
7
+
8
+ const RuntimeGlobals = require("../RuntimeGlobals");
9
+ const RuntimeModule = require("../RuntimeModule");
10
+ const Template = require("../Template");
11
+
12
+ /** @typedef {import("../Compilation")} Compilation */
13
+
14
+ /**
15
+ * Provides a single object URL (one per base URI) for the worklet bootstrap
16
+ * script. A worklet global scope has no `self` and no `location`; this script
17
+ * sets them up before the emitted chunks — which assume a worker-like scope —
18
+ * are added via `addModule`. Deduping by base URI avoids leaking a new object
19
+ * URL per worklet.
20
+ */
21
+ class GetWorkletBootstrapRuntimeModule extends RuntimeModule {
22
+ constructor() {
23
+ super("get worklet bootstrap", RuntimeModule.STAGE_ATTACH);
24
+ }
25
+
26
+ /**
27
+ * Generates runtime code for this runtime module.
28
+ * @returns {string | null} runtime code
29
+ */
30
+ generate() {
31
+ const { getWorkletBootstrap, baseURI } = RuntimeGlobals;
32
+ const { runtimeTemplate } = /** @type {Compilation} */ (this.compilation);
33
+ // The arrow inside the blob string is fine — it runs in the worklet (always
34
+ // a module scope); the surrounding functions must respect `output.environment`.
35
+ const getter = runtimeTemplate.basicFunction("", [
36
+ `var base = ${baseURI};`,
37
+ "if (!cache.has(base)) {",
38
+ Template.indent([
39
+ "var script = [",
40
+ Template.indent([
41
+ // worklet scopes have no `self`; chunks assume a worker-like scope
42
+ '"globalThis.self = globalThis.self || globalThis;",',
43
+ // some runtime modules read `location`; forward the document base
44
+ '"globalThis.location = " + JSON.stringify(base) + ";"'
45
+ ]),
46
+ '].join("\\n");',
47
+ 'cache.set(base, URL.createObjectURL(new Blob([script], { type: "text/javascript" })));'
48
+ ]),
49
+ "}",
50
+ "return cache.get(base);"
51
+ ]);
52
+ return `${getWorkletBootstrap} = (${runtimeTemplate.basicFunction("", [
53
+ "var cache = new Map();",
54
+ `return ${getter};`
55
+ ])})();`;
56
+ }
57
+ }
58
+
59
+ module.exports = GetWorkletBootstrapRuntimeModule;
@@ -6,12 +6,179 @@
6
6
 
7
7
  const RuntimeGlobals = require("../RuntimeGlobals");
8
8
  const Template = require("../Template");
9
+ const HarmonyImportDependency = require("../dependencies/HarmonyImportDependency");
9
10
  const HelperRuntimeModule = require("./HelperRuntimeModule");
10
11
 
12
+ /** @typedef {import("../ChunkGraph")} ChunkGraph */
13
+ /** @typedef {import("../Module")} Module */
14
+ /** @typedef {import("../ModuleGraph")} ModuleGraph */
11
15
  /** @typedef {import("../Module").RuntimeRequirements} RuntimeRequirements */
12
16
  /** @typedef {import("../Module").ExportsType} ExportsType */
13
17
  /** @typedef {import("../ChunkGraph").ModuleId} ModuleId */
14
18
 
19
+ /**
20
+ * @typedef {object} DeferredCycleState
21
+ * @property {Map<Module, Set<Module>>} sccOf strongly-connected component per module (shared object per component)
22
+ * @property {Map<Module, Set<Module> | null>} peers memoized SCC peers (component minus the module) per deferred module
23
+ */
24
+
25
+ /** @type {WeakMap<ModuleGraph, DeferredCycleState>} */
26
+ const deferredCycleCache = new WeakMap();
27
+
28
+ /**
29
+ * Materializes the active harmony-import targets of a module (deferred edges
30
+ * included, matching the spec's `RequestedModules` recursion).
31
+ * @param {ModuleGraph} moduleGraph the module graph
32
+ * @param {Module} module the module
33
+ * @returns {Module[]} imported modules
34
+ */
35
+ function harmonyImportTargets(moduleGraph, module) {
36
+ const connections = moduleGraph.getOutgoingConnectionsByModule(module);
37
+ if (!connections) return [];
38
+ /** @type {Module[]} */
39
+ const targets = [];
40
+ for (const [dep, moduleConnections] of connections) {
41
+ if (
42
+ dep &&
43
+ moduleConnections.some(
44
+ (c) =>
45
+ c.dependency instanceof HarmonyImportDependency &&
46
+ c.isTargetActive(undefined)
47
+ )
48
+ ) {
49
+ targets.push(dep);
50
+ }
51
+ }
52
+ return targets;
53
+ }
54
+
55
+ /**
56
+ * Assigns every module reachable from `seed` (through active harmony imports)
57
+ * to its strongly-connected component via an iterative Tarjan pass, writing the
58
+ * results into `sccOf`. Modules already assigned by an earlier pass are treated
59
+ * as finished, so across all deferred imports every edge is visited once
60
+ * (O(V + E) total) rather than re-walked per import.
61
+ * @param {ModuleGraph} moduleGraph the module graph
62
+ * @param {Module} seed the module to explore from
63
+ * @param {Map<Module, Set<Module>>} sccOf module-to-component map to populate
64
+ * @returns {void}
65
+ */
66
+ function assignStronglyConnectedComponents(moduleGraph, seed, sccOf) {
67
+ if (sccOf.has(seed)) return;
68
+ /** @type {Map<Module, number>} */
69
+ const index = new Map();
70
+ /** @type {Map<Module, number>} */
71
+ const low = new Map();
72
+ /** @type {Set<Module>} */
73
+ const onStack = new Set();
74
+ /** @type {Module[]} */
75
+ const componentStack = [];
76
+ /** @type {{ node: Module, targets: Module[], i: number }[]} */
77
+ const work = [];
78
+ let counter = 0;
79
+ /**
80
+ * @param {Module} node node to open
81
+ */
82
+ const open = (node) => {
83
+ index.set(node, counter);
84
+ low.set(node, counter);
85
+ counter++;
86
+ componentStack.push(node);
87
+ onStack.add(node);
88
+ work.push({ node, targets: harmonyImportTargets(moduleGraph, node), i: 0 });
89
+ };
90
+ open(seed);
91
+ while (work.length > 0) {
92
+ const frame = work[work.length - 1];
93
+ if (frame.i < frame.targets.length) {
94
+ const next = frame.targets[frame.i++];
95
+ // Already in a finished component (from this or a prior pass): skip.
96
+ if (sccOf.has(next)) continue;
97
+ if (!index.has(next)) {
98
+ open(next);
99
+ } else if (onStack.has(next)) {
100
+ const nodeLow = /** @type {number} */ (low.get(frame.node));
101
+ const nextIndex = /** @type {number} */ (index.get(next));
102
+ if (nextIndex < nodeLow) low.set(frame.node, nextIndex);
103
+ }
104
+ continue;
105
+ }
106
+ work.pop();
107
+ const node = frame.node;
108
+ const nodeLow = /** @type {number} */ (low.get(node));
109
+ if (work.length > 0) {
110
+ const parent = work[work.length - 1].node;
111
+ if (nodeLow < /** @type {number} */ (low.get(parent))) {
112
+ low.set(parent, nodeLow);
113
+ }
114
+ }
115
+ if (nodeLow === index.get(node)) {
116
+ /** @type {Set<Module>} */
117
+ const component = new Set();
118
+ let member;
119
+ do {
120
+ member = /** @type {Module} */ (componentStack.pop());
121
+ onStack.delete(member);
122
+ component.add(member);
123
+ } while (member !== node);
124
+ for (const m of component) sccOf.set(m, component);
125
+ }
126
+ }
127
+ }
128
+
129
+ /**
130
+ * Per the TC39 import-defer spec's `ReadyForSyncExecution`, forcing evaluation
131
+ * of a deferred module must throw when any module in its transitive static
132
+ * import closure is currently evaluating. Only a module in `module`'s own
133
+ * strongly-connected component can be evaluating at that point (anything else it
134
+ * imports is either already evaluated or not started), so we emit just the SCC
135
+ * peers instead of the whole (potentially huge) forward closure.
136
+ * @param {ModuleGraph} moduleGraph the module graph
137
+ * @param {Module} module the deferred module
138
+ * @returns {Set<Module> | null} the SCC peers when cyclic, otherwise null
139
+ */
140
+ function getDeferredCycleModules(moduleGraph, module) {
141
+ let state = deferredCycleCache.get(moduleGraph);
142
+ if (state === undefined) {
143
+ state = { sccOf: new Map(), peers: new Map() };
144
+ deferredCycleCache.set(moduleGraph, state);
145
+ }
146
+ const cached = state.peers.get(module);
147
+ if (cached !== undefined) return cached;
148
+ assignStronglyConnectedComponents(moduleGraph, module, state.sccOf);
149
+ const component = state.sccOf.get(module);
150
+ // A trivial component (size 1, no self-cycle peers) means no cycle; a direct
151
+ // self-loop is already covered by the `evaluating` check on `module` itself.
152
+ let result = null;
153
+ if (component !== undefined && component.size > 1) {
154
+ result = new Set(component);
155
+ result.delete(module);
156
+ }
157
+ state.peers.set(module, result);
158
+ return result;
159
+ }
160
+
161
+ /**
162
+ * Maps a defer-cycle closure to the runtime module ids whose `evaluating` flag
163
+ * the deferred namespace must check. `resolveId` maps a closure module to the
164
+ * runtime id that carries its evaluation state (its own id, or the id of the
165
+ * concatenated module that absorbed it); unresolved (`null`) members are
166
+ * dropped. Returns `null` when there is nothing to check.
167
+ * @param {Set<Module> | null} closure closure modules, or null when not cyclic
168
+ * @param {(module: Module) => ModuleId | null} resolveId maps a module to its runtime id
169
+ * @returns {ModuleId[] | null} deduplicated runtime ids, or null
170
+ */
171
+ function getDeferredCycleModuleIds(closure, resolveId) {
172
+ if (closure === null) return null;
173
+ /** @type {Set<ModuleId>} */
174
+ const ids = new Set();
175
+ for (const module of closure) {
176
+ const id = resolveId(module);
177
+ if (id !== null) ids.add(id);
178
+ }
179
+ return ids.size > 0 ? [...ids] : null;
180
+ }
181
+
15
182
  /**
16
183
  * @param {ExportsType} exportsType exports type
17
184
  * @returns {string} mode
@@ -29,6 +196,7 @@ function getMakeDeferredNamespaceModeFromExportsType(exportsType) {
29
196
  * @param {string} moduleId moduleId
30
197
  * @param {ExportsType} exportsType exportsType
31
198
  * @param {(ModuleId | null)[]} asyncDepsIds asyncDepsIds
199
+ * @param {ModuleId[] | null} syncCycleDepsIds transitive static closure ids when the module is part of a defer cycle
32
200
  * @param {RuntimeRequirements} runtimeRequirements runtime requirements
33
201
  * @returns {string} call make optimized deferred namespace object
34
202
  */
@@ -36,17 +204,23 @@ function getOptimizedDeferredModule(
36
204
  moduleId,
37
205
  exportsType,
38
206
  asyncDepsIds,
207
+ syncCycleDepsIds,
39
208
  runtimeRequirements
40
209
  ) {
41
210
  runtimeRequirements.add(RuntimeGlobals.makeOptimizedDeferredNamespaceObject);
42
211
  const mode = getMakeDeferredNamespaceModeFromExportsType(exportsType);
43
- return `${
44
- RuntimeGlobals.makeOptimizedDeferredNamespaceObject
45
- }(${moduleId}, ${mode}${
46
- asyncDepsIds.length > 0
47
- ? `, ${JSON.stringify(asyncDepsIds.filter((x) => x !== null))}`
48
- : ""
49
- })`;
212
+ const asyncDeps = asyncDepsIds.filter((x) => x !== null);
213
+ const hasSync = syncCycleDepsIds !== null && syncCycleDepsIds.length > 0;
214
+ // `syncDeps` is passed positionally after `asyncDeps`, so a `0` placeholder
215
+ // keeps the slot when the module has cycle deps but no async deps.
216
+ const args = [moduleId, mode];
217
+ if (asyncDeps.length > 0 || hasSync) {
218
+ args.push(asyncDeps.length > 0 ? JSON.stringify(asyncDeps) : "0");
219
+ }
220
+ if (hasSync) args.push(JSON.stringify(syncCycleDepsIds));
221
+ return `${RuntimeGlobals.makeOptimizedDeferredNamespaceObject}(${args.join(
222
+ ", "
223
+ )})`;
50
224
  }
51
225
 
52
226
  class MakeOptimizedDeferredNamespaceObjectRuntimeModule extends HelperRuntimeModule {
@@ -72,7 +246,9 @@ class MakeOptimizedDeferredNamespaceObjectRuntimeModule extends HelperRuntimeMod
72
246
  const hasAsync = this.hasAsyncRuntime;
73
247
  return Template.asString([
74
248
  // Note: must be a function (not arrow), because this is used in body!
75
- `${fn} = function(moduleId, mode${hasAsync ? ", asyncDeps" : ""}) {`,
249
+ // `asyncDeps` keeps a fixed positional slot even without async runtime
250
+ // so the trailing `syncDeps` (defer-cycle closure) always lines up.
251
+ `${fn} = function(moduleId, mode, asyncDeps, syncDeps) {`,
76
252
  Template.indent([
77
253
  `${cst} r = this;`,
78
254
  hasAsync ? `${cst} isAsync = asyncDeps && asyncDeps.length;` : "",
@@ -80,6 +256,19 @@ class MakeOptimizedDeferredNamespaceObjectRuntimeModule extends HelperRuntimeMod
80
256
  Template.indent([
81
257
  "get a() {",
82
258
  Template.indent([
259
+ // Forcing evaluation of a module that is currently evaluating
260
+ // (a cycle reached through a deferred import) must throw rather
261
+ // than expose its partial exports. `syncDeps` (present only for
262
+ // cyclic deferred modules) carries the transitive static closure,
263
+ // so an evaluating dependency is caught before any evaluation.
264
+ `${cst} cachedModule = __webpack_module_cache__[moduleId];`,
265
+ 'if (cachedModule !== undefined && (cachedModule.evaluating || cachedModule.evaluatingAsync)) throw new TypeError("Cannot access a deferred module namespace while the module is being evaluated");',
266
+ "if (syncDeps) for (var i = 0; i < syncDeps.length; i++) {",
267
+ Template.indent([
268
+ `${cst} depModule = __webpack_module_cache__[syncDeps[i]];`,
269
+ 'if (depModule !== undefined && (depModule.evaluating || depModule.evaluatingAsync)) throw new TypeError("Cannot access a deferred module namespace while a dependency is being evaluated");'
270
+ ]),
271
+ "}",
83
272
  `${lt} exports = r(moduleId);`,
84
273
  hasAsync
85
274
  ? `if(isAsync) exports = exports[${RuntimeGlobals.asyncModuleExportSymbol}];`
@@ -164,6 +353,11 @@ class MakeDeferredNamespaceObjectRuntimeModule extends HelperRuntimeModule {
164
353
  "}",
165
354
  "",
166
355
  `${lt} init = ${runtimeTemplate.basicFunction("", [
356
+ // A deferred namespace that forces evaluation of a module that is
357
+ // already evaluating (a cycle) must throw rather than expose its
358
+ // partial exports.
359
+ `${cst} evaluatingModule = __webpack_module_cache__[moduleId];`,
360
+ 'if (evaluatingModule !== undefined && (evaluatingModule.evaluating || evaluatingModule.evaluatingAsync)) throw new TypeError("Cannot access a deferred module namespace while the module is being evaluated");',
167
361
  `ns = ${RuntimeGlobals.require}(moduleId);`,
168
362
  hasAsync
169
363
  ? `if (${RuntimeGlobals.asyncModuleExportSymbol} in ns) ns = ns[${RuntimeGlobals.asyncModuleExportSymbol}];`
@@ -348,6 +542,8 @@ module.exports.MakeDeferredNamespaceObjectRuntimeModule =
348
542
  MakeDeferredNamespaceObjectRuntimeModule;
349
543
  module.exports.MakeOptimizedDeferredNamespaceObjectRuntimeModule =
350
544
  MakeOptimizedDeferredNamespaceObjectRuntimeModule;
545
+ module.exports.getDeferredCycleModuleIds = getDeferredCycleModuleIds;
546
+ module.exports.getDeferredCycleModules = getDeferredCycleModules;
351
547
  module.exports.getMakeDeferredNamespaceModeFromExportsType =
352
548
  getMakeDeferredNamespaceModeFromExportsType;
353
549
  module.exports.getOptimizedDeferredModule = getOptimizedDeferredModule;
@@ -25,8 +25,11 @@ class SetAnonymousDefaultNameRuntimeModule extends HelperRuntimeModule {
25
25
  const fn = RuntimeGlobals.setAnonymousDefaultName;
26
26
  return Template.asString([
27
27
  "// set .name for anonymous default exports per ES spec",
28
+ "// skipped when the property is non-configurable (pre-ES2015 engines),",
29
+ "// where Object.defineProperty would throw",
28
30
  `${fn} = ${runtimeTemplate.basicFunction("x", [
29
- '(Object.getOwnPropertyDescriptor(x, "name") || {}).writable || Object.defineProperty(x, "name", { value: "default", configurable: true });'
31
+ 'var descriptor = Object.getOwnPropertyDescriptor(x, "name");',
32
+ 'if (!descriptor || (!descriptor.writable && descriptor.configurable)) Object.defineProperty(x, "name", { value: "default", configurable: true });'
30
33
  ])};`
31
34
  ]);
32
35
  }
@@ -233,6 +233,36 @@ const sanitizeUrlForError = (href) => {
233
233
  }
234
234
  };
235
235
 
236
+ /**
237
+ * Splits lockfile content containing git merge conflict markers (2-way or
238
+ * diff3) into its two sides so each can be parsed as valid JSON on its own.
239
+ * @param {string} content lockfile content with conflict markers
240
+ * @returns {[string, string]} the "ours" and "theirs" variants
241
+ */
242
+ const splitMergeConflicts = (content) => {
243
+ /** @type {string[]} */
244
+ const ours = [];
245
+ /** @type {string[]} */
246
+ const theirs = [];
247
+ // 0 = shared, 1 = ours, 2 = theirs, 3 = common ancestor (diff3, dropped)
248
+ let side = 0;
249
+ for (const line of content.split(/\r?\n/)) {
250
+ if (line.startsWith("<<<<<<<")) {
251
+ side = 1;
252
+ } else if (line.startsWith("|||||||")) {
253
+ side = 3;
254
+ } else if (line.startsWith("=======")) {
255
+ side = 2;
256
+ } else if (line.startsWith(">>>>>>>")) {
257
+ side = 0;
258
+ } else {
259
+ if (side === 0 || side === 1) ours.push(line);
260
+ if (side === 0 || side === 2) theirs.push(line);
261
+ }
262
+ }
263
+ return [ours.join("\n"), theirs.join("\n")];
264
+ };
265
+
236
266
  class Lockfile {
237
267
  constructor() {
238
268
  /** @type {number} */
@@ -247,7 +277,16 @@ class Lockfile {
247
277
  * @returns {Lockfile} lockfile
248
278
  */
249
279
  static parse(content) {
250
- // TODO handle merge conflicts
280
+ // A git merge conflict leaves `<<<<<<<`/`=======`/`>>>>>>>` markers; parse
281
+ // each side and union the entries, since lockfile changes only add keys.
282
+ if (content.includes("<<<<<<<")) {
283
+ const [ours, theirs] = splitMergeConflicts(content);
284
+ const lockfile = Lockfile.parse(ours);
285
+ for (const [key, entry] of Lockfile.parse(theirs).entries) {
286
+ if (!lockfile.entries.has(key)) lockfile.entries.set(key, entry);
287
+ }
288
+ return lockfile;
289
+ }
251
290
  const data = JSON.parse(content);
252
291
  if (data.version !== 1) {
253
292
  throw new Error(`Unsupported lockfile version ${data.version}`);
@@ -5,10 +5,9 @@
5
5
 
6
6
  "use strict";
7
7
 
8
- const { getContext } = require("loader-runner");
9
-
10
8
  const NormalModule = require("../NormalModule");
11
9
  const ModuleNotFoundError = require("../errors/ModuleNotFoundError");
10
+ const { getContext } = require("../loaders/LoaderRunner");
12
11
  const { isAbsolute, join } = require("../util/fs");
13
12
  const { parseResourceWithoutFragment } = require("../util/identifier");
14
13