@depup/webpack 5.110.1-depup.0 → 5.111.1-depup.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 (304) hide show
  1. package/README.md +7 -8
  2. package/changes.json +7 -11
  3. package/lib/APIPlugin.js +26 -11
  4. package/lib/AutomaticPrefetchPlugin.js +1 -1
  5. package/lib/Cache.js +8 -3
  6. package/lib/CacheFacade.js +1 -1
  7. package/lib/ChunkGraph.js +20 -18
  8. package/lib/CircularModulesPlugin.js +157 -55
  9. package/lib/CleanPlugin.js +2 -2
  10. package/lib/CompatibilityPlugin.js +3 -4
  11. package/lib/Compilation.js +337 -338
  12. package/lib/Compiler.js +213 -51
  13. package/lib/ConcatenationScope.js +25 -35
  14. package/lib/ConstPlugin.js +16 -132
  15. package/lib/CopyPlugin.js +1054 -0
  16. package/lib/DefinePlugin.js +24 -8
  17. package/lib/DependencyTemplate.js +2 -1
  18. package/lib/DotenvPlugin.js +64 -40
  19. package/lib/ErrorHelpers.js +113 -0
  20. package/lib/ExportsInfo.js +30 -16
  21. package/lib/ExternalModule.js +47 -22
  22. package/lib/FileSystemInfo.js +17 -14
  23. package/lib/FlagDependencyExportsPlugin.js +53 -34
  24. package/lib/FlagDependencyUsagePlugin.js +17 -15
  25. package/lib/Generator.js +24 -2
  26. package/lib/HotModuleReplacementPlugin.js +55 -7
  27. package/lib/IgnorePlugin.js +1 -1
  28. package/lib/JavascriptMetaInfoPlugin.js +5 -3
  29. package/lib/LoaderOptionsPlugin.js +1 -1
  30. package/lib/MainTemplate.js +5 -1
  31. package/lib/Module.js +19 -10
  32. package/lib/ModuleGraph.js +6 -9
  33. package/lib/MultiCompiler.js +7 -17
  34. package/lib/MultiWatching.js +1 -1
  35. package/lib/NormalModule.js +148 -70
  36. package/lib/NormalModuleFactory.js +1 -1
  37. package/lib/RuntimeGlobals.js +21 -7
  38. package/lib/RuntimeModule.js +28 -12
  39. package/lib/RuntimePlugin.js +33 -3
  40. package/lib/RuntimeTemplate.js +1147 -847
  41. package/lib/SourceMapDevToolPlugin.js +54 -104
  42. package/lib/TemplatedPathPlugin.js +16 -59
  43. package/lib/Watching.js +9 -0
  44. package/lib/WebpackOptionsApply.js +84 -91
  45. package/lib/asset/AssetBytesGenerator.js +7 -1
  46. package/lib/asset/AssetGenerator.js +50 -24
  47. package/lib/asset/AssetModule.js +3 -0
  48. package/lib/asset/AssetSourceGenerator.js +7 -1
  49. package/lib/asset/WebManifestParser.js +7 -5
  50. package/lib/async-modules/AsyncModuleHelpers.js +10 -4
  51. package/lib/buildChunkGraph.js +11 -15
  52. package/lib/cache/AddBuildDependenciesPlugin.js +33 -4
  53. package/lib/cache/IdleFileCachePlugin.js +2 -2
  54. package/lib/cache/MemoryCachePlugin.js +4 -4
  55. package/lib/cache/MemoryWithGcCachePlugin.js +7 -8
  56. package/lib/cache/PackFileCacheStrategy.js +17 -19
  57. package/lib/cache/getLazyHashedEtag.js +3 -5
  58. package/lib/config/browserslistTargetHandler.js +17 -4
  59. package/lib/config/defaults.js +162 -142
  60. package/lib/config/getClaimedAssetTypes.js +10 -11
  61. package/lib/config/normalization.js +100 -20
  62. package/lib/config/target.js +13 -4
  63. package/lib/container/ContainerReferencePlugin.js +6 -0
  64. package/lib/container/RemoteRuntimeModule.js +9 -0
  65. package/lib/container/declaredRemotes.js +39 -0
  66. package/lib/{ContextExclusionPlugin.js → context/ContextExclusionPlugin.js} +1 -1
  67. package/lib/{ContextModule.js → context/ContextModule.js} +54 -115
  68. package/lib/{ContextModuleFactory.js → context/ContextModuleFactory.js} +19 -21
  69. package/lib/{ContextReplacementPlugin.js → context/ContextReplacementPlugin.js} +4 -4
  70. package/lib/css/CssGenerator.js +27 -11
  71. package/lib/css/CssInjectStyleRuntimeModule.js +9 -0
  72. package/lib/css/CssLoadingRuntimeModule.js +92 -15
  73. package/lib/css/CssModule.js +1 -1
  74. package/lib/css/CssModulesPlugin.js +3 -10
  75. package/lib/css/CssParser.js +162 -31
  76. package/lib/css/CssServerStylesRuntimeModule.js +9 -0
  77. package/lib/css/cssMinify.js +43 -32
  78. package/lib/css/data.js +3526 -871
  79. package/lib/css/syntax.js +6455 -1237
  80. package/lib/debug/ProfilingPlugin.js +7 -4
  81. package/lib/dependencies/AMDDefineDependencyParserPlugin.js +6 -3
  82. package/lib/dependencies/AMDRuntimeModules.js +18 -0
  83. package/lib/dependencies/CommonJsExportRequireDependency.js +13 -12
  84. package/lib/dependencies/CommonJsExportsParserPlugin.js +12 -13
  85. package/lib/dependencies/CommonJsImportsParserPlugin.js +5 -5
  86. package/lib/dependencies/CommonJsPlugin.js +19 -3
  87. package/lib/dependencies/CommonJsRequireDependency.js +32 -9
  88. package/lib/dependencies/CommonJsSelfReferenceDependency.js +2 -4
  89. package/lib/dependencies/ContextDependency.js +1 -1
  90. package/lib/dependencies/ContextDependencyHelpers.js +3 -9
  91. package/lib/dependencies/ContextDependencyTemplateAsRequireCall.js +20 -7
  92. package/lib/dependencies/ContextElementDependency.js +1 -1
  93. package/lib/dependencies/CssIcssExportDependency.js +13 -9
  94. package/lib/dependencies/CssIcssImportDependency.js +3 -6
  95. package/lib/dependencies/CssUrlDependency.js +3 -5
  96. package/lib/dependencies/HarmonyCompatibilityDependency.js +67 -22
  97. package/lib/dependencies/HarmonyDetectionParserPlugin.js +3 -4
  98. package/lib/dependencies/HarmonyEvaluatedImportSpecifierDependency.js +10 -4
  99. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +12 -7
  100. package/lib/dependencies/HarmonyExportExpressionDependency.js +47 -33
  101. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +217 -34
  102. package/lib/dependencies/HarmonyExportInitFragment.js +110 -23
  103. package/lib/dependencies/HarmonyExportSpecifierDependency.js +25 -58
  104. package/lib/dependencies/HarmonyImportBareSideEffectDependency.js +59 -0
  105. package/lib/dependencies/HarmonyImportDependency.js +99 -41
  106. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +198 -25
  107. package/lib/dependencies/HarmonyImportSideEffectDependency.js +117 -4
  108. package/lib/dependencies/HarmonyImportSpecifierDependency.js +40 -3
  109. package/lib/dependencies/HarmonyModulesPlugin.js +20 -0
  110. package/lib/dependencies/HtmlEntryDependency.js +136 -104
  111. package/lib/dependencies/HtmlInlineScriptDependency.js +3 -4
  112. package/lib/dependencies/HtmlInlineStyleDependency.js +3 -4
  113. package/lib/dependencies/ImportContextDependency.js +43 -3
  114. package/lib/dependencies/ImportDependency.js +8 -29
  115. package/lib/dependencies/ImportMetaContextDependencyParserPlugin.js +1 -1
  116. package/lib/dependencies/ImportMetaGlobHelpers.js +1 -1
  117. package/lib/dependencies/ImportMetaMainDependency.js +104 -0
  118. package/lib/dependencies/ImportMetaPlugin.js +67 -25
  119. package/lib/dependencies/ImportParserPlugin.js +25 -15
  120. package/lib/dependencies/LoaderPlugin.js +26 -1
  121. package/lib/dependencies/RequireContextDependencyParserPlugin.js +1 -1
  122. package/lib/dependencies/RequireHeaderDependency.js +20 -21
  123. package/lib/dependencies/SystemRuntimeModule.js +9 -0
  124. package/lib/dependencies/URLContextDependency.js +1 -1
  125. package/lib/dependencies/URLDependency.js +6 -5
  126. package/lib/dependencies/WorkerAndWorkletPlugin.js +16 -21
  127. package/lib/dependencies/WorkerDependency.js +12 -18
  128. package/lib/dependencies/WorkletDependency.js +12 -20
  129. package/lib/dependencies/importOptionsCheck.js +47 -0
  130. package/lib/dll/DelegatedModule.js +18 -1
  131. package/lib/dll/DllReferencePlugin.js +11 -8
  132. package/lib/dll/LibManifestPlugin.js +1 -1
  133. package/lib/errors/AnalyzableBailoutsWarning.js +41 -0
  134. package/lib/errors/DotenvFileError.js +29 -0
  135. package/lib/errors/DuplicateModulesWarning.js +12 -7
  136. package/lib/errors/EmptyCopyPatternWarning.js +26 -0
  137. package/lib/errors/ExternalStarReexportError.js +44 -0
  138. package/lib/errors/HookWebpackError.js +3 -2
  139. package/lib/errors/ImportedBindingAssignmentError.js +30 -0
  140. package/lib/errors/MissingSourceMapsWarning.js +36 -0
  141. package/lib/errors/ModuleParseError.js +2 -1
  142. package/lib/errors/UnusedAssetsWarning.js +36 -0
  143. package/lib/errors/UnusedFederationWarning.js +35 -0
  144. package/lib/errors/UnusedModulesWarning.js +38 -0
  145. package/lib/esm/ExportWebpackRequireRuntimeModule.js +9 -0
  146. package/lib/esm/ModuleChunkFormatPlugin.js +28 -3
  147. package/lib/esm/ModuleChunkLoadingPlugin.js +21 -5
  148. package/lib/esm/ModuleChunkLoadingRuntimeModule.js +91 -53
  149. package/lib/hmr/HotModuleReplacement.runtime.js +8 -2
  150. package/lib/hmr/HotModuleReplacementRuntimeModule.js +9 -0
  151. package/lib/hmr/LazyCompilationPlugin.js +3 -5
  152. package/lib/html/HtmlGenerator.js +72 -87
  153. package/lib/html/HtmlModulesPlugin.js +479 -215
  154. package/lib/html/HtmlParser.js +110 -147
  155. package/lib/html/builtinEmbeddedRenderer.js +107 -0
  156. package/lib/html/data.js +142 -7
  157. package/lib/html/htmlMinify.js +92 -122
  158. package/lib/html/syntax.js +2031 -1556
  159. package/lib/ids/HashedModuleIdsPlugin.js +2 -1
  160. package/lib/index.js +49 -3
  161. package/lib/javascript/ChunkFormatHelpers.js +4 -3
  162. package/lib/javascript/JavascriptGenerator.js +8 -1
  163. package/lib/javascript/JavascriptModule.js +1 -0
  164. package/lib/javascript/JavascriptModulesPlugin.js +76 -80
  165. package/lib/javascript/JavascriptParser.js +1970 -900
  166. package/lib/javascript/StartupHelpers.js +27 -3
  167. package/lib/javascript/data.js +172 -0
  168. package/lib/javascript/grammar.js +5546 -0
  169. package/lib/javascript/parser.js +1500 -0
  170. package/lib/javascript/regexp.js +1762 -0
  171. package/lib/javascript/regexpData.js +51 -0
  172. package/lib/javascript/syntax.js +9061 -5262
  173. package/lib/json/JsonGenerator.js +7 -1
  174. package/lib/library/ModuleLibraryPlugin.js +171 -132
  175. package/lib/loaders/LoaderRunner.js +170 -14
  176. package/lib/node/NodeWatchFileSystem.js +3 -9
  177. package/lib/node/ReadFileChunkLoadingRuntimeModule.js +22 -0
  178. package/lib/node/ReadFileCompileAsyncWasmPlugin.js +8 -15
  179. package/lib/node/RequireChunkLoadingRuntimeModule.js +22 -0
  180. package/lib/optimize/AggressiveMergingPlugin.js +3 -5
  181. package/lib/optimize/ConcatenatedModule.js +222 -125
  182. package/lib/optimize/ConstExportsPlugin.js +50 -34
  183. package/lib/optimize/FlagIncludedChunksPlugin.js +3 -11
  184. package/lib/optimize/InlineExports.js +20 -2
  185. package/lib/optimize/InnerGraphPlugin.js +7 -13
  186. package/lib/optimize/LimitChunkCountPlugin.js +5 -8
  187. package/lib/optimize/MangleExportsPlugin.js +13 -4
  188. package/lib/optimize/ModuleConcatenationPlugin.js +27 -5
  189. package/lib/optimize/RealContentHashPlugin.js +179 -44
  190. package/lib/optimize/SideEffectsFlagPlugin.js +24 -28
  191. package/lib/optimize/SplitChunksPlugin.js +2 -4
  192. package/lib/performance/AnalyzableBailoutsPlugin.js +115 -0
  193. package/lib/performance/BroadContextsPlugin.js +1 -1
  194. package/lib/performance/CacheEffectivenessPlugin.js +7 -7
  195. package/lib/performance/DuplicateModulesPlugin.js +57 -13
  196. package/lib/performance/EvalUsagePlugin.js +5 -2
  197. package/lib/performance/MissingSourceMapsPlugin.js +115 -0
  198. package/lib/performance/PureAnnotationsPlugin.js +6 -3
  199. package/lib/performance/SizeLimitsPlugin.js +2 -4
  200. package/lib/performance/TopLevelThisPlugin.js +5 -4
  201. package/lib/performance/UnusedAssetsPlugin.js +109 -0
  202. package/lib/performance/UnusedFederationPlugin.js +147 -0
  203. package/lib/performance/UnusedModulesPlugin.js +141 -0
  204. package/lib/performance/UnusedReexportsPlugin.js +1 -55
  205. package/lib/performance/isOnlyReexported.js +65 -0
  206. package/lib/prefetch/ChunkPrefetchFunctionRuntimeModule.js +25 -5
  207. package/lib/prefetch/ChunkPrefetchPreloadPlugin.js +8 -8
  208. package/lib/prefetch/ChunkPrefetchStartupRuntimeModule.js +9 -0
  209. package/lib/prefetch/ChunkPrefetchTriggerRuntimeModule.js +9 -0
  210. package/lib/prefetch/ChunkPreloadTriggerRuntimeModule.js +9 -0
  211. package/lib/prefetch/ResourceHintPlugin.js +29 -35
  212. package/lib/prefetch/ResourceHintRuntimeModule.js +9 -0
  213. package/lib/prefetch/StartupAssetHintRuntimeModule.js +16 -10
  214. package/lib/rules/RuleSetCompiler.js +211 -4
  215. package/lib/runtime/AsyncModuleRuntimeModule.js +103 -67
  216. package/lib/runtime/AutoPublicPathRuntimeModule.js +9 -0
  217. package/lib/runtime/BaseUriRuntimeModule.js +9 -0
  218. package/lib/runtime/ChunkNameRuntimeModule.js +9 -0
  219. package/lib/runtime/EnsureChunkRuntimeModule.js +35 -16
  220. package/lib/runtime/GetChunkFilenameRuntimeModule.js +12 -4
  221. package/lib/runtime/GetFullHashRuntimeModule.js +9 -0
  222. package/lib/runtime/GetMainFilenameRuntimeModule.js +9 -0
  223. package/lib/runtime/GetWorkletBootstrapRuntimeModule.js +9 -0
  224. package/lib/runtime/GlobalRuntimeModule.js +11 -4
  225. package/lib/runtime/HasOwnPropertyRuntimeModule.js +9 -0
  226. package/lib/runtime/HelperRuntimeModule.js +10 -0
  227. package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +313 -222
  228. package/lib/runtime/NonceRuntimeModule.js +9 -0
  229. package/lib/runtime/OnChunksLoadedRuntimeModule.js +67 -20
  230. package/lib/runtime/PublicPathRuntimeModule.js +9 -0
  231. package/lib/runtime/RuntimeIdRuntimeModule.js +9 -0
  232. package/lib/runtime/SpecNamespaceObjectRuntimeModule.js +90 -0
  233. package/lib/runtime/StartupChunkDependenciesRuntimeModule.js +9 -0
  234. package/lib/runtime/StartupEntrypointRuntimeModule.js +9 -0
  235. package/lib/runtime/SystemContextRuntimeModule.js +9 -0
  236. package/lib/runtime/ToBinaryRuntimeModule.js +9 -0
  237. package/lib/schemes/DataUriPlugin.js +3 -6
  238. package/lib/schemes/HttpUriPlugin.js +22 -5
  239. package/lib/schemes/VirtualUrlPlugin.js +1 -1
  240. package/lib/serialization/BinaryMiddleware.js +9 -9
  241. package/lib/serialization/FileMiddleware.js +31 -18
  242. package/lib/serialization/ObjectMiddleware.js +168 -139
  243. package/lib/sharing/ConsumeSharedPlugin.js +12 -0
  244. package/lib/sharing/ConsumeSharedRuntimeModule.js +11 -0
  245. package/lib/sharing/ShareRuntimeModule.js +9 -0
  246. package/lib/sharing/declaredShared.js +47 -0
  247. package/lib/stats/DefaultStatsFactoryPlugin.js +6 -5
  248. package/lib/stats/DefaultStatsPrinterPlugin.js +3 -0
  249. package/lib/typescript/TypeScriptPlugin.js +10 -13
  250. package/lib/url/URLParserPlugin.js +6 -8
  251. package/lib/util/ArrayQueue.js +3 -3
  252. package/lib/util/LocConverter.js +4 -7
  253. package/lib/util/SourceProcessor.js +115 -99
  254. package/lib/util/URLAbsoluteSpecifier.js +3 -1
  255. package/lib/util/async.js +292 -0
  256. package/lib/util/buildDiagnostics.js +69 -0
  257. package/lib/util/chainedImports.js +3 -4
  258. package/lib/util/concatenate.js +4 -4
  259. package/lib/util/conventions.js +5 -1
  260. package/lib/util/createHooksRegistry.js +1 -2
  261. package/lib/util/createMappings.js +25 -3
  262. package/lib/util/dataURL.js +2 -3
  263. package/lib/util/deterministicGrouping.js +8 -13
  264. package/lib/util/findGraphRoots.js +6 -13
  265. package/lib/util/fs.js +27 -1
  266. package/lib/util/globUtils.js +1 -1
  267. package/lib/util/handlerKeys.js +40 -0
  268. package/lib/util/hash/wasm-hash.js +3 -4
  269. package/lib/util/identifier.js +20 -0
  270. package/lib/util/internalSerializables.js +7 -1
  271. package/lib/util/registerExternalSerializer.js +6 -45
  272. package/lib/util/removeBOM.js +82 -1
  273. package/lib/util/semver.js +5 -3
  274. package/lib/wasm-async/AsyncWasmCompileRuntimeModule.js +14 -3
  275. package/lib/wasm-async/AsyncWasmLoadingRuntimeModule.js +14 -3
  276. package/lib/wasm-async/AsyncWebAssemblyGenerator.js +6 -1
  277. package/lib/wasm-async/AsyncWebAssemblyJavascriptGenerator.js +5 -1
  278. package/lib/wasm-async/UniversalCompileAsyncWasmPlugin.js +7 -12
  279. package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +12 -4
  280. package/lib/wasm-sync/WebAssemblyGenerator.js +6 -1
  281. package/lib/wasm-sync/WebAssemblyJavascriptGenerator.js +5 -1
  282. package/lib/wasm-sync/WebAssemblyUtils.js +2 -4
  283. package/lib/web/FetchCompileAsyncWasmPlugin.js +10 -6
  284. package/lib/web/FetchCompileWasmPlugin.js +4 -2
  285. package/lib/web/JsonpChunkLoadingRuntimeModule.js +36 -0
  286. package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +19 -0
  287. package/package.json +55 -46
  288. package/schemas/WebpackOptions.check.js +1 -1
  289. package/schemas/WebpackOptions.json +388 -76
  290. package/schemas/plugins/LoaderOptionsPlugin.check.js +1 -1
  291. package/schemas/plugins/ManifestPlugin.check.js +1 -1
  292. package/schemas/plugins/SourceMapDevToolPlugin.check.js +1 -1
  293. package/schemas/plugins/asset/AssetGeneratorOptions.check.js +1 -1
  294. package/schemas/plugins/asset/AssetResourceGeneratorOptions.check.js +1 -1
  295. package/schemas/plugins/container/ContainerPlugin.check.js +1 -1
  296. package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
  297. package/schemas/plugins/debug/ProfilingPlugin.check.js +1 -1
  298. package/schemas/plugins/dll/DllReferencePlugin.check.js +1 -1
  299. package/schemas/plugins/ids/HashedModuleIdsPlugin.check.js +1 -1
  300. package/schemas/plugins/schemes/HttpUriPlugin.check.js +1 -1
  301. package/types.d.ts +1795 -608
  302. package/lib/dependencies/ExportBindingInitFragment.js +0 -191
  303. package/lib/errors/EntrypointOverlapWarning.js +0 -45
  304. package/lib/performance/EntrypointOverlapPlugin.js +0 -122
@@ -20,6 +20,7 @@ const {
20
20
  evaluateToString,
21
21
  toConstantDependency
22
22
  } = require("./javascript/JavascriptParserHelpers");
23
+ const { getBuildDiagnostics } = require("./util/buildDiagnostics");
23
24
  const createHash = require("./util/createHash");
24
25
  const createHooksRegistry = require("./util/createHooksRegistry");
25
26
 
@@ -92,8 +93,10 @@ class RuntimeValue {
92
93
  const buildInfo = /** @type {BuildInfo} */ (parser.state.module.buildInfo);
93
94
  if (this.options === true) {
94
95
  buildInfo.cacheable = false;
96
+ const diagnostics = getBuildDiagnostics(buildInfo);
95
97
  const reasons =
96
- buildInfo.notCacheableReasons || (buildInfo.notCacheableReasons = []);
98
+ diagnostics.notCacheableReasons ||
99
+ (diagnostics.notCacheableReasons = []);
97
100
  const reason = `DefinePlugin runtime value ${key}`;
98
101
  if (!reasons.includes(reason)) reasons.push(reason);
99
102
  } else {
@@ -375,7 +378,7 @@ const PLUGIN_NAME = "DefinePlugin";
375
378
  const VALUE_DEP_PREFIX = `webpack/${PLUGIN_NAME} `;
376
379
  const VALUE_DEP_MAIN = `webpack/${PLUGIN_NAME}_hash`;
377
380
 
378
- // Keys webpack injects itself are not the user's to remove, so `performance.unusedDefines`
381
+ // Keys webpack injects itself are not the user's to remove, so `performance.unusedConfig`
379
382
  // never sees them.
380
383
  /** @type {WeakSet<DefinePlugin>} */
381
384
  const INTERNAL_PLUGINS = new WeakSet();
@@ -721,11 +724,11 @@ class DefinePlugin {
721
724
  (compilation, { normalModuleFactory }) => {
722
725
  const definitions = this.definitions;
723
726
  const { performance } = compilation.options;
724
- // Only `performance.unusedDefines` reads these, so a build without it
727
+ // Only `performance.unusedConfig` reads these, so a build without it
725
728
  // collects nothing.
726
729
  const collectDeclared =
727
730
  performance !== false &&
728
- performance.unusedDefines === true &&
731
+ performance.unusedConfig === true &&
729
732
  !INTERNAL_PLUGINS.has(this);
730
733
  /** @type {Set<string> | undefined} */
731
734
  let declaredKeys;
@@ -1218,13 +1221,26 @@ class DefinePlugin {
1218
1221
  }
1219
1222
  return -1;
1220
1223
  };
1224
+ // Cut the chain at the undefined member, so a read after it still
1225
+ // throws; an optional link there short-circuits the whole chain.
1221
1226
  parser.hooks.expressionMemberChain
1222
1227
  .for(chainRoot)
1223
- .tap(PLUGIN_NAME, (expr, members) => {
1228
+ .tap(PLUGIN_NAME, (expr, members, membersOptionals) => {
1224
1229
  const deps = [key];
1225
- if (findUndefinedMemberAccess(members, deps) === -1) return;
1230
+ const undefinedIndex = findUndefinedMemberAccess(members, deps);
1231
+ if (undefinedIndex === -1) return;
1226
1232
  for (const dep of deps) addValueDependency(dep);
1227
- return toConstantDependency(parser, "undefined")(expr);
1233
+ return toConstantDependency(
1234
+ parser,
1235
+ "undefined"
1236
+ )(
1237
+ membersOptionals[undefinedIndex + 1]
1238
+ ? expr
1239
+ : dropTrailingMembers(
1240
+ expr,
1241
+ members.length - 1 - undefinedIndex
1242
+ )
1243
+ );
1228
1244
  });
1229
1245
  // Cut the chain at the undefined member, so what follows still
1230
1246
  // throws; an optional link there takes the call, arguments unevaluated.
@@ -1331,7 +1347,7 @@ class DefinePlugin {
1331
1347
  DefinePlugin.getCompilationHooks = createHooksRegistry(createCompilationHooks);
1332
1348
 
1333
1349
  /**
1334
- * Marks an instance as webpack's own, so `performance.unusedDefines` never
1350
+ * Marks an instance as webpack's own, so `performance.unusedConfig` never
1335
1351
  * reports the keys it declares against the user.
1336
1352
  * @param {DefinePlugin} plugin the instance webpack constructed itself
1337
1353
  * @returns {DefinePlugin} the same instance
@@ -12,7 +12,7 @@
12
12
  /** @import Dependency from "./Dependency" */
13
13
  /** @import DependencyTemplates from "./DependencyTemplates" */
14
14
  /** @import { GenerateContext } from "./Generator" */
15
- /** @import Module, { RuntimeRequirements } from "./Module" */
15
+ /** @import Module, { CodeGenerationResultData, RuntimeRequirements } from "./Module" */
16
16
  /** @import ModuleGraph from "./ModuleGraph" */
17
17
  /** @import RuntimeTemplate from "./RuntimeTemplate" */
18
18
  /** @import { RuntimeSpec } from "./util/runtime" */
@@ -37,6 +37,7 @@
37
37
  * @property {ConcatenationScope=} concatenationScope when in a concatenated module, information about other concatenated modules
38
38
  * @property {CodeGenerationResults} codeGenerationResults the code generation results
39
39
  * @property {InitFragment<GenerateContext>[]} chunkInitFragments chunkInitFragments
40
+ * @property {(() => CodeGenerationResultData)=} getData get access to the code generation data
40
41
  */
41
42
 
42
43
  /**
@@ -3,27 +3,6 @@
3
3
  Author Natsu @xiaoxiaojx
4
4
  */
5
5
 
6
- "use strict";
7
-
8
- const FileSystemInfo = require("./FileSystemInfo");
9
- const { join } = require("./util/fs");
10
-
11
- /** @import { DotenvPluginOptions } from "../declarations/WebpackOptions" */
12
- /** @import Compiler from "./Compiler" */
13
- /** @import { ItemCacheFacade } from "./CacheFacade" */
14
- /** @import { InputFileSystem } from "./util/fs" */
15
- /** @import { Snapshot } from "./FileSystemInfo" */
16
-
17
- /** @typedef {Exclude<DotenvPluginOptions["prefix"], string | undefined>} Prefix */
18
- /** @typedef {Record<string, string>} Env */
19
-
20
- const DEFAULT_TEMPLATE = [
21
- ".env",
22
- ".env.local",
23
- ".env.[mode]",
24
- ".env.[mode].local"
25
- ];
26
-
27
6
  // cspell:ignore Motte, motdotla
28
7
 
29
8
  /*
@@ -61,6 +40,28 @@ const DEFAULT_TEMPLATE = [
61
40
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62
41
  */
63
42
 
43
+ "use strict";
44
+
45
+ const FileSystemInfo = require("./FileSystemInfo");
46
+ const DotenvFileError = require("./errors/DotenvFileError");
47
+ const { join } = require("./util/fs");
48
+
49
+ /** @import { DotenvPluginOptions } from "../declarations/WebpackOptions" */
50
+ /** @import Compiler from "./Compiler" */
51
+ /** @import { ItemCacheFacade } from "./CacheFacade" */
52
+ /** @import { InputFileSystem } from "./util/fs" */
53
+ /** @import { Snapshot } from "./FileSystemInfo" */
54
+
55
+ /** @typedef {Exclude<DotenvPluginOptions["prefix"], string | undefined>} Prefix */
56
+ /** @typedef {Record<string, string>} Env */
57
+
58
+ const DEFAULT_TEMPLATE = [
59
+ ".env",
60
+ ".env.local",
61
+ ".env.[mode]",
62
+ ".env.[mode].local"
63
+ ];
64
+
64
65
  // Regex for parsing .env files
65
66
  // ported from https://github.com/motdotla/dotenv/blob/v17.4.2/lib/main.js#L38
66
67
  const LINE =
@@ -155,8 +156,8 @@ function expandValue(value, processEnv, runningParsed) {
155
156
  const opMatch = expression.match(opRegex);
156
157
  const splitter = opMatch ? opMatch[0] : null;
157
158
 
158
- const r = expression.split(/** @type {string} */ (splitter));
159
- // const r = splitter ? expression.split(splitter) : [expression];
159
+ // `split(null)` splits on the string "null", cutting up names containing it
160
+ const r = splitter ? expression.split(splitter) : [expression];
160
161
 
161
162
  /** @type {string} */
162
163
  let defaultValue;
@@ -222,12 +223,8 @@ function expand(options) {
222
223
  runningParsed[key] = resolvedValue;
223
224
  }
224
225
 
225
- // Part of `dotenv-expand` code, but we don't need it because of we don't modify `process.env`
226
- // for (const processKey in options.parsed) {
227
- // if (processEnv) {
228
- // processEnv[processKey] = options.parsed[processKey];
229
- // }
230
- // }
226
+ // `dotenv-expand` writes the parsed values back into `process.env` here.
227
+ // Omitted: webpack never mutates the ambient environment.
231
228
 
232
229
  return options;
233
230
  }
@@ -235,16 +232,21 @@ function expand(options) {
235
232
  /**
236
233
  * Format environment variables as DefinePlugin definitions
237
234
  * @param {Env} env environment variables
238
- * @returns {Record<string, string>} formatted definitions
235
+ * @returns {Record<string, string | Env>} formatted definitions
239
236
  */
240
237
  const envToDefinitions = (env) => {
241
- const definitions = /** @type {Record<string, string>} */ ({});
238
+ const definitions = /** @type {Record<string, string | Env>} */ ({});
239
+ // one nested definition rather than a `import.meta.env.<key>` per key: a
240
+ // dotted key would otherwise read back as a nested object, not as the key
241
+ const importMetaEnv = /** @type {Env} */ (Object.create(null));
242
242
 
243
243
  for (const [key, value] of Object.entries(env)) {
244
244
  const defValue = JSON.stringify(value);
245
+ // `process.env` stays flat — it must not shadow the real one at runtime
245
246
  definitions[`process.env.${key}`] = defValue;
246
- definitions[`import.meta.env.${key}`] = defValue;
247
+ importMetaEnv[key] = defValue;
247
248
  }
249
+ definitions["import.meta.env"] = importMetaEnv;
248
250
 
249
251
  return definitions;
250
252
  };
@@ -296,6 +298,8 @@ class DotenvPlugin {
296
298
 
297
299
  /** @type {undefined | InstanceType<Snapshot>} */
298
300
  let snapshot;
301
+ /** @type {undefined | DotenvFileError} */
302
+ let loadError;
299
303
 
300
304
  const cache = compiler.getCache(PLUGIN_NAME);
301
305
  const identifier = JSON.stringify(
@@ -304,16 +308,31 @@ class DotenvPlugin {
304
308
  const itemCache = cache.getItemCache(identifier, null);
305
309
 
306
310
  compiler.hooks.beforeCompile.tapPromise(PLUGIN_NAME, async () => {
307
- const { parsed, snapshot: newSnapshot } = dir
308
- ? await this._loadEnv(compiler, itemCache, dir)
309
- : { parsed: {} };
310
- const env = this._getEnv(prefixes, parsed);
311
-
312
- definePlugin.definitions = envToDefinitions(env || {});
313
- snapshot = newSnapshot;
311
+ loadError = undefined;
312
+ try {
313
+ const { parsed, snapshot: newSnapshot } = dir
314
+ ? await this._loadEnv(compiler, itemCache, dir)
315
+ : { parsed: {} };
316
+ const env = this._getEnv(prefixes, parsed);
317
+
318
+ definePlugin.definitions = envToDefinitions(env || {});
319
+ snapshot = newSnapshot;
320
+ } catch (err) {
321
+ // reported on the compilation so watch mode recovers when it is fixed
322
+ if (!(err instanceof DotenvFileError)) throw err;
323
+ loadError = err;
324
+ definePlugin.definitions = envToDefinitions({});
325
+ snapshot = undefined;
326
+ }
314
327
  });
315
328
 
316
329
  compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
330
+ if (loadError) {
331
+ compilation.errors.push(loadError);
332
+ compilation.fileDependencies.add(
333
+ /** @type {string} */ (loadError.file)
334
+ );
335
+ }
317
336
  if (snapshot) {
318
337
  compilation.fileDependencies.addAll(snapshot.getFileIterable());
319
338
  compilation.missingDependencies.addAll(snapshot.getMissingIterable());
@@ -369,7 +388,12 @@ class DotenvPlugin {
369
388
  fileDependencies.push(filePath);
370
389
  return content;
371
390
  },
372
- () => {
391
+ (err) => {
392
+ const code = /** @type {NodeJS.ErrnoException} */ (err).code;
393
+ // only an absent file is normal; anything else is a real fault
394
+ if (code !== "ENOENT" && code !== "ENOTDIR") {
395
+ throw new DotenvFileError(filePath, err);
396
+ }
373
397
  // File doesn't exist, add to missingDependencies (this is normal)
374
398
  missingDependencies.push(filePath);
375
399
  return "";
@@ -5,10 +5,39 @@
5
5
 
6
6
  "use strict";
7
7
 
8
+ const path = require("path");
9
+ const { fileUrlToPath } = require("./util/identifier");
10
+ const memoize = require("./util/memoize");
11
+
12
+ /** @import RequestShortener from "./RequestShortener" */
13
+
14
+ const getNonErrorEmittedError = memoize(() =>
15
+ require("./errors/NonErrorEmittedError")
16
+ );
17
+
8
18
  const loaderFlag = "LOADER_EXECUTION";
9
19
 
10
20
  const webpackOptionsFlag = "WEBPACK_OPTIONS";
11
21
 
22
+ // Every frame of a stack is indented, so a line opening with `at ` after
23
+ // whitespace is a frame rather than a part of the message itself.
24
+ const STACK_FRAME_REGEXP = /^\s+at\s/;
25
+
26
+ // `at name (file:line:column)`, and the `at file:line:column` a frame with no
27
+ // name is written as.
28
+ const STACK_FRAME_FILE_REGEXP = /^(\s+at\s(?:.*\()?)(.+?):(\d+):(\d+)(\)?)$/;
29
+
30
+ // A generated function nests its parentheses and carries a position of its
31
+ // own, so each `file:line:column` in it is read on its own.
32
+ const GENERATED_FRAME_REGEXP = /\beval at /;
33
+ const POSITION_REGEXP = /([^\s()]+):\d+:\d+/g;
34
+
35
+ const WEBPACK_SOURCE_PATH = path.join(__dirname, path.sep);
36
+
37
+ // The engine's own frames name no file of the project: `node:internal/…` under
38
+ // node and deno, the bare `native` under bun.
39
+ const ENGINE_FILE_REGEXP = /^(?:node:|native$)/;
40
+
12
41
  /**
13
42
  * Returns stack trace without the specified flag included.
14
43
  * @param {string} stack stack trace
@@ -74,6 +103,88 @@ const cutOffMessage = (stack, message) => {
74
103
  return firstLine === message ? stack.slice(nextLine + 1) : stack;
75
104
  };
76
105
 
106
+ /**
107
+ * Returns the file a stack frame names, or undefined when the line names none.
108
+ * @param {string} line line of a stack
109
+ * @returns {string | undefined} the file the frame names
110
+ */
111
+ const frameFile = (line) => {
112
+ const match = STACK_FRAME_FILE_REGEXP.exec(line);
113
+ return match === null ? undefined : fileUrlToPath(match[2]);
114
+ };
115
+
116
+ /**
117
+ * Returns the stack without the frames this file's own wrapping put on it.
118
+ * @param {string | undefined} stack stack trace
119
+ * @returns {string | undefined} stack trace starting at the caller
120
+ */
121
+ const cutOffWrappingFrames = (stack) => {
122
+ if (typeof stack !== "string") return stack;
123
+ const lines = stack.split("\n");
124
+ const index = lines.findIndex((line) => STACK_FRAME_REGEXP.test(line));
125
+ if (index === -1) return stack;
126
+ while (index < lines.length && frameFile(lines[index]) === __filename) {
127
+ lines.splice(index, 1);
128
+ }
129
+ return lines.join("\n");
130
+ };
131
+
132
+ /**
133
+ * Returns the value as an error, naming whatever a tap, a loader or a plugin
134
+ * failed with when that is not one. Everything reading a failure expects one.
135
+ * @param {EXPECTED_ANY} value value something failed with
136
+ * @returns {Error} the value, or an error naming it
137
+ */
138
+ const toError = (value) => {
139
+ if (value instanceof Error) return value;
140
+ const error = new (getNonErrorEmittedError())(value);
141
+ // The wrapping is not the site: the stack starts where the value was caught.
142
+ // Cut rather than `captureStackTrace`, which elides every frame under bun.
143
+ error.stack = cutOffWrappingFrames(error.stack);
144
+ return error;
145
+ };
146
+
147
+ /**
148
+ * Returns whether a rebuild of the same project names the same position in the
149
+ * file. Webpack's own sources move with a release, and the engine's with it.
150
+ * @param {string} file file a stack frame names
151
+ * @returns {boolean} whether the position is worth keeping
152
+ */
153
+ const isReproduciblePosition = (file) =>
154
+ !file.startsWith(WEBPACK_SOURCE_PATH) && !ENGINE_FILE_REGEXP.test(file);
155
+
156
+ /**
157
+ * Returns the message with every stack frame naming its file relative to the
158
+ * context, and a position only where {@link isReproduciblePosition} allows one.
159
+ * @param {string} message error message
160
+ * @param {RequestShortener} requestShortener request shortener
161
+ * @returns {string} message whose frames a second build writes the same way
162
+ */
163
+ const contextifyStackFrames = (message, requestShortener) =>
164
+ message
165
+ .split("\n")
166
+ .map((line) => {
167
+ if (!STACK_FRAME_REGEXP.test(line)) return line;
168
+ if (GENERATED_FRAME_REGEXP.test(line)) {
169
+ return line.replace(
170
+ POSITION_REGEXP,
171
+ (position, file) =>
172
+ /** @type {string} */
173
+ (requestShortener.shorten(fileUrlToPath(file)))
174
+ );
175
+ }
176
+ const match = STACK_FRAME_FILE_REGEXP.exec(line);
177
+ if (match === null) return line;
178
+ const [, frame, url, lineNumber, column, end] = match;
179
+ // An engine may name the file as a URL rather than as a path.
180
+ const file = fileUrlToPath(url);
181
+ const position = isReproduciblePosition(file)
182
+ ? `:${lineNumber}:${column}`
183
+ : "";
184
+ return `${frame}${requestShortener.shorten(file)}${position}${end}`;
185
+ })
186
+ .join("\n");
187
+
77
188
  /**
78
189
  * Returns stack trace without the loader execution flag and message included.
79
190
  * @param {string} stack stack trace
@@ -100,8 +211,10 @@ const cleanUpWebpackOptions = (stack, message) => {
100
211
 
101
212
  module.exports.cleanUp = cleanUp;
102
213
  module.exports.cleanUpWebpackOptions = cleanUpWebpackOptions;
214
+ module.exports.contextifyStackFrames = contextifyStackFrames;
103
215
  module.exports.cutOffByFlag = cutOffByFlag;
104
216
  module.exports.cutOffLoaderExecution = cutOffLoaderExecution;
105
217
  module.exports.cutOffMessage = cutOffMessage;
106
218
  module.exports.cutOffMultilineMessage = cutOffMultilineMessage;
107
219
  module.exports.cutOffWebpackOptions = cutOffWebpackOptions;
220
+ module.exports.toError = toError;
@@ -151,20 +151,20 @@ class ExportsInfo {
151
151
  /** @type {Exports} */
152
152
  this._exports = new Map();
153
153
 
154
- // `_otherExportsInfo` is a fallback entry for unlisted exports. Two roles:
155
- // 1. factory template — `getExportInfo` creates `new ExportInfo(name, this)`,
156
- // so created export info extends its properties.
157
- // 2. flags whether the whole exportsInfo can be statically analyzed.
158
- // Its `used` reachable values:
159
- // - NoInfo: no use analysis yet (`optimization#usedExports` off), or used without info
160
- // - Unused: analyzed, no unlisted export needed
161
- // - Unknown: used in unknown way
162
- // - Used/OnlyPropertiesUsed: never reached
163
- // Its `provided` reachable values:
164
- // - undefined: provision not determined yet
165
- // - false: determined, no unlisted export is provided
166
- // - null: only runtime knows (dynamic/unknown exports)
167
- // - true: never reached
154
+ // WHY: a fallback entry for the unlisted exports, in two roles — the factory
155
+ // template `getExportInfo` extends with `new ExportInfo(name, this)`, and the
156
+ // flag for whether this exportsInfo can be statically analyzed at all.
157
+ // Its reachable `used` values:
158
+ // - NoInfo: no use analysis yet (`optimization#usedExports` off), or used
159
+ // without info
160
+ // - Unused: analyzed, no unlisted export needed
161
+ // - Unknown: used in an unknown way
162
+ // - Used/OnlyPropertiesUsed: never reached
163
+ // Its reachable `provided` values:
164
+ // - undefined: provision not determined yet
165
+ // - false: determined, no unlisted export is provided
166
+ // - null: only runtime knows (dynamic or unknown exports)
167
+ // - true: never reached
168
168
  /** @type {ExportInfo} */
169
169
  this._otherExportsInfo = new ExportInfo(null);
170
170
  /** @type {ExportInfo} */
@@ -1671,7 +1671,9 @@ class ExportInfo {
1671
1671
  }
1672
1672
 
1673
1673
  /**
1674
- * Returns the target, undefined when there is no target, false when no target is valid.
1674
+ * Walks the reexport chain and returns the first target whose module passes
1675
+ * `validTargetModuleFilter`. Returns undefined when there is no target, false
1676
+ * when the chain ends without a valid module.
1675
1677
  * @param {ModuleGraph} moduleGraph the module graph
1676
1678
  * @param {ValidTargetModuleFilter} validTargetModuleFilter a valid target module
1677
1679
  * @returns {TargetItemWithoutConnection | null | undefined | false} the target, undefined when there is no target, false when no target is valid
@@ -1736,7 +1738,9 @@ class ExportInfo {
1736
1738
  }
1737
1739
 
1738
1740
  /**
1739
- * Returns the target.
1741
+ * Resolves the reexport chain as far as `resolveTargetFilter` allows and
1742
+ * returns where it ends. Returns undefined when there is no target, the
1743
+ * targets disagree, or the chain is circular.
1740
1744
  * @param {ModuleGraph} moduleGraph the module graph
1741
1745
  * @param {ResolveTargetFilter} resolveTargetFilter filter function to further resolve target
1742
1746
  * @returns {TargetItemWithConnection | undefined} the target
@@ -1747,6 +1751,16 @@ class ExportInfo {
1747
1751
  return result;
1748
1752
  }
1749
1753
 
1754
+ /**
1755
+ * Returns whether resolving the target leads back to this export, which
1756
+ * `getTarget` cannot express as it reports a cycle as "no target".
1757
+ * @param {ModuleGraph} moduleGraph the module graph
1758
+ * @returns {boolean} true, when the reexport chain is circular
1759
+ */
1760
+ hasCircularTarget(moduleGraph) {
1761
+ return this._getTarget(moduleGraph, RETURNS_TRUE, undefined) === CIRCULAR;
1762
+ }
1763
+
1750
1764
  /**
1751
1765
  * Returns the target.
1752
1766
  * @param {ModuleGraph} moduleGraph the module graph
@@ -29,6 +29,7 @@ const { coreModules } = require("./node/nodeBuiltins");
29
29
  const createHash = require("./util/createHash");
30
30
  const createHooksRegistry = require("./util/createHooksRegistry");
31
31
  const extractUrlAndGlobal = require("./util/extractUrlAndGlobal");
32
+ const { toJsStringLiteral } = require("./util/identifier");
32
33
  const makeSerializable = require("./util/makeSerializable");
33
34
  const memoize = require("./util/memoize");
34
35
  const { propertyAccess } = require("./util/property");
@@ -110,6 +111,7 @@ const getEnvironmentNotSupportAsyncWarning = memoize(() =>
110
111
  * @property {InitFragment<ChunkRenderContext>[]=} chunkInitFragments
111
112
  * @property {ReadOnlyRuntimeRequirements=} runtimeRequirements
112
113
  * @property {[string, string][]=} specifiers
114
+ * @property {string=} externalReexport native reexport source and attributes
113
115
  */
114
116
 
115
117
  /** @typedef {true | [string, string][]} Imported */
@@ -346,10 +348,9 @@ const getSourceForImportExternal = (
346
348
  }
347
349
  const phase = dependencyMeta && dependencyMeta.phase;
348
350
  checkPhaseIsSupported(phase, runtimeTemplate);
349
- // `import.defer(…)` and `import.source(…)` are only valid forms of the
350
- // native `import(…)` function, so we only emit the phase suffix when the
351
- // importFunctionName is the default `"import"`. Anything else has no phase
352
- // form at all, and dropping it would silently import eagerly instead.
351
+ // `import.defer(…)` and `import.source(…)` are forms of the native `import(…)`
352
+ // alone, so the phase suffix is emitted only for the default name. Anything
353
+ // else has no phase form, and dropping it would import eagerly instead.
353
354
  if (
354
355
  baseImportName !== "import" &&
355
356
  (ImportPhaseUtils.isDefer(phase) || ImportPhaseUtils.isSource(phase))
@@ -417,6 +418,18 @@ const importAssertionReplacer = (key, value) => {
417
418
  return value;
418
419
  };
419
420
 
421
+ /**
422
+ * Renders the import attributes clause of a static import or reexport.
423
+ * @param {ImportDependencyMeta | undefined} dependencyMeta import metadata
424
+ * @returns {string} static import attributes
425
+ */
426
+ const getImportAttributes = (dependencyMeta) =>
427
+ dependencyMeta && dependencyMeta.attributes
428
+ ? dependencyMeta.attributes._isLegacyAssert
429
+ ? ` assert ${JSON.stringify(dependencyMeta.attributes, importAssertionReplacer)}`
430
+ : ` with ${JSON.stringify(dependencyMeta.attributes)}`
431
+ : "";
432
+
420
433
  /**
421
434
  * Represents ModuleExternalInitFragment.
422
435
  * @extends {InitFragment<GenerateContext>}
@@ -503,33 +516,25 @@ class ModuleExternalInitFragment extends InitFragment {
503
516
  _request: request,
504
517
  _identifier: identifier
505
518
  } = this;
506
- const attributes =
507
- dependencyMeta && dependencyMeta.attributes
508
- ? dependencyMeta.attributes._isLegacyAssert
509
- ? ` assert ${JSON.stringify(
510
- dependencyMeta.attributes,
511
- importAssertionReplacer
512
- )}`
513
- : ` with ${JSON.stringify(dependencyMeta.attributes)}`
514
- : "";
519
+ const attributes = getImportAttributes(dependencyMeta);
515
520
  const phase = dependencyMeta && dependencyMeta.phase;
516
521
  checkPhaseIsSupported(phase, context.runtimeTemplate);
517
522
  let content = "";
518
523
  if (ImportPhaseUtils.isSource(phase) && imported === true) {
519
524
  // There is no `import source * as ns` form: the source phase binds one
520
525
  // identifier, so it stands in for the namespace the other branches build.
521
- content = `import source ${identifier} from ${JSON.stringify(
526
+ content = `import source ${identifier} from ${toJsStringLiteral(
522
527
  request
523
528
  )}${attributes};\n`;
524
529
  } else if (imported === true) {
525
530
  // namespace
526
531
  const phaseKeyword = ImportPhaseUtils.isDefer(phase) ? "defer " : "";
527
- content = `import ${phaseKeyword}* as ${identifier} from ${JSON.stringify(
532
+ content = `import ${phaseKeyword}* as ${identifier} from ${toJsStringLiteral(
528
533
  request
529
534
  )}${attributes};\n`;
530
535
  } else if (imported.length === 0) {
531
536
  // just import, no use
532
- content = `import ${JSON.stringify(request)}${attributes};\n`;
537
+ content = `import ${toJsStringLiteral(request)}${attributes};\n`;
533
538
  } else if (
534
539
  ImportPhaseUtils.isSource(phase) &&
535
540
  imported.length === 1 &&
@@ -537,7 +542,7 @@ class ModuleExternalInitFragment extends InitFragment {
537
542
  ) {
538
543
  // `import source x from "…"` — the source-phase form binds the source
539
544
  // object directly to a single identifier (no namespace, no destructuring).
540
- content = `import source ${imported[0][1]} from ${JSON.stringify(
545
+ content = `import source ${imported[0][1]} from ${toJsStringLiteral(
541
546
  request
542
547
  )}${attributes};\n`;
543
548
  } else {
@@ -548,7 +553,7 @@ class ModuleExternalInitFragment extends InitFragment {
548
553
  }
549
554
  return name;
550
555
  })
551
- .join(", ")} } from ${JSON.stringify(request)}${attributes};\n`;
556
+ .join(", ")} } from ${toJsStringLiteral(request)}${attributes};\n`;
552
557
  }
553
558
  return content;
554
559
  }
@@ -689,10 +694,9 @@ const getSourceForModuleExternal = (
689
694
  imported = true;
690
695
  }
691
696
 
692
- // `import defer …` is only valid as `import defer * as ns from "…"`, so
693
- // keep the namespace form even if usage analysis would otherwise narrow
694
- // the import down to specific names. Defer + concatenation is semantically
695
- // at odds (lazy vs. eager), so we preserve the user-written shape here.
697
+ // `import defer` is valid only as `import defer * as ns from "…"`, so the
698
+ // namespace form is kept even where usage analysis would narrow it: defer and
699
+ // concatenation are at odds, lazy against eager.
696
700
  if (ImportPhaseUtils.isDefer(phase)) {
697
701
  imported = true;
698
702
  }
@@ -738,6 +742,12 @@ const getSourceForModuleExternal = (
738
742
  }
739
743
  return {
740
744
  expression,
745
+ externalReexport:
746
+ moduleAndSpecifiers.length === 1 &&
747
+ !ImportPhaseUtils.isDefer(phase) &&
748
+ !ImportPhaseUtils.isSource(phase)
749
+ ? `from ${toJsStringLiteral(moduleAndSpecifiers[0])}${getImportAttributes(dependencyMeta)}`
750
+ : undefined,
741
751
  init: moduleRemapping
742
752
  ? `${runtimeTemplate.renderConst()} x = ${runtimeTemplate.basicFunction(
743
753
  "y",
@@ -1238,6 +1248,17 @@ class ExternalModule extends Module {
1238
1248
  return this._resolveExternalType(this.externalType) !== "module";
1239
1249
  }
1240
1250
 
1251
+ /**
1252
+ * The request this external resolves to for its own type, with the record form
1253
+ * narrowed to its entry. An array is a module specifier plus a property path.
1254
+ * @returns {string | string[] | undefined} the resolved request
1255
+ */
1256
+ getResolvedRequest() {
1257
+ return /** @type {string | string[] | undefined} */ (
1258
+ this._getRequestAndExternalType().request
1259
+ );
1260
+ }
1261
+
1241
1262
  /**
1242
1263
  * Get request and external type.
1243
1264
  * @private
@@ -1535,6 +1556,10 @@ class ExternalModule extends Module {
1535
1556
  data = new Map();
1536
1557
  data.set("chunkInitFragments", sourceData.chunkInitFragments);
1537
1558
  }
1559
+ if (sourceData.externalReexport) {
1560
+ if (!data) data = new Map();
1561
+ data.set("externalReexport", sourceData.externalReexport);
1562
+ }
1538
1563
 
1539
1564
  /** @type {Sources} */
1540
1565
  const sources = new Map();