webpack 5.104.1 → 5.105.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 (279) hide show
  1. package/bin/webpack.js +6 -3
  2. package/lib/APIPlugin.js +85 -15
  3. package/lib/AbstractMethodError.js +1 -0
  4. package/lib/AsyncDependenciesBlock.js +13 -1
  5. package/lib/AsyncDependencyToInitialChunkError.js +1 -0
  6. package/lib/AutomaticPrefetchPlugin.js +1 -1
  7. package/lib/BannerPlugin.js +2 -0
  8. package/lib/CacheFacade.js +2 -2
  9. package/lib/CaseSensitiveModulesWarning.js +1 -0
  10. package/lib/Chunk.js +8 -4
  11. package/lib/ChunkGraph.js +30 -9
  12. package/lib/ChunkGroup.js +6 -3
  13. package/lib/ChunkRenderError.js +2 -0
  14. package/lib/CleanPlugin.js +4 -1
  15. package/lib/CodeGenerationError.js +7 -1
  16. package/lib/CodeGenerationResults.js +10 -3
  17. package/lib/CommentCompilationWarning.js +2 -1
  18. package/lib/Compilation.js +280 -236
  19. package/lib/Compiler.js +3 -2
  20. package/lib/ConcatenationScope.js +2 -1
  21. package/lib/ConcurrentCompilationError.js +3 -3
  22. package/lib/ContextModule.js +248 -111
  23. package/lib/ContextModuleFactory.js +14 -2
  24. package/lib/DefinePlugin.js +3 -1
  25. package/lib/DelegatedModule.js +6 -0
  26. package/lib/DelegatedModuleFactoryPlugin.js +2 -0
  27. package/lib/Dependency.js +6 -1
  28. package/lib/DependencyTemplates.js +3 -2
  29. package/lib/DllModule.js +2 -0
  30. package/lib/DllReferencePlugin.js +1 -0
  31. package/lib/DotenvPlugin.js +11 -5
  32. package/lib/DynamicEntryPlugin.js +1 -0
  33. package/lib/EnvironmentNotSupportAsyncWarning.js +1 -0
  34. package/lib/EvalSourceMapDevToolPlugin.js +17 -13
  35. package/lib/ExportsInfo.js +8 -4
  36. package/lib/ExternalModule.js +16 -0
  37. package/lib/FalseIIFEUmdWarning.js +1 -0
  38. package/lib/FileSystemInfo.js +49 -25
  39. package/lib/FlagDependencyExportsPlugin.js +8 -1
  40. package/lib/FlagDependencyUsagePlugin.js +9 -7
  41. package/lib/HarmonyLinkingError.js +1 -0
  42. package/lib/HookWebpackError.js +2 -0
  43. package/lib/HotModuleReplacementPlugin.js +16 -2
  44. package/lib/InitFragment.js +1 -0
  45. package/lib/InvalidDependenciesModuleWarning.js +1 -0
  46. package/lib/LibManifestPlugin.js +1 -0
  47. package/lib/ManifestPlugin.js +4 -1
  48. package/lib/Module.js +7 -4
  49. package/lib/ModuleBuildError.js +3 -1
  50. package/lib/ModuleDependencyError.js +1 -0
  51. package/lib/ModuleDependencyWarning.js +1 -0
  52. package/lib/ModuleError.js +2 -1
  53. package/lib/ModuleFilenameHelpers.js +2 -1
  54. package/lib/ModuleGraph.js +3 -0
  55. package/lib/ModuleGraphConnection.js +10 -1
  56. package/lib/ModuleHashingError.js +2 -0
  57. package/lib/ModuleInfoHeaderPlugin.js +6 -1
  58. package/lib/ModuleNotFoundError.js +1 -0
  59. package/lib/ModuleParseError.js +5 -1
  60. package/lib/ModuleProfile.js +1 -1
  61. package/lib/ModuleRestoreError.js +2 -0
  62. package/lib/ModuleSourceTypeConstants.js +1 -11
  63. package/lib/ModuleStoreError.js +2 -0
  64. package/lib/ModuleWarning.js +3 -1
  65. package/lib/MultiCompiler.js +11 -7
  66. package/lib/MultiWatching.js +2 -2
  67. package/lib/NoModeWarning.js +1 -0
  68. package/lib/NodeStuffInWebError.js +1 -0
  69. package/lib/NormalModule.js +26 -5
  70. package/lib/NormalModuleFactory.js +20 -4
  71. package/lib/OptionsApply.js +3 -1
  72. package/lib/ProgressPlugin.js +4 -0
  73. package/lib/RawModule.js +2 -0
  74. package/lib/RuntimeModule.js +10 -0
  75. package/lib/RuntimePlugin.js +7 -9
  76. package/lib/RuntimeTemplate.js +14 -7
  77. package/lib/SourceMapDevToolPlugin.js +30 -23
  78. package/lib/Template.js +10 -5
  79. package/lib/TemplatedPathPlugin.js +4 -2
  80. package/lib/UnhandledSchemeError.js +1 -0
  81. package/lib/UnsupportedFeatureWarning.js +1 -0
  82. package/lib/WarnDeprecatedOptionPlugin.js +1 -0
  83. package/lib/WatchIgnorePlugin.js +1 -1
  84. package/lib/Watching.js +5 -0
  85. package/lib/WebpackError.js +4 -0
  86. package/lib/WebpackOptionsApply.js +60 -40
  87. package/lib/asset/AssetBytesGenerator.js +1 -0
  88. package/lib/asset/AssetGenerator.js +9 -3
  89. package/lib/asset/AssetModulesPlugin.js +33 -2
  90. package/lib/asset/AssetSourceGenerator.js +1 -0
  91. package/lib/asset/RawDataUrlModule.js +4 -0
  92. package/lib/async-modules/AwaitDependenciesInitFragment.js +4 -1
  93. package/lib/buildChunkGraph.js +31 -2
  94. package/lib/cache/MemoryWithGcCachePlugin.js +1 -0
  95. package/lib/cache/PackFileCacheStrategy.js +41 -8
  96. package/lib/cache/getLazyHashedEtag.js +13 -4
  97. package/lib/cache/mergeEtags.js +3 -1
  98. package/lib/cli.js +3 -1
  99. package/lib/config/defaults.js +65 -44
  100. package/lib/config/normalization.js +96 -0
  101. package/lib/container/ContainerEntryModule.js +4 -0
  102. package/lib/container/FallbackModule.js +2 -0
  103. package/lib/container/HoistContainerReferencesPlugin.js +6 -0
  104. package/lib/container/RemoteModule.js +19 -0
  105. package/lib/css/CssGenerator.js +31 -4
  106. package/lib/css/CssModulesPlugin.js +26 -30
  107. package/lib/css/CssParser.js +12 -9
  108. package/lib/debug/ProfilingPlugin.js +1 -0
  109. package/lib/dependencies/AMDDefineDependency.js +3 -1
  110. package/lib/dependencies/AMDDefineDependencyParserPlugin.js +6 -0
  111. package/lib/dependencies/AMDPlugin.js +1 -1
  112. package/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js +7 -1
  113. package/lib/dependencies/CachedConstDependency.js +1 -0
  114. package/lib/dependencies/CommonJsDependencyHelpers.js +2 -0
  115. package/lib/dependencies/CommonJsExportRequireDependency.js +1 -0
  116. package/lib/dependencies/CommonJsFullRequireDependency.js +2 -0
  117. package/lib/dependencies/CommonJsImportsParserPlugin.js +3 -0
  118. package/lib/dependencies/CommonJsRequireContextDependency.js +2 -2
  119. package/lib/dependencies/CommonJsSelfReferenceDependency.js +1 -0
  120. package/lib/dependencies/ConstDependency.js +1 -0
  121. package/lib/dependencies/ContextDependencyHelpers.js +11 -4
  122. package/lib/dependencies/ContextElementDependency.js +1 -0
  123. package/lib/dependencies/CriticalDependencyWarning.js +1 -0
  124. package/lib/dependencies/CssIcssExportDependency.js +5 -4
  125. package/lib/dependencies/CssIcssSymbolDependency.js +1 -0
  126. package/lib/dependencies/CssUrlDependency.js +2 -3
  127. package/lib/dependencies/ExternalModuleInitFragment.js +4 -1
  128. package/lib/dependencies/ExternalModuleInitFragmentDependency.js +0 -9
  129. package/lib/dependencies/HarmonyAcceptDependency.js +3 -0
  130. package/lib/dependencies/HarmonyEvaluatedImportSpecifierDependency.js +1 -0
  131. package/lib/dependencies/HarmonyExportExpressionDependency.js +4 -0
  132. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +8 -1
  133. package/lib/dependencies/HarmonyExportInitFragment.js +17 -3
  134. package/lib/dependencies/HarmonyExportSpecifierDependency.js +4 -0
  135. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +266 -5
  136. package/lib/dependencies/HarmonyImportSpecifierDependency.js +22 -3
  137. package/lib/dependencies/ImportDependency.js +1 -0
  138. package/lib/dependencies/ImportMetaContextDependencyParserPlugin.js +1 -0
  139. package/lib/dependencies/ImportMetaPlugin.js +53 -11
  140. package/lib/dependencies/ImportParserPlugin.js +7 -12
  141. package/lib/dependencies/LoaderPlugin.js +3 -0
  142. package/lib/dependencies/ModuleDecoratorDependency.js +1 -0
  143. package/lib/dependencies/ModuleDependency.js +1 -0
  144. package/lib/dependencies/ModuleInitFragmentDependency.js +87 -0
  145. package/lib/dependencies/ProvidedDependency.js +1 -0
  146. package/lib/dependencies/RequireContextPlugin.js +1 -0
  147. package/lib/dependencies/RequireEnsureDependenciesBlockParserPlugin.js +7 -2
  148. package/lib/dependencies/RuntimeRequirementsDependency.js +1 -0
  149. package/lib/dependencies/WorkerDependency.js +9 -3
  150. package/lib/dependencies/WorkerPlugin.js +1 -0
  151. package/lib/dependencies/getFunctionExpression.js +3 -1
  152. package/lib/errors/BuildCycleError.js +4 -1
  153. package/lib/esm/ModuleChunkFormatPlugin.js +6 -4
  154. package/lib/esm/ModuleChunkLoadingPlugin.js +1 -0
  155. package/lib/esm/ModuleChunkLoadingRuntimeModule.js +1 -0
  156. package/lib/hmr/LazyCompilationPlugin.js +5 -0
  157. package/lib/hmr/lazyCompilationBackend.js +3 -2
  158. package/lib/ids/ChunkModuleIdRangePlugin.js +2 -0
  159. package/lib/ids/IdHelpers.js +10 -8
  160. package/lib/ids/OccurrenceModuleIdsPlugin.js +15 -7
  161. package/lib/ids/SyncModuleIdsPlugin.js +5 -1
  162. package/lib/javascript/BasicEvaluatedExpression.js +1 -0
  163. package/lib/javascript/EnableChunkLoadingPlugin.js +5 -2
  164. package/lib/javascript/JavascriptModulesPlugin.js +29 -8
  165. package/lib/javascript/JavascriptParser.js +47 -14
  166. package/lib/json/JsonParser.js +6 -0
  167. package/lib/library/AbstractLibraryPlugin.js +4 -1
  168. package/lib/library/AmdLibraryPlugin.js +2 -1
  169. package/lib/library/AssignLibraryPlugin.js +6 -2
  170. package/lib/library/EnableLibraryPlugin.js +1 -0
  171. package/lib/library/ExportPropertyLibraryPlugin.js +1 -1
  172. package/lib/library/JsonpLibraryPlugin.js +1 -1
  173. package/lib/library/ModuleLibraryPlugin.js +130 -13
  174. package/lib/library/SystemLibraryPlugin.js +4 -1
  175. package/lib/library/UmdLibraryPlugin.js +4 -3
  176. package/lib/logging/createConsoleLogger.js +3 -0
  177. package/lib/logging/truncateArgs.js +1 -1
  178. package/lib/node/CommonJsChunkLoadingPlugin.js +1 -0
  179. package/lib/node/NodeTargetPlugin.js +1 -0
  180. package/lib/node/NodeWatchFileSystem.js +3 -0
  181. package/lib/node/nodeConsole.js +18 -1
  182. package/lib/optimize/AggressiveMergingPlugin.js +2 -1
  183. package/lib/optimize/AggressiveSplittingPlugin.js +10 -6
  184. package/lib/optimize/ConcatenatedModule.js +33 -19
  185. package/lib/optimize/FlagIncludedChunksPlugin.js +11 -1
  186. package/lib/optimize/InnerGraph.js +5 -3
  187. package/lib/optimize/InnerGraphPlugin.js +25 -25
  188. package/lib/optimize/MangleExportsPlugin.js +14 -2
  189. package/lib/optimize/MergeDuplicateChunksPlugin.js +3 -0
  190. package/lib/optimize/MinChunkSizePlugin.js +5 -2
  191. package/lib/optimize/ModuleConcatenationPlugin.js +19 -4
  192. package/lib/optimize/RealContentHashPlugin.js +35 -27
  193. package/lib/optimize/RemoveParentModulesPlugin.js +12 -3
  194. package/lib/optimize/SideEffectsFlagPlugin.js +3 -0
  195. package/lib/optimize/SplitChunksPlugin.js +14 -3
  196. package/lib/performance/AssetsOverSizeLimitWarning.js +6 -2
  197. package/lib/performance/EntrypointsOverSizeLimitWarning.js +6 -2
  198. package/lib/performance/NoAsyncChunksWarning.js +1 -0
  199. package/lib/rules/BasicEffectRulePlugin.js +2 -0
  200. package/lib/rules/BasicMatcherRulePlugin.js +3 -0
  201. package/lib/rules/ObjectMatcherRulePlugin.js +5 -1
  202. package/lib/rules/RuleSetCompiler.js +2 -0
  203. package/lib/runtime/AsyncModuleRuntimeModule.js +1 -0
  204. package/lib/runtime/ChunkNameRuntimeModule.js +1 -0
  205. package/lib/runtime/CompatRuntimeModule.js +1 -0
  206. package/lib/runtime/EnsureChunkRuntimeModule.js +1 -0
  207. package/lib/runtime/GetChunkFilenameRuntimeModule.js +4 -0
  208. package/lib/runtime/GetMainFilenameRuntimeModule.js +2 -0
  209. package/lib/runtime/GetTrustedTypesPolicyRuntimeModule.js +1 -0
  210. package/lib/runtime/LoadScriptRuntimeModule.js +2 -0
  211. package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +15 -32
  212. package/lib/runtime/PublicPathRuntimeModule.js +1 -0
  213. package/lib/runtime/StartupChunkDependenciesPlugin.js +2 -0
  214. package/lib/runtime/StartupChunkDependenciesRuntimeModule.js +1 -0
  215. package/lib/runtime/StartupEntrypointRuntimeModule.js +1 -0
  216. package/lib/schemes/HttpUriPlugin.js +27 -7
  217. package/lib/schemes/VirtualUrlPlugin.js +7 -2
  218. package/lib/serialization/BinaryMiddleware.js +4 -0
  219. package/lib/serialization/FileMiddleware.js +9 -4
  220. package/lib/serialization/ObjectMiddleware.js +34 -11
  221. package/lib/serialization/PlainObjectSerializer.js +2 -0
  222. package/lib/sharing/ConsumeSharedModule.js +60 -0
  223. package/lib/sharing/ConsumeSharedPlugin.js +5 -4
  224. package/lib/sharing/ProvideSharedModule.js +4 -0
  225. package/lib/sharing/ProvideSharedPlugin.js +24 -25
  226. package/lib/sharing/resolveMatchedConfigs.js +2 -2
  227. package/lib/sharing/utils.js +8 -6
  228. package/lib/stats/DefaultStatsFactoryPlugin.js +14 -12
  229. package/lib/stats/DefaultStatsPrinterPlugin.js +6 -5
  230. package/lib/stats/StatsFactory.js +2 -2
  231. package/lib/url/URLParserPlugin.js +4 -3
  232. package/lib/util/AppendOnlyStackedSet.js +57 -0
  233. package/lib/util/Hash.js +1 -0
  234. package/lib/util/IterableHelpers.js +1 -0
  235. package/lib/util/LazyBucketSortedSet.js +1 -0
  236. package/lib/util/LazySet.js +1 -0
  237. package/lib/util/ParallelismFactorCalculator.js +1 -0
  238. package/lib/util/SortableSet.js +1 -0
  239. package/lib/util/StringXor.js +1 -0
  240. package/lib/util/binarySearchBounds.js +15 -8
  241. package/lib/util/chainedImports.js +1 -1
  242. package/lib/util/cleverMerge.js +6 -1
  243. package/lib/util/comparators.js +21 -1
  244. package/lib/util/compileBooleanMatcher.js +3 -3
  245. package/lib/util/concatenate.js +3 -2
  246. package/lib/util/conventions.js +3 -2
  247. package/lib/util/deterministicGrouping.js +13 -1
  248. package/lib/util/extractSourceMap.js +12 -13
  249. package/lib/util/fs.js +15 -19
  250. package/lib/util/hash/BatchedHash.js +3 -0
  251. package/lib/util/hash/BulkUpdateHash.js +7 -1
  252. package/lib/util/hash/hash-digest.js +1 -0
  253. package/lib/util/hash/wasm-hash.js +16 -1
  254. package/lib/util/identifier.js +7 -2
  255. package/lib/util/magicComment.js +1 -1
  256. package/lib/util/propertyName.js +1 -1
  257. package/lib/util/registerExternalSerializer.js +1 -0
  258. package/lib/util/runtime.js +15 -1
  259. package/lib/util/semver.js +1 -0
  260. package/lib/util/serialization.js +2 -2
  261. package/lib/wasm/EnableWasmLoadingPlugin.js +1 -0
  262. package/lib/wasm-async/AsyncWasmLoadingRuntimeModule.js +11 -3
  263. package/lib/wasm-async/AsyncWebAssemblyGenerator.js +1 -0
  264. package/lib/wasm-async/AsyncWebAssemblyModulesPlugin.js +3 -2
  265. package/lib/wasm-sync/UnsupportedWebAssemblyFeatureError.js +5 -1
  266. package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +3 -0
  267. package/lib/wasm-sync/WebAssemblyInInitialChunkError.js +2 -0
  268. package/lib/wasm-sync/WebAssemblyJavascriptGenerator.js +7 -3
  269. package/lib/wasm-sync/WebAssemblyModulesPlugin.js +2 -2
  270. package/lib/wasm-sync/WebAssemblyParser.js +3 -1
  271. package/lib/web/FetchCompileWasmPlugin.js +1 -0
  272. package/lib/web/JsonpChunkLoadingPlugin.js +1 -0
  273. package/lib/web/JsonpChunkLoadingRuntimeModule.js +1 -0
  274. package/lib/webpack.js +13 -3
  275. package/lib/webworker/ImportScriptsChunkLoadingPlugin.js +1 -0
  276. package/package.json +20 -28
  277. package/schemas/WebpackOptions.check.js +1 -1
  278. package/schemas/WebpackOptions.json +71 -5
  279. package/types.d.ts +339 -93
@@ -58,6 +58,7 @@ const processExportInfo = require("./processExportInfo");
58
58
  /** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
59
59
  /** @typedef {import("./HarmonyImportDependency").Ids} Ids */
60
60
  /** @typedef {import("./HarmonyImportDependency").ExportPresenceMode} ExportPresenceMode */
61
+ /** @typedef {import("./HarmonyExportInitFragment").ExportMap} ExportMap */
61
62
  /** @typedef {import("../dependencies/ImportPhase").ImportPhaseType} ImportPhaseType */
62
63
 
63
64
  /** @typedef {"missing" | "unused" | "empty-star" | "reexport-dynamic-default" | "reexport-named-default" | "reexport-namespace-object" | "reexport-fake-namespace-object" | "reexport-undefined" | "normal-reexport" | "dynamic-reexport"} ExportModeType */
@@ -264,6 +265,7 @@ const getMode = (moduleGraph, dep, runtimeKey) => {
264
265
 
265
266
  // reexporting with a fixed name
266
267
  if (name) {
268
+ /** @type {ExportMode} */
267
269
  let mode;
268
270
  const exportInfo = exportsInfo.getReadOnlyExportInfo(name);
269
271
 
@@ -464,7 +466,7 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
464
466
  * @param {RuntimeSpec} runtime the runtime
465
467
  * @param {ExportsInfo} exportsInfo exports info about the current module (optional)
466
468
  * @param {Module} importedModule the imported module (optional)
467
- * @returns {{exports?: Exports, checked?: Checked, ignoredExports: IgnoredExports, hidden?: Hidden}} information
469
+ * @returns {{ exports?: Exports, checked?: Checked, ignoredExports: IgnoredExports, hidden?: Hidden }} information
468
470
  */
469
471
  getStarReexports(
470
472
  moduleGraph,
@@ -480,8 +482,10 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
480
482
  const noExtraImports =
481
483
  exportsInfo.otherExportsInfo.getUsed(runtime) === UsageState.Unused;
482
484
 
485
+ /** @type {IgnoredExports} */
483
486
  const ignoredExports = new Set(["default", ...this.activeExports]);
484
487
 
488
+ /** @type {Hidden | undefined} */
485
489
  let hiddenExports;
486
490
  const otherStarExports =
487
491
  this._discoverActiveExportsFromOtherStarExports(moduleGraph);
@@ -1300,6 +1304,7 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS
1300
1304
  runtimeRequirements.add(RuntimeGlobals.exports);
1301
1305
  runtimeRequirements.add(RuntimeGlobals.definePropertyGetters);
1302
1306
 
1307
+ /** @type {ExportMap} */
1303
1308
  const map = new Map();
1304
1309
  map.set(key, `/* ${comment} */ ${returnValue}`);
1305
1310
 
@@ -1325,6 +1330,7 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS
1325
1330
  runtimeRequirements.add(RuntimeGlobals.definePropertyGetters);
1326
1331
  runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
1327
1332
 
1333
+ /** @type {ExportMap} */
1328
1334
  const map = new Map();
1329
1335
  map.set(
1330
1336
  key,
@@ -1365,6 +1371,7 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS
1365
1371
  runtimeRequirements.add(RuntimeGlobals.definePropertyGetters);
1366
1372
  runtimeRequirements.add(RuntimeGlobals.makeDeferredNamespaceObject);
1367
1373
 
1374
+ /** @type {ExportMap} */
1368
1375
  const map = new Map();
1369
1376
  const moduleId = JSON.stringify(chunkGraph.getModuleId(module));
1370
1377
  const mode = getMakeDeferredNamespaceModeFromExportsType(exportsType);
@@ -12,6 +12,7 @@ const { propertyName } = require("../util/propertyName");
12
12
 
13
13
  /** @typedef {import("webpack-sources").Source} Source */
14
14
  /** @typedef {import("../Generator").GenerateContext} GenerateContext */
15
+ /** @typedef {import("../ExportsInfo").UsedName} UsedName */
15
16
 
16
17
  /**
17
18
  * @param {Iterable<string>} iterable iterable strings
@@ -33,7 +34,12 @@ const joinIterableWithComma = (iterable) => {
33
34
  return str;
34
35
  };
35
36
 
37
+ /** @typedef {Map<UsedName, string>} ExportMap */
38
+ /** @typedef {Set<string>} UnusedExports */
39
+
40
+ /** @type {ExportMap} */
36
41
  const EMPTY_MAP = new Map();
42
+ /** @type {UnusedExports} */
37
43
  const EMPTY_SET = new Set();
38
44
 
39
45
  /**
@@ -42,8 +48,8 @@ const EMPTY_SET = new Set();
42
48
  class HarmonyExportInitFragment extends InitFragment {
43
49
  /**
44
50
  * @param {string} exportsArgument the exports identifier
45
- * @param {Map<string, string>} exportMap mapping from used name to exposed variable name
46
- * @param {Set<string>} unusedExports list of unused export names
51
+ * @param {ExportMap} exportMap mapping from used name to exposed variable name
52
+ * @param {UnusedExports} unusedExports list of unused export names
47
53
  */
48
54
  constructor(
49
55
  exportsArgument,
@@ -51,8 +57,11 @@ class HarmonyExportInitFragment extends InitFragment {
51
57
  unusedExports = EMPTY_SET
52
58
  ) {
53
59
  super(undefined, InitFragment.STAGE_HARMONY_EXPORTS, 1, "harmony-exports");
60
+ /** @type {string} */
54
61
  this.exportsArgument = exportsArgument;
62
+ /** @type {ExportMap} */
55
63
  this.exportMap = exportMap;
64
+ /** @type {UnusedExports} */
56
65
  this.unusedExports = unusedExports;
57
66
  }
58
67
 
@@ -61,8 +70,10 @@ class HarmonyExportInitFragment extends InitFragment {
61
70
  * @returns {HarmonyExportInitFragment} merged fragment
62
71
  */
63
72
  mergeAll(fragments) {
73
+ /** @type {undefined | ExportMap} */
64
74
  let exportMap;
65
75
  let exportMapOwned = false;
76
+ /** @type {undefined | UnusedExports} */
66
77
  let unusedExports;
67
78
  let unusedExportsOwned = false;
68
79
 
@@ -108,6 +119,7 @@ class HarmonyExportInitFragment extends InitFragment {
108
119
  * @returns {HarmonyExportInitFragment} merged result
109
120
  */
110
121
  merge(other) {
122
+ /** @type {ExportMap} */
111
123
  let exportMap;
112
124
  if (this.exportMap.size === 0) {
113
125
  exportMap = other.exportMap;
@@ -119,6 +131,7 @@ class HarmonyExportInitFragment extends InitFragment {
119
131
  if (!exportMap.has(key)) exportMap.set(key, value);
120
132
  }
121
133
  }
134
+ /** @type {UnusedExports} */
122
135
  let unusedExports;
123
136
  if (this.unusedExports.size === 0) {
124
137
  unusedExports = other.unusedExports;
@@ -153,6 +166,7 @@ class HarmonyExportInitFragment extends InitFragment {
153
166
  : this.unusedExports.size > 0
154
167
  ? `/* unused harmony export ${first(this.unusedExports)} */\n`
155
168
  : "";
169
+ /** @type {string[]} */
156
170
  const definitions = [];
157
171
  const orderedExportMap = [...this.exportMap].sort(([a], [b]) =>
158
172
  a < b ? -1 : 1
@@ -160,7 +174,7 @@ class HarmonyExportInitFragment extends InitFragment {
160
174
  for (const [key, value] of orderedExportMap) {
161
175
  definitions.push(
162
176
  `\n/* harmony export */ ${propertyName(
163
- key
177
+ /** @type {string} */ (key)
164
178
  )}: ${runtimeTemplate.returningFunction(value)}`
165
179
  );
166
180
  }
@@ -17,6 +17,8 @@ const NullDependency = require("./NullDependency");
17
17
  /** @typedef {import("../ModuleGraphConnection").ConnectionState} ConnectionState */
18
18
  /** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */
19
19
  /** @typedef {import("../serialization/ObjectMiddleware").ObjectSerializerContext} ObjectSerializerContext */
20
+ /** @typedef {import("./HarmonyExportInitFragment").UnusedExports} UnusedExports */
21
+ /** @typedef {import("./HarmonyExportInitFragment").ExportMap} ExportMap */
20
22
 
21
23
  class HarmonyExportSpecifierDependency extends NullDependency {
22
24
  /**
@@ -104,6 +106,7 @@ HarmonyExportSpecifierDependency.Template = class HarmonyExportSpecifierDependen
104
106
  .getExportsInfo(module)
105
107
  .getUsedName(dep.name, runtime);
106
108
  if (!used) {
109
+ /** @type {UnusedExports} */
107
110
  const set = new Set();
108
111
  set.add(dep.name || "namespace");
109
112
  initFragments.push(
@@ -112,6 +115,7 @@ HarmonyExportSpecifierDependency.Template = class HarmonyExportSpecifierDependen
112
115
  return;
113
116
  }
114
117
 
118
+ /** @type {ExportMap} */
115
119
  const map = new Map();
116
120
  map.set(used, `/* binding */ ${dep.id}`);
117
121
  initFragments.push(
@@ -12,6 +12,7 @@ const {
12
12
  getImportAttributes
13
13
  } = require("../javascript/JavascriptParser");
14
14
  const InnerGraph = require("../optimize/InnerGraph");
15
+ const AppendOnlyStackedSet = require("../util/AppendOnlyStackedSet");
15
16
  const ConstDependency = require("./ConstDependency");
16
17
  const HarmonyAcceptDependency = require("./HarmonyAcceptDependency");
17
18
  const HarmonyAcceptImportDependency = require("./HarmonyAcceptImportDependency");
@@ -36,9 +37,18 @@ const { ImportPhaseUtils, createGetImportPhase } = require("./ImportPhase");
36
37
  /** @typedef {import("../javascript/JavascriptParser").Members} Members */
37
38
  /** @typedef {import("../javascript/JavascriptParser").MembersOptionals} MembersOptionals */
38
39
  /** @typedef {import("./HarmonyImportDependency").Ids} Ids */
40
+ /** @typedef {import("./HarmonyImportDependency").ExportPresenceMode} ExportPresenceMode */
39
41
  /** @typedef {import("./ImportPhase").ImportPhaseType} ImportPhaseType */
40
42
 
43
+ /**
44
+ * @typedef {object} HarmonySpecifierGuards
45
+ * @property {AppendOnlyStackedSet<string> | undefined} guards
46
+ */
47
+
48
+ /** @typedef {Map<string, Set<string>>} Guards Map of import root to guarded member keys */
49
+
41
50
  const harmonySpecifierTag = Symbol("harmony import");
51
+ const harmonySpecifierGuardTag = Symbol("harmony import guard");
42
52
 
43
53
  /**
44
54
  * @typedef {object} HarmonySettings
@@ -53,6 +63,18 @@ const harmonySpecifierTag = Symbol("harmony import");
53
63
 
54
64
  const PLUGIN_NAME = "HarmonyImportDependencyParserPlugin";
55
65
 
66
+ /** @type {(members: Members) => string} */
67
+ const getMembersKey = (members) => members.join(".");
68
+
69
+ /**
70
+ * Strip the root binding name if needed
71
+ * @param {HarmonySettings} settings settings
72
+ * @param {Ids} ids ids
73
+ * @returns {Ids} ids for presence check
74
+ */
75
+ const getIdsForPresence = (settings, ids) =>
76
+ settings.ids.length ? ids.slice(1) : ids;
77
+
56
78
  module.exports = class HarmonyImportDependencyParserPlugin {
57
79
  /**
58
80
  * @param {JavascriptParserOptions} options options
@@ -70,13 +92,30 @@ module.exports = class HarmonyImportDependencyParserPlugin {
70
92
  this.strictThisContextOnImports = options.strictThisContextOnImports;
71
93
  }
72
94
 
95
+ /**
96
+ * @param {JavascriptParser} parser the parser
97
+ * @param {Ids} ids ids
98
+ * @returns {ExportPresenceMode} exportPresenceMode
99
+ */
100
+ getExportPresenceMode(parser, ids) {
101
+ const harmonySettings = /** @type {HarmonySettings=} */ (
102
+ parser.currentTagData
103
+ );
104
+ if (!harmonySettings) return this.exportPresenceMode;
105
+
106
+ const data = /** @type {HarmonySpecifierGuards=} */ (
107
+ parser.getTagData(harmonySettings.name, harmonySpecifierGuardTag)
108
+ );
109
+ return data && data.guards && data.guards.has(getMembersKey(ids))
110
+ ? false
111
+ : this.exportPresenceMode;
112
+ }
113
+
73
114
  /**
74
115
  * @param {JavascriptParser} parser the parser
75
116
  * @returns {void}
76
117
  */
77
118
  apply(parser) {
78
- const { exportPresenceMode } = this;
79
-
80
119
  const getImportPhase = createGetImportPhase(this.options.deferImport);
81
120
 
82
121
  /**
@@ -228,6 +267,7 @@ module.exports = class HarmonyImportDependencyParserPlugin {
228
267
  .for(harmonySpecifierTag)
229
268
  .tap(PLUGIN_NAME, (expr) => {
230
269
  const settings = /** @type {HarmonySettings} */ (parser.currentTagData);
270
+
231
271
  const dep = new HarmonyImportSpecifierDependency(
232
272
  settings.source,
233
273
  settings.sourceOrder,
@@ -235,7 +275,10 @@ module.exports = class HarmonyImportDependencyParserPlugin {
235
275
  settings.name,
236
276
  /** @type {Range} */
237
277
  (expr.range),
238
- exportPresenceMode,
278
+ this.getExportPresenceMode(
279
+ parser,
280
+ getIdsForPresence(settings, settings.ids)
281
+ ),
239
282
  settings.phase,
240
283
  settings.attributes,
241
284
  []
@@ -285,7 +328,10 @@ module.exports = class HarmonyImportDependencyParserPlugin {
285
328
  settings.name,
286
329
  /** @type {Range} */
287
330
  (expr.range),
288
- exportPresenceMode,
331
+ this.getExportPresenceMode(
332
+ parser,
333
+ getIdsForPresence(settings, ids)
334
+ ),
289
335
  settings.phase,
290
336
  settings.attributes,
291
337
  ranges
@@ -335,7 +381,10 @@ module.exports = class HarmonyImportDependencyParserPlugin {
335
381
  ids,
336
382
  settings.name,
337
383
  /** @type {Range} */ (expr.range),
338
- exportPresenceMode,
384
+ this.getExportPresenceMode(
385
+ parser,
386
+ getIdsForPresence(settings, ids)
387
+ ),
339
388
  settings.phase,
340
389
  settings.attributes,
341
390
  ranges
@@ -402,7 +451,219 @@ module.exports = class HarmonyImportDependencyParserPlugin {
402
451
  parser.state.module.addDependency(dep);
403
452
  }
404
453
  });
454
+
455
+ /**
456
+ * @param {Expression} expression expression
457
+ * @returns {{ root: string, members: Members } | undefined} info
458
+ */
459
+ const getHarmonyImportInfo = (expression) => {
460
+ const nameInfo = parser.getNameForExpression(expression);
461
+ if (!nameInfo) return;
462
+
463
+ const rootInfo = nameInfo.rootInfo;
464
+ const root =
465
+ typeof rootInfo === "string"
466
+ ? rootInfo
467
+ : rootInfo instanceof VariableInfo
468
+ ? rootInfo.name
469
+ : undefined;
470
+ if (!root) return;
471
+ if (!parser.getTagData(root, harmonySpecifierTag)) return;
472
+ return { root, members: nameInfo.getMembers() };
473
+ };
474
+
475
+ /**
476
+ * @param {Guards} guards guards
477
+ * @param {string} root root name
478
+ * @param {Members} members members
479
+ */
480
+ const addToGuards = (guards, root, members) => {
481
+ const membersKey = getMembersKey(members);
482
+ const guardedMembers = guards.get(root);
483
+ if (guardedMembers) {
484
+ guardedMembers.add(membersKey);
485
+ return;
486
+ }
487
+
488
+ guards.set(
489
+ root,
490
+ // Adding `foo.bar` implies guarding `foo` as well
491
+ membersKey === "" ? new Set([""]) : new Set([membersKey, ""])
492
+ );
493
+ };
494
+
495
+ /**
496
+ * @param {Expression} expression expression
497
+ * @param {Guards} guards guards
498
+ * @param {boolean} needTruthy need to be truthy
499
+ */
500
+ const collect = (expression, guards, needTruthy) => {
501
+ // !foo
502
+ if (
503
+ expression.type === "UnaryExpression" &&
504
+ expression.operator === "!"
505
+ ) {
506
+ collect(expression.argument, guards, !needTruthy);
507
+ return;
508
+ } else if (expression.type === "LogicalExpression" && needTruthy) {
509
+ // foo && bar
510
+ if (expression.operator === "&&") {
511
+ collect(expression.left, guards, true);
512
+ collect(expression.right, guards, true);
513
+ }
514
+ // falsy || foo
515
+ else if (expression.operator === "||") {
516
+ const leftEvaluation = parser.evaluateExpression(expression.left);
517
+ const leftBool = leftEvaluation.asBool();
518
+ if (leftBool === false) {
519
+ collect(expression.right, guards, true);
520
+ }
521
+ }
522
+ // nullish ?? foo
523
+ else if (expression.operator === "??") {
524
+ const leftEvaluation = parser.evaluateExpression(expression.left);
525
+ const leftNullish = leftEvaluation.asNullish();
526
+ if (leftNullish === true) {
527
+ collect(expression.right, guards, true);
528
+ }
529
+ }
530
+ return;
531
+ }
532
+ if (!needTruthy) return;
533
+
534
+ /**
535
+ * @param {Expression} targetExpression expression
536
+ * @returns {boolean} is added
537
+ */
538
+ const addGuardForExpression = (targetExpression) => {
539
+ const info = getHarmonyImportInfo(targetExpression);
540
+ if (!info) return false;
541
+ addToGuards(guards, info.root, info.members);
542
+ return true;
543
+ };
544
+
545
+ /**
546
+ * @param {Expression} left left expression
547
+ * @param {Expression} right right expression
548
+ * @param {(evaluation: ReturnType<JavascriptParser["evaluateExpression"]>) => boolean} matcher matcher
549
+ * @returns {boolean} is added
550
+ */
551
+ const addGuardForNullishCompare = (left, right, matcher) => {
552
+ const leftEval = parser.evaluateExpression(left);
553
+ if (leftEval && matcher(leftEval)) {
554
+ return addGuardForExpression(right);
555
+ }
556
+ const rightEval = parser.evaluateExpression(right);
557
+ if (rightEval && matcher(rightEval)) {
558
+ return addGuardForExpression(/** @type {Expression} */ (left));
559
+ }
560
+ return false;
561
+ };
562
+
563
+ if (expression.type === "BinaryExpression") {
564
+ // "bar" in foo
565
+ if (expression.operator === "in") {
566
+ const leftEvaluation = parser.evaluateExpression(expression.left);
567
+ if (leftEvaluation.couldHaveSideEffects()) return;
568
+ const propertyName = leftEvaluation.asString();
569
+ if (!propertyName) return;
570
+ parser.evaluateExpression(expression.right);
571
+ const info = getHarmonyImportInfo(expression.right);
572
+ if (!info) return;
573
+
574
+ if (info.members.length) {
575
+ for (const member of info.members) {
576
+ addToGuards(guards, info.root, [member]);
577
+ }
578
+ }
579
+ addToGuards(guards, info.root, [...info.members, propertyName]);
580
+ return;
581
+ }
582
+ // foo !== undefined
583
+ else if (
584
+ expression.operator === "!==" &&
585
+ addGuardForNullishCompare(
586
+ /** @type {Expression} */ (expression.left),
587
+ expression.right,
588
+ (evaluation) => evaluation.isUndefined()
589
+ )
590
+ ) {
591
+ return;
592
+ }
593
+ // foo != undefined
594
+ // foo != null
595
+ else if (
596
+ expression.operator === "!=" &&
597
+ addGuardForNullishCompare(
598
+ /** @type {Expression} */ (expression.left),
599
+ expression.right,
600
+ (evaluation) => Boolean(evaluation.asNullish())
601
+ )
602
+ ) {
603
+ return;
604
+ }
605
+ }
606
+ addGuardForExpression(expression);
607
+ };
608
+
609
+ /**
610
+ * @param {Guards} guards guards
611
+ * @param {() => void} walk walk callback
612
+ * @returns {void}
613
+ */
614
+ const withGuards = (guards, walk) => {
615
+ const applyGuards = () => {
616
+ /** @type {(() => void)[]} */
617
+ const restoreFns = [];
618
+
619
+ for (const [rootName, members] of guards) {
620
+ const previous = parser.getVariableInfo(rootName);
621
+ const exist = /** @type {HarmonySpecifierGuards=} */ (
622
+ parser.getTagData(rootName, harmonySpecifierGuardTag)
623
+ );
624
+
625
+ const mergedGuards =
626
+ exist && exist.guards
627
+ ? exist.guards.createChild()
628
+ : new AppendOnlyStackedSet();
629
+
630
+ for (const memberKey of members) mergedGuards.add(memberKey);
631
+ parser.tagVariable(rootName, harmonySpecifierGuardTag, {
632
+ guards: mergedGuards
633
+ });
634
+ restoreFns.push(() => {
635
+ parser.setVariable(rootName, previous);
636
+ });
637
+ }
638
+
639
+ return () => {
640
+ for (const restore of restoreFns) {
641
+ restore();
642
+ }
643
+ };
644
+ };
645
+
646
+ const restore = applyGuards();
647
+ try {
648
+ walk();
649
+ } finally {
650
+ restore();
651
+ }
652
+ };
653
+
654
+ parser.hooks.collectGuards.tap(PLUGIN_NAME, (expression) => {
655
+ if (parser.scope.isAsmJs) return;
656
+ /** @type {Guards} */
657
+ const guards = new Map();
658
+ collect(expression, guards, true);
659
+
660
+ if (guards.size === 0) return;
661
+ return (walk) => {
662
+ withGuards(guards, walk);
663
+ };
664
+ });
405
665
  }
406
666
  };
407
667
 
668
+ module.exports.harmonySpecifierGuardTag = harmonySpecifierGuardTag;
408
669
  module.exports.harmonySpecifierTag = harmonySpecifierTag;
@@ -6,6 +6,7 @@
6
6
  "use strict";
7
7
 
8
8
  const Dependency = require("../Dependency");
9
+ const InitFragment = require("../InitFragment");
9
10
  const Template = require("../Template");
10
11
  const {
11
12
  getDependencyUsedByExportsCondition
@@ -72,10 +73,15 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency {
72
73
  this.range = range;
73
74
  this.idRanges = idRanges;
74
75
  this.exportPresenceMode = exportPresenceMode;
76
+ /** @type {undefined | boolean} */
75
77
  this.namespaceObjectAsContext = false;
78
+ /** @type {undefined | boolean} */
76
79
  this.call = undefined;
80
+ /** @type {undefined | boolean} */
77
81
  this.directImport = undefined;
82
+ /** @type {undefined | boolean | string} */
78
83
  this.shorthand = undefined;
84
+ /** @type {undefined | boolean} */
79
85
  this.asiSafe = undefined;
80
86
  /** @type {UsedByExports | undefined} */
81
87
  this.usedByExports = undefined;
@@ -336,10 +342,22 @@ HarmonyImportSpecifierDependency.Template = class HarmonyImportSpecifierDependen
336
342
  */
337
343
  apply(dependency, source, templateContext) {
338
344
  const dep = /** @type {HarmonyImportSpecifierDependency} */ (dependency);
339
- const { moduleGraph, runtime } = templateContext;
345
+ const { moduleGraph, runtime, initFragments } = templateContext;
340
346
  const connection = moduleGraph.getConnection(dep);
341
- // Skip rendering depending when dependency is conditional
342
- if (connection && !connection.isTargetActive(runtime)) return;
347
+
348
+ // Only render declaration for import specifier when the dependency is conditional
349
+ if (connection && !connection.isTargetActive(runtime)) {
350
+ initFragments.push(
351
+ new InitFragment(
352
+ `/* unused harmony import specifier */ var ${dep.name};\n`,
353
+ InitFragment.STAGE_HARMONY_IMPORTS,
354
+ 0,
355
+ `unused import specifier ${dep.name}`
356
+ )
357
+ );
358
+
359
+ return;
360
+ }
343
361
 
344
362
  const ids = dep.getIds(moduleGraph);
345
363
  const {
@@ -431,6 +449,7 @@ HarmonyImportSpecifierDependency.Template = class HarmonyImportSpecifierDependen
431
449
  const { moduleGraph, module, runtime, concatenationScope } =
432
450
  templateContext;
433
451
  const connection = moduleGraph.getConnection(dep);
452
+ /** @type {string} */
434
453
  let exportExpr;
435
454
  if (
436
455
  connection &&
@@ -67,6 +67,7 @@ class ImportDependency extends ModuleDependency {
67
67
  */
68
68
  getReferencedExports(moduleGraph, runtime) {
69
69
  if (!this.referencedExports) return Dependency.EXPORTS_OBJECT_REFERENCED;
70
+ /** @type {ReferencedExports} */
70
71
  const refs = [];
71
72
  for (const referencedExport of this.referencedExports) {
72
73
  if (referencedExport[0] === "default") {
@@ -84,6 +84,7 @@ module.exports = class ImportMetaContextDependencyParserPlugin {
84
84
  );
85
85
  if (!requestExpr.isString()) return;
86
86
  const request = /** @type {string} */ (requestExpr.string);
87
+ /** @type {WebpackError[]} */
87
88
  const errors = [];
88
89
  let regExp = /^\.\/.*$/;
89
90
  let recursive = true;