webpack 5.110.2 → 5.111.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (226) hide show
  1. package/README.md +5 -2
  2. package/lib/APIPlugin.js +23 -7
  3. package/lib/AutomaticPrefetchPlugin.js +1 -1
  4. package/lib/Cache.js +8 -3
  5. package/lib/CacheFacade.js +1 -1
  6. package/lib/ChunkGraph.js +20 -18
  7. package/lib/CircularModulesPlugin.js +157 -55
  8. package/lib/CleanPlugin.js +2 -2
  9. package/lib/Compilation.js +321 -303
  10. package/lib/Compiler.js +209 -46
  11. package/lib/ConcatenationScope.js +25 -35
  12. package/lib/ContextModule.js +17 -81
  13. package/lib/ContextModuleFactory.js +1 -1
  14. package/lib/CopyPlugin.js +1054 -0
  15. package/lib/DefinePlugin.js +24 -8
  16. package/lib/DotenvPlugin.js +41 -13
  17. package/lib/ExternalModule.js +41 -14
  18. package/lib/FileSystemInfo.js +17 -14
  19. package/lib/FlagDependencyExportsPlugin.js +45 -21
  20. package/lib/FlagDependencyUsagePlugin.js +8 -2
  21. package/lib/HotModuleReplacementPlugin.js +53 -7
  22. package/lib/JavascriptMetaInfoPlugin.js +5 -3
  23. package/lib/MainTemplate.js +5 -1
  24. package/lib/Module.js +16 -7
  25. package/lib/MultiCompiler.js +1 -1
  26. package/lib/MultiWatching.js +1 -1
  27. package/lib/NormalModule.js +58 -32
  28. package/lib/NormalModuleFactory.js +1 -1
  29. package/lib/RuntimeGlobals.js +21 -7
  30. package/lib/RuntimeModule.js +28 -12
  31. package/lib/RuntimePlugin.js +33 -3
  32. package/lib/RuntimeTemplate.js +794 -477
  33. package/lib/SourceMapDevToolPlugin.js +1 -1
  34. package/lib/Watching.js +9 -0
  35. package/lib/WebpackOptionsApply.js +84 -91
  36. package/lib/asset/AssetGenerator.js +25 -8
  37. package/lib/asset/AssetModule.js +3 -0
  38. package/lib/asset/WebManifestParser.js +7 -5
  39. package/lib/async-modules/AsyncModuleHelpers.js +10 -4
  40. package/lib/cache/AddBuildDependenciesPlugin.js +33 -4
  41. package/lib/cache/IdleFileCachePlugin.js +2 -2
  42. package/lib/cache/PackFileCacheStrategy.js +14 -1
  43. package/lib/config/browserslistTargetHandler.js +19 -0
  44. package/lib/config/defaults.js +110 -64
  45. package/lib/config/normalization.js +100 -20
  46. package/lib/config/target.js +10 -0
  47. package/lib/container/ContainerReferencePlugin.js +6 -0
  48. package/lib/container/RemoteRuntimeModule.js +9 -0
  49. package/lib/container/declaredRemotes.js +39 -0
  50. package/lib/css/CssGenerator.js +8 -0
  51. package/lib/css/CssInjectStyleRuntimeModule.js +9 -0
  52. package/lib/css/CssLoadingRuntimeModule.js +94 -36
  53. package/lib/css/CssModule.js +1 -1
  54. package/lib/css/CssModulesPlugin.js +7 -6
  55. package/lib/css/CssParser.js +144 -11
  56. package/lib/css/CssServerStylesRuntimeModule.js +9 -0
  57. package/lib/css/cssMinify.js +11 -3
  58. package/lib/css/data.js +2814 -678
  59. package/lib/css/syntax.js +4082 -248
  60. package/lib/debug/ProfilingPlugin.js +4 -0
  61. package/lib/dependencies/AMDDefineDependencyParserPlugin.js +6 -3
  62. package/lib/dependencies/AMDRuntimeModules.js +18 -0
  63. package/lib/dependencies/CommonJsExportRequireDependency.js +3 -1
  64. package/lib/dependencies/CommonJsExportsParserPlugin.js +12 -13
  65. package/lib/dependencies/CommonJsImportsParserPlugin.js +1 -0
  66. package/lib/dependencies/CommonJsPlugin.js +19 -3
  67. package/lib/dependencies/CommonJsRequireDependency.js +32 -9
  68. package/lib/dependencies/ContextDependencyTemplateAsRequireCall.js +20 -7
  69. package/lib/dependencies/CssIcssExportDependency.js +7 -1
  70. package/lib/dependencies/HarmonyCompatibilityDependency.js +58 -4
  71. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +8 -3
  72. package/lib/dependencies/HarmonyExportExpressionDependency.js +44 -29
  73. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +171 -32
  74. package/lib/dependencies/HarmonyExportInitFragment.js +99 -19
  75. package/lib/dependencies/HarmonyExportSpecifierDependency.js +18 -30
  76. package/lib/dependencies/HarmonyImportBareSideEffectDependency.js +59 -0
  77. package/lib/dependencies/HarmonyImportDependency.js +99 -41
  78. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +20 -3
  79. package/lib/dependencies/HarmonyImportSpecifierDependency.js +24 -1
  80. package/lib/dependencies/HarmonyModulesPlugin.js +20 -0
  81. package/lib/dependencies/HtmlEntryDependency.js +62 -2
  82. package/lib/dependencies/ImportContextDependency.js +43 -3
  83. package/lib/dependencies/ImportDependency.js +8 -29
  84. package/lib/dependencies/ImportMetaMainDependency.js +104 -0
  85. package/lib/dependencies/ImportMetaPlugin.js +59 -15
  86. package/lib/dependencies/ImportParserPlugin.js +24 -14
  87. package/lib/dependencies/RequireHeaderDependency.js +20 -21
  88. package/lib/dependencies/SystemRuntimeModule.js +9 -0
  89. package/lib/dependencies/WorkerDependency.js +1 -2
  90. package/lib/dependencies/WorkletDependency.js +1 -2
  91. package/lib/dependencies/importOptionsCheck.js +47 -0
  92. package/lib/dll/DelegatedModule.js +18 -1
  93. package/lib/dll/DllReferencePlugin.js +11 -8
  94. package/lib/dll/LibManifestPlugin.js +1 -1
  95. package/lib/errors/AnalyzableBailoutsWarning.js +41 -0
  96. package/lib/errors/DotenvFileError.js +29 -0
  97. package/lib/errors/DuplicateModulesWarning.js +12 -7
  98. package/lib/errors/EmptyCopyPatternWarning.js +26 -0
  99. package/lib/errors/ExternalStarReexportError.js +44 -0
  100. package/lib/errors/ImportedBindingAssignmentError.js +30 -0
  101. package/lib/errors/MissingSourceMapsWarning.js +36 -0
  102. package/lib/errors/ModuleParseError.js +2 -1
  103. package/lib/errors/UnusedAssetsWarning.js +36 -0
  104. package/lib/errors/UnusedFederationWarning.js +35 -0
  105. package/lib/errors/UnusedModulesWarning.js +38 -0
  106. package/lib/esm/ExportWebpackRequireRuntimeModule.js +9 -0
  107. package/lib/esm/ModuleChunkFormatPlugin.js +28 -3
  108. package/lib/esm/ModuleChunkLoadingPlugin.js +30 -11
  109. package/lib/esm/ModuleChunkLoadingRuntimeModule.js +92 -60
  110. package/lib/hmr/HotModuleReplacement.runtime.js +8 -2
  111. package/lib/hmr/HotModuleReplacementRuntimeModule.js +9 -0
  112. package/lib/html/HtmlGenerator.js +11 -5
  113. package/lib/html/HtmlModulesPlugin.js +360 -84
  114. package/lib/html/HtmlParser.js +13 -6
  115. package/lib/html/builtinEmbeddedRenderer.js +107 -0
  116. package/lib/html/data.js +121 -7
  117. package/lib/html/htmlMinify.js +84 -113
  118. package/lib/html/syntax.js +1067 -569
  119. package/lib/ids/HashedModuleIdsPlugin.js +2 -1
  120. package/lib/index.js +3 -0
  121. package/lib/javascript/JavascriptModule.js +1 -0
  122. package/lib/javascript/JavascriptModulesPlugin.js +52 -22
  123. package/lib/javascript/JavascriptParser.js +1255 -728
  124. package/lib/javascript/StartupHelpers.js +27 -3
  125. package/lib/javascript/data.js +172 -0
  126. package/lib/javascript/grammar.js +5546 -0
  127. package/lib/javascript/parser.js +1494 -0
  128. package/lib/javascript/regexp.js +1762 -0
  129. package/lib/javascript/regexpData.js +51 -0
  130. package/lib/javascript/syntax.js +8696 -5225
  131. package/lib/library/ModuleLibraryPlugin.js +116 -5
  132. package/lib/node/ReadFileChunkLoadingRuntimeModule.js +22 -0
  133. package/lib/node/RequireChunkLoadingRuntimeModule.js +22 -0
  134. package/lib/optimize/ConcatenatedModule.js +133 -25
  135. package/lib/optimize/ConstExportsPlugin.js +50 -39
  136. package/lib/optimize/InlineExports.js +20 -123
  137. package/lib/optimize/MangleExportsPlugin.js +10 -0
  138. package/lib/optimize/ModuleConcatenationPlugin.js +24 -1
  139. package/lib/optimize/RealContentHashPlugin.js +68 -9
  140. package/lib/optimize/SideEffectsFlagPlugin.js +17 -9
  141. package/lib/performance/AnalyzableBailoutsPlugin.js +115 -0
  142. package/lib/performance/CacheEffectivenessPlugin.js +4 -3
  143. package/lib/performance/DuplicateModulesPlugin.js +57 -13
  144. package/lib/performance/EvalUsagePlugin.js +5 -2
  145. package/lib/performance/MissingSourceMapsPlugin.js +115 -0
  146. package/lib/performance/PureAnnotationsPlugin.js +6 -3
  147. package/lib/performance/TopLevelThisPlugin.js +5 -4
  148. package/lib/performance/UnusedAssetsPlugin.js +109 -0
  149. package/lib/performance/UnusedFederationPlugin.js +147 -0
  150. package/lib/performance/UnusedModulesPlugin.js +141 -0
  151. package/lib/performance/UnusedReexportsPlugin.js +1 -55
  152. package/lib/performance/isOnlyReexported.js +65 -0
  153. package/lib/prefetch/ChunkPrefetchFunctionRuntimeModule.js +25 -5
  154. package/lib/prefetch/ChunkPrefetchPreloadPlugin.js +2 -0
  155. package/lib/prefetch/ChunkPrefetchStartupRuntimeModule.js +9 -0
  156. package/lib/prefetch/ChunkPrefetchTriggerRuntimeModule.js +9 -0
  157. package/lib/prefetch/ChunkPreloadTriggerRuntimeModule.js +9 -0
  158. package/lib/prefetch/ResourceHintPlugin.js +7 -3
  159. package/lib/prefetch/ResourceHintRuntimeModule.js +9 -0
  160. package/lib/prefetch/StartupAssetHintRuntimeModule.js +9 -0
  161. package/lib/rules/RuleSetCompiler.js +211 -4
  162. package/lib/runtime/AsyncModuleRuntimeModule.js +105 -67
  163. package/lib/runtime/AutoPublicPathRuntimeModule.js +9 -0
  164. package/lib/runtime/BaseUriRuntimeModule.js +9 -0
  165. package/lib/runtime/ChunkNameRuntimeModule.js +9 -0
  166. package/lib/runtime/EnsureChunkRuntimeModule.js +35 -16
  167. package/lib/runtime/GetChunkFilenameRuntimeModule.js +9 -0
  168. package/lib/runtime/GetFullHashRuntimeModule.js +9 -0
  169. package/lib/runtime/GetMainFilenameRuntimeModule.js +9 -0
  170. package/lib/runtime/GetWorkletBootstrapRuntimeModule.js +9 -0
  171. package/lib/runtime/GlobalRuntimeModule.js +9 -0
  172. package/lib/runtime/HasOwnPropertyRuntimeModule.js +9 -0
  173. package/lib/runtime/HelperRuntimeModule.js +10 -0
  174. package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +338 -217
  175. package/lib/runtime/NonceRuntimeModule.js +9 -0
  176. package/lib/runtime/OnChunksLoadedRuntimeModule.js +67 -20
  177. package/lib/runtime/PublicPathRuntimeModule.js +9 -0
  178. package/lib/runtime/RuntimeIdRuntimeModule.js +9 -0
  179. package/lib/runtime/SpecNamespaceObjectRuntimeModule.js +90 -0
  180. package/lib/runtime/StartupChunkDependenciesRuntimeModule.js +9 -0
  181. package/lib/runtime/StartupEntrypointRuntimeModule.js +9 -0
  182. package/lib/runtime/SystemContextRuntimeModule.js +9 -0
  183. package/lib/runtime/ToBinaryRuntimeModule.js +9 -0
  184. package/lib/schemes/HttpUriPlugin.js +22 -5
  185. package/lib/serialization/FileMiddleware.js +15 -2
  186. package/lib/serialization/ObjectMiddleware.js +138 -106
  187. package/lib/sharing/ConsumeSharedPlugin.js +12 -0
  188. package/lib/sharing/ConsumeSharedRuntimeModule.js +11 -0
  189. package/lib/sharing/ShareRuntimeModule.js +9 -0
  190. package/lib/sharing/declaredShared.js +47 -0
  191. package/lib/stats/DefaultStatsFactoryPlugin.js +3 -1
  192. package/lib/stats/DefaultStatsPrinterPlugin.js +3 -0
  193. package/lib/util/ArrayQueue.js +3 -3
  194. package/lib/util/SourceProcessor.js +76 -69
  195. package/lib/util/URLAbsoluteSpecifier.js +3 -1
  196. package/lib/util/async.js +292 -0
  197. package/lib/util/buildDiagnostics.js +69 -0
  198. package/lib/util/conventions.js +5 -1
  199. package/lib/util/fs.js +27 -1
  200. package/lib/util/handlerKeys.js +40 -0
  201. package/lib/util/identifier.js +20 -0
  202. package/lib/util/internalSerializables.js +6 -0
  203. package/lib/util/registerExternalSerializer.js +6 -45
  204. package/lib/wasm-async/AsyncWasmCompileRuntimeModule.js +9 -0
  205. package/lib/wasm-async/AsyncWasmLoadingRuntimeModule.js +9 -0
  206. package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +9 -0
  207. package/lib/web/JsonpChunkLoadingRuntimeModule.js +36 -0
  208. package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +19 -0
  209. package/package.json +22 -16
  210. package/schemas/WebpackOptions.check.js +1 -1
  211. package/schemas/WebpackOptions.json +388 -76
  212. package/schemas/plugins/LoaderOptionsPlugin.check.js +1 -1
  213. package/schemas/plugins/ManifestPlugin.check.js +1 -1
  214. package/schemas/plugins/SourceMapDevToolPlugin.check.js +1 -1
  215. package/schemas/plugins/asset/AssetGeneratorOptions.check.js +1 -1
  216. package/schemas/plugins/asset/AssetResourceGeneratorOptions.check.js +1 -1
  217. package/schemas/plugins/container/ContainerPlugin.check.js +1 -1
  218. package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
  219. package/schemas/plugins/debug/ProfilingPlugin.check.js +1 -1
  220. package/schemas/plugins/dll/DllReferencePlugin.check.js +1 -1
  221. package/schemas/plugins/ids/HashedModuleIdsPlugin.check.js +1 -1
  222. package/schemas/plugins/schemes/HttpUriPlugin.check.js +1 -1
  223. package/types.d.ts +1440 -331
  224. package/lib/dependencies/ExportBindingInitFragment.js +0 -191
  225. package/lib/errors/EntrypointOverlapWarning.js +0 -45
  226. package/lib/performance/EntrypointOverlapPlugin.js +0 -122
@@ -11,11 +11,14 @@ const InitFragment = require("../InitFragment");
11
11
  const Template = require("../Template");
12
12
  const AwaitDependenciesInitFragment = require("../async-modules/AwaitDependenciesInitFragment");
13
13
  const isGeneratorLowered = require("../async-modules/isGeneratorLowered");
14
+ const memoize = require("../util/memoize");
14
15
  const { filterRuntime, mergeRuntime } = require("../util/runtime");
15
16
  const HarmonyLinkingError = require("./HarmonyLinkingError");
16
17
  const { ImportPhase, ImportPhaseUtils } = require("./ImportPhase");
17
18
  const ModuleDependency = require("./ModuleDependency");
18
19
 
20
+ const getExternalModule = memoize(() => require("../ExternalModule"));
21
+
19
22
  /** @import { ReplaceSource } from "webpack-sources" */
20
23
  /**
21
24
  * @import {
@@ -97,6 +100,36 @@ const getNonOptionalPart = (members, membersOptionals) => {
97
100
 
98
101
  /** @typedef {string[]} Ids */
99
102
 
103
+ /**
104
+ * Export names a lazy barrel still defers, so they are missing from its provided
105
+ * exports without being absent from the module.
106
+ * @param {Module} module the imported module
107
+ * @returns {Set<string> | true | undefined} deferred names, true when a deferred star re-export may provide any name, undefined when none
108
+ */
109
+ const getDeferredExports = (module) => {
110
+ const factoryMeta = module.factoryMeta;
111
+ if (factoryMeta === undefined || !factoryMeta.sideEffectFree) return;
112
+ /** @type {Set<string> | undefined} */
113
+ let names;
114
+ for (const dep of module.dependencies) {
115
+ // TODO remove in webpack 6
116
+ // These may be missing on custom dependency types not extending the base Dependency
117
+ if (
118
+ typeof dep.getLazyUntil !== "function" ||
119
+ typeof dep.isLazy !== "function"
120
+ ) {
121
+ continue;
122
+ }
123
+ if (!dep.isLazy()) continue;
124
+ const until = dep.getLazyUntil();
125
+ if (until === Dependency.LAZY_UNTIL_FALLBACK) return true;
126
+ if (until !== Dependency.LAZY_UNTIL_ID) continue;
127
+ if (names === undefined) names = new Set();
128
+ names.add(/** @type {string} */ (dep.getLazyName()));
129
+ }
130
+ return names;
131
+ };
132
+
100
133
  class HarmonyImportDependency extends ModuleDependency {
101
134
  /**
102
135
  * Creates an instance of HarmonyImportDependency.
@@ -185,9 +218,14 @@ class HarmonyImportDependency extends ModuleDependency {
185
218
  const importedModule = /** @type {Module} */ (moduleGraph.getModule(this));
186
219
  const meta = moduleGraph.getMeta(module);
187
220
 
221
+ // An async external is a promise webpack awaits, not a module record with
222
+ // an evaluating state, so deferring its namespace would never throw.
188
223
  const isDeferred =
189
224
  ImportPhaseUtils.isDefer(this.phase) &&
190
- !(/** @type {BuildMeta} */ (importedModule.buildMeta).async);
225
+ !(
226
+ /** @type {BuildMeta} */ (importedModule.buildMeta).async &&
227
+ importedModule instanceof getExternalModule()
228
+ );
191
229
 
192
230
  const metaKey = isDeferred ? "deferredImportVarMap" : "importVarMap";
193
231
  let importVarMap = meta[metaKey];
@@ -283,48 +321,63 @@ class HarmonyImportDependency extends ModuleDependency {
283
321
  (exportsType !== "default-with-named" || ids[0] !== "default") &&
284
322
  moduleGraph.isExportProvided(importedModule, ids) === false
285
323
  ) {
286
- // We are sure that it's not provided
287
-
288
- // Try to provide detailed info in the error message
289
- let pos = 0;
290
- let exportsInfo = moduleGraph.getExportsInfo(importedModule);
291
- while (pos < ids.length && exportsInfo) {
292
- const id = ids[pos++];
293
- const exportInfo = exportsInfo.getReadOnlyExportInfo(id);
294
- if (exportInfo.provided === false) {
295
- // We are sure that it's not provided
296
- const providedExports = exportsInfo.getProvidedExports();
297
- const moreInfo = !Array.isArray(providedExports)
298
- ? " (possible exports unknown)"
299
- : providedExports.length === 0
300
- ? " (module has no exports)"
301
- : ` (possible exports: ${providedExports.join(", ")})`;
302
- return [
303
- new HarmonyLinkingError(
304
- `export ${ids
305
- .slice(0, pos)
306
- .map((id) => `'${id}'`)
307
- .join(".")} ${additionalMessage} was not found in '${
308
- this.userRequest
309
- }'${moreInfo}`
310
- )
311
- ];
324
+ const deferredExports = getDeferredExports(importedModule);
325
+
326
+ if (
327
+ deferredExports !== true &&
328
+ (deferredExports === undefined || !deferredExports.has(ids[0]))
329
+ ) {
330
+ // We are sure that it's not provided
331
+
332
+ // Try to provide detailed info in the error message
333
+ let pos = 0;
334
+ let exportsInfo = moduleGraph.getExportsInfo(importedModule);
335
+ while (pos < ids.length && exportsInfo) {
336
+ const id = ids[pos++];
337
+ const exportInfo = exportsInfo.getReadOnlyExportInfo(id);
338
+ if (exportInfo.provided === false) {
339
+ // We are sure that it's not provided
340
+ let providedExports = exportsInfo.getProvidedExports();
341
+ // only the first level names the imported module itself
342
+ if (
343
+ pos === 1 &&
344
+ deferredExports !== undefined &&
345
+ Array.isArray(providedExports)
346
+ ) {
347
+ providedExports = [...providedExports, ...deferredExports];
348
+ }
349
+ const moreInfo = !Array.isArray(providedExports)
350
+ ? " (possible exports unknown)"
351
+ : providedExports.length === 0
352
+ ? " (module has no exports)"
353
+ : ` (possible exports: ${providedExports.join(", ")})`;
354
+ return [
355
+ new HarmonyLinkingError(
356
+ `export ${ids
357
+ .slice(0, pos)
358
+ .map((id) => `'${id}'`)
359
+ .join(".")} ${additionalMessage} was not found in '${
360
+ this.userRequest
361
+ }'${moreInfo}`
362
+ )
363
+ ];
364
+ }
365
+ exportsInfo =
366
+ /** @type {ExportsInfo} */
367
+ (exportInfo.getNestedExportsInfo());
312
368
  }
313
- exportsInfo =
314
- /** @type {ExportsInfo} */
315
- (exportInfo.getNestedExportsInfo());
316
- }
317
369
 
318
- // General error message
319
- return [
320
- new HarmonyLinkingError(
321
- `export ${ids
322
- .map((id) => `'${id}'`)
323
- .join(".")} ${additionalMessage} was not found in '${
324
- this.userRequest
325
- }'`
326
- )
327
- ];
370
+ // General error message
371
+ return [
372
+ new HarmonyLinkingError(
373
+ `export ${ids
374
+ .map((id) => `'${id}'`)
375
+ .join(".")} ${additionalMessage} was not found in '${
376
+ this.userRequest
377
+ }'`
378
+ )
379
+ ];
380
+ }
328
381
  }
329
382
  }
330
383
  switch (exportsType) {
@@ -468,8 +521,13 @@ HarmonyImportDependency.Template = class HarmonyImportDependencyTemplate extends
468
521
  }
469
522
 
470
523
  const importStatement = dep.getImportStatement(false, templateContext);
524
+ // A module deferring itself is already evaluating: awaiting it would probe
525
+ // the deferred namespace and force the evaluation it must not trigger.
526
+ const isSelfDeferred =
527
+ ImportPhaseUtils.isDefer(dep.phase) && referencedModule === module;
471
528
  if (
472
529
  referencedModule &&
530
+ !isSelfDeferred &&
473
531
  templateContext.moduleGraph.isAsync(referencedModule)
474
532
  ) {
475
533
  templateContext.initFragments.push(
@@ -5,6 +5,7 @@
5
5
 
6
6
  "use strict";
7
7
 
8
+ const ImportedBindingAssignmentError = require("../errors/ImportedBindingAssignmentError");
8
9
  const WebpackError = require("../errors/WebpackError");
9
10
  const getParserHooks = require("../hmr/parserHooks");
10
11
  const {
@@ -17,6 +18,7 @@ const HarmonyAcceptDependency = require("./HarmonyAcceptDependency");
17
18
  const HarmonyAcceptImportDependency = require("./HarmonyAcceptImportDependency");
18
19
  const HarmonyEvaluatedImportSpecifierDependency = require("./HarmonyEvaluatedImportSpecifierDependency");
19
20
  const HarmonyExports = require("./HarmonyExports");
21
+ const HarmonyImportBareSideEffectDependency = require("./HarmonyImportBareSideEffectDependency");
20
22
  const {
21
23
  ExportPresenceModes,
22
24
  getNonOptionalPart
@@ -310,7 +312,13 @@ class HarmonyImportDependencyParserPlugin {
310
312
  parser.state.current.addError(error);
311
313
  }
312
314
 
313
- const sideEffectDep = new HarmonyImportSideEffectDependency(
315
+ // A declaration binding nothing was written for what importing produces,
316
+ // which for a module emitting its own file is that file.
317
+ const SideEffectDependency =
318
+ statement.specifiers.length === 0
319
+ ? HarmonyImportBareSideEffectDependency
320
+ : HarmonyImportSideEffectDependency;
321
+ const sideEffectDep = new SideEffectDependency(
314
322
  /** @type {string} */ (source),
315
323
  parser.state.lastHarmonyImportOrder,
316
324
  phase,
@@ -393,11 +401,20 @@ class HarmonyImportDependencyParserPlugin {
393
401
  );
394
402
  // Concatenation would turn the binding into a plain local, losing the
395
403
  // getter-only property whose write throws.
396
- parser.hooks.assign.for(harmonySpecifierTag).tap(PLUGIN_NAME, () => {
397
- markUsed(/** @type {HarmonySettings} */ (parser.currentTagData));
404
+ parser.hooks.assign.for(harmonySpecifierTag).tap(PLUGIN_NAME, (expr) => {
405
+ const settings = /** @type {HarmonySettings} */ (parser.currentTagData);
406
+ markUsed(settings);
398
407
  /** @type {JavascriptModuleBuildInfo} */
399
408
  (parser.state.module.buildInfo).moduleConcatenationBailout =
400
409
  "assignment to an imported binding";
410
+ // A named import is written through the namespace's getter-only
411
+ // property, which throws on its own. A namespace one is the binding
412
+ // itself, and nothing webpack can emit for it throws, so report it.
413
+ if (settings.ids.length === 0) {
414
+ const error = new ImportedBindingAssignmentError(settings.name);
415
+ error.loc = parser.getLocation(expr);
416
+ parser.state.module.addError(error);
417
+ }
401
418
  });
402
419
  parser.hooks.expression
403
420
  .for(harmonySpecifierTag)
@@ -26,10 +26,11 @@ const HarmonyImportGuard = require("./HarmonyImportGuard");
26
26
  const { ImportPhaseUtils } = require("./ImportPhase");
27
27
 
28
28
  /** @import { ReplaceSource } from "webpack-sources" */
29
- /** @import { GetConditionFn, ReferencedExports } from "../Dependency" */
29
+ /** @import { GetConditionFn, ReferencedExports, UpdateHashContext } from "../Dependency" */
30
30
  /** @import { DependencyTemplateContext } from "../DependencyTemplate" */
31
31
  /** @import Module, { BuildMeta } from "../Module" */
32
32
  /** @import ModuleGraph from "../ModuleGraph" */
33
+ /** @import Hash from "../util/Hash" */
33
34
  /**
34
35
  * @import ModuleGraphConnection, {
35
36
  * ConnectionState
@@ -262,6 +263,28 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency {
262
263
  return condition;
263
264
  }
264
265
 
266
+ /**
267
+ * Updates the hash with the data contributed by this instance.
268
+ * @param {Hash} hash hash to be updated
269
+ * @param {UpdateHashContext} context context
270
+ * @returns {void}
271
+ */
272
+ updateHash(hash, context) {
273
+ const { chunkGraph, runtime } = context;
274
+ const moduleGraph = chunkGraph.moduleGraph;
275
+ if (!isInlineExportsEnabled(moduleGraph)) return;
276
+ const module = moduleGraph.getModule(this);
277
+ if (!module || !isInlineEnabled(module)) return;
278
+ const ids = this.getIds(moduleGraph);
279
+ if (ids.length === 0) return;
280
+ const exportsInfo = moduleGraph.getExportsInfo(module);
281
+ if (!exportsInfo.hasInlinedUsedName(ids, runtime)) return;
282
+ const usedName = exportsInfo.getUsedName(ids, runtime);
283
+ if (usedName instanceof InlinedUsedName) {
284
+ usedName.updateHash(hash);
285
+ }
286
+ }
287
+
265
288
  /**
266
289
  * Gets module evaluation side effects state.
267
290
  * @param {ModuleGraph} moduleGraph the module graph
@@ -20,6 +20,7 @@ const HarmonyExportExpressionDependency = require("./HarmonyExportExpressionDepe
20
20
  const HarmonyExportHeaderDependency = require("./HarmonyExportHeaderDependency");
21
21
  const HarmonyExportImportedSpecifierDependency = require("./HarmonyExportImportedSpecifierDependency");
22
22
  const HarmonyExportSpecifierDependency = require("./HarmonyExportSpecifierDependency");
23
+ const HarmonyImportBareSideEffectDependency = require("./HarmonyImportBareSideEffectDependency");
23
24
  const HarmonyImportDependencyParserPlugin = require("./HarmonyImportDependencyParserPlugin");
24
25
  const HarmonyImportSideEffectDependency = require("./HarmonyImportSideEffectDependency");
25
26
  const HarmonyImportSpecifierDependency = require("./HarmonyImportSpecifierDependency");
@@ -34,6 +35,7 @@ const TopLevelAwaitDependency = require("./TopLevelAwaitDependency");
34
35
  */
35
36
  /** @import Compiler from "../Compiler" */
36
37
  /** @import Parser from "../javascript/JavascriptParser" */
38
+ /** @import { BuildInfo } from "../Module" */
37
39
 
38
40
  /**
39
41
  * Defines the harmony modules plugin options type used by this module.
@@ -81,6 +83,15 @@ class HarmonyModulesPlugin {
81
83
  new HarmonyImportSideEffectDependency.Template()
82
84
  );
83
85
 
86
+ compilation.dependencyFactories.set(
87
+ HarmonyImportBareSideEffectDependency,
88
+ normalModuleFactory
89
+ );
90
+ compilation.dependencyTemplates.set(
91
+ HarmonyImportBareSideEffectDependency,
92
+ new HarmonyImportBareSideEffectDependency.Template()
93
+ );
94
+
84
95
  compilation.dependencyFactories.set(
85
96
  HarmonyImportSpecifierDependency,
86
97
  normalModuleFactory
@@ -149,6 +160,15 @@ class HarmonyModulesPlugin {
149
160
  return;
150
161
  }
151
162
 
163
+ if (parserOptions.specNamespaceObject) {
164
+ // Recorded on the module, because an importer asks the module it
165
+ // imports whether its namespace is a spec exotic object.
166
+ parser.hooks.program.tap(PLUGIN_NAME, () => {
167
+ /** @type {BuildInfo} */
168
+ (parser.state.module.buildInfo).specNamespaceObject = true;
169
+ });
170
+ }
171
+
152
172
  new HarmonyDetectionParserPlugin().apply(parser);
153
173
  new HarmonyImportDependencyParserPlugin(parserOptions).apply(parser);
154
174
  new HarmonyExportDependencyParserPlugin(parserOptions).apply(parser);
@@ -7,6 +7,7 @@
7
7
  const {
8
8
  CSS_IMPORT_TYPE,
9
9
  CSS_TYPE,
10
+ HTML_TYPE,
10
11
  JAVASCRIPT_TYPE
11
12
  } = require("../ModuleSourceTypeConstants");
12
13
  const ResourceHintPlugin = require("../prefetch/ResourceHintPlugin");
@@ -194,7 +195,12 @@ const getEntrypointChunksInLoadOrder = (entrypoint) => {
194
195
  const chunksLoadedByAncestorTags = new Set();
195
196
  /** @type {Set<import("../ChunkGroup")>} */
196
197
  const visitedGroups = new Set();
197
- const walk = (/** @type {import("../ChunkGroup")} */ group) => {
198
+ /**
199
+ * Collects the chunks an ancestor entry's own tags already load.
200
+ * @param {import("../ChunkGroup")} group chunk group to walk up from
201
+ * @returns {void}
202
+ */
203
+ const walk = (group) => {
198
204
  if (visitedGroups.has(group)) return;
199
205
  visitedGroups.add(group);
200
206
  for (const parent of group.parentsIterable) {
@@ -220,7 +226,12 @@ const getEntrypointChunksInLoadOrder = (entrypoint) => {
220
226
  const ordered = [];
221
227
  /** @type {Set<Chunk>} */
222
228
  const seen = new Set();
223
- const push = (/** @type {Chunk | null | undefined} */ chunk) => {
229
+ /**
230
+ * Appends a chunk once, skipping the ones an ancestor entry already loads.
231
+ * @param {Chunk | null | undefined} chunk chunk to append
232
+ * @returns {void}
233
+ */
234
+ const push = (chunk) => {
224
235
  if (!chunk || seen.has(chunk) || chunk === entryChunk) return;
225
236
  if (chunksLoadedByAncestorTags.has(chunk)) return;
226
237
  seen.add(chunk);
@@ -577,6 +588,47 @@ const buildLinkTag = (rel, attrs) =>
577
588
  : ""
578
589
  }>`;
579
590
 
591
+ /**
592
+ * The chunks a hint means when it names a page: a page loads no JavaScript of
593
+ * its own, so the hint follows the entries the parser extracted from it.
594
+ * @param {import("../Compilation")} compilation compilation
595
+ * @param {Chunk} chunk chunk a hint resolved to
596
+ * @returns {Chunk[]} the chunks to hint at
597
+ */
598
+ const resolvePageChunk = (compilation, chunk) => {
599
+ const { chunkGraph } = compilation;
600
+ const modules = chunkGraph.getChunkModulesIterableBySourceType(
601
+ chunk,
602
+ HTML_TYPE
603
+ );
604
+ // A page with a JavaScript side of its own (an `output.library` entry) is
605
+ // hinted too — `chunkHasJs` can't say so, it holds for any runtime chunk.
606
+ const javascript = chunkGraph.getChunkModulesIterableBySourceType(
607
+ chunk,
608
+ JAVASCRIPT_TYPE
609
+ );
610
+ /** @type {Chunk[]} */
611
+ const chunks = javascript === undefined ? [] : [chunk];
612
+ // A chunk carrying no page stands for itself; a page stands for the entries
613
+ // extracted from it, so one that extracted nothing hints nothing.
614
+ if (modules === undefined) return chunks.length === 0 ? [chunk] : chunks;
615
+ for (const module of modules) {
616
+ const { htmlEntries } =
617
+ /** @type {import("../html/HtmlModule").HtmlModuleBuildInfo} */ (
618
+ module.buildInfo
619
+ ) || {};
620
+ if (!htmlEntries) continue;
621
+ for (const group of Object.values(htmlEntries)) {
622
+ for (const { entryName } of group) {
623
+ const entrypoint = compilation.entrypoints.get(entryName);
624
+ const entryChunk = entrypoint && entrypoint.getEntrypointChunk();
625
+ if (entryChunk) chunks.push(entryChunk);
626
+ }
627
+ }
628
+ }
629
+ return chunks;
630
+ };
631
+
580
632
  /**
581
633
  * Resolve one `output.html.resourceHints` descriptor to zero or more `<link>`
582
634
  * tags. A `chunk`/`entry` reference becomes the emitted chunk URL (a sentinel
@@ -623,6 +675,14 @@ const resolveResourceHint = (desc, ctx) => {
623
675
  } else {
624
676
  return [];
625
677
  }
678
+ /** @type {Chunk[]} */
679
+ const hinted = [];
680
+ for (const chunk of chunks) {
681
+ for (const resolved of resolvePageChunk(ctx.compilation, chunk)) {
682
+ hinted.push(resolved);
683
+ }
684
+ }
685
+ chunks = hinted;
626
686
  const kind = desc.as === "style" ? "css" : "javascript";
627
687
  const as = desc.as || (rel === "modulepreload" ? undefined : "script");
628
688
  // A hint targeting another chunk must match how that chunk is fetched, so
@@ -8,11 +8,13 @@
8
8
  const makeSerializable = require("../util/makeSerializable");
9
9
  const ContextDependency = require("./ContextDependency");
10
10
  const ContextDependencyTemplateAsRequireCall = require("./ContextDependencyTemplateAsRequireCall");
11
+ const importOptionsCheck = require("./importOptionsCheck");
11
12
 
12
13
  /** @import { Range } from "../javascript/JavascriptParser" */
13
- /** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext<[Range]>} ObjectDeserializerContext */
14
- /** @typedef {import("../serialization/ObjectMiddleware").ObjectSerializerContext<[Range]>} ObjectSerializerContext */
14
+ /** @import { ObjectDeserializerContext, ObjectSerializerContext } from "../serialization/ObjectMiddleware" */
15
15
  /** @import { ContextDependencyOptions } from "./ContextDependency" */
16
+ /** @import { ReplaceSource } from "webpack-sources" */
17
+ /** @import { DependencyTemplateContext } from "../DependencyTemplate" */
16
18
 
17
19
  class ImportContextDependency extends ContextDependency {
18
20
  /**
@@ -26,6 +28,8 @@ class ImportContextDependency extends ContextDependency {
26
28
 
27
29
  this.range = range;
28
30
  this.valueRange = valueRange;
31
+ /** @type {Range | undefined} */
32
+ this.optionsRange = undefined;
29
33
  }
30
34
 
31
35
  get type() {
@@ -56,6 +60,7 @@ class ImportContextDependency extends ContextDependency {
56
60
  */
57
61
  serialize(context) {
58
62
  context.write(this.valueRange);
63
+ context.write(this.optionsRange);
59
64
 
60
65
  super.serialize(context);
61
66
  }
@@ -66,6 +71,7 @@ class ImportContextDependency extends ContextDependency {
66
71
  */
67
72
  deserialize(context) {
68
73
  this.valueRange = context.read();
74
+ this.optionsRange = context.read();
69
75
 
70
76
  super.deserialize(context.rest);
71
77
  }
@@ -76,6 +82,40 @@ makeSerializable(
76
82
  "webpack/lib/dependencies/ImportContextDependency"
77
83
  );
78
84
 
79
- ImportContextDependency.Template = ContextDependencyTemplateAsRequireCall;
85
+ ImportContextDependency.Template = class ImportContextDependencyTemplate extends (
86
+ ContextDependencyTemplateAsRequireCall
87
+ ) {
88
+ /**
89
+ * Rewrites the call around its request, dropping anything the original one
90
+ * carried after it. Overridden where a later argument must be kept.
91
+ * @param {ContextDependency} dep the dependency
92
+ * @param {ReplaceSource} source the current replace source which can be modified
93
+ * @param {string} moduleExports the expression the request is passed to
94
+ * @param {DependencyTemplateContext} templateContext the context object
95
+ * @returns {void}
96
+ */
97
+ replaceCall(dep, source, moduleExports, templateContext) {
98
+ const optionsRange = /** @type {ImportContextDependency} */ (dep)
99
+ .optionsRange;
100
+ if (optionsRange === undefined) {
101
+ super.replaceCall(dep, source, moduleExports, templateContext);
102
+ return;
103
+ }
104
+ // Request then options, in that order; their own source is kept so
105
+ // nested dependencies in them still get their replacements.
106
+ const range = /** @type {Range} */ (dep.range);
107
+ const valueRange = /** @type {Range} */ (dep.valueRange);
108
+ const check = importOptionsCheck(
109
+ templateContext.runtimeTemplate,
110
+ ["r", "o"],
111
+ `${moduleExports}(r)`
112
+ );
113
+ source.replace(range[0], valueRange[0] - 1, `(${check})(`);
114
+ // The options range excludes any parentheses the source had, so a comma
115
+ // expression would otherwise split into arguments of its own.
116
+ source.replace(valueRange[1], optionsRange[0] - 1, ", (");
117
+ source.replace(optionsRange[1], range[1] - 1, "))");
118
+ }
119
+ };
80
120
 
81
121
  module.exports = ImportContextDependency;
@@ -6,11 +6,11 @@
6
6
  "use strict";
7
7
 
8
8
  const Dependency = require("../Dependency");
9
- const Template = require("../Template");
10
9
  const makeSerializable = require("../util/makeSerializable");
11
10
  const HarmonyImportGuard = require("./HarmonyImportGuard");
12
11
  const { ImportPhaseUtils } = require("./ImportPhase");
13
12
  const ModuleDependency = require("./ModuleDependency");
13
+ const importOptionsCheck = require("./importOptionsCheck");
14
14
 
15
15
  /** @import { ReplaceSource } from "webpack-sources" */
16
16
  /** @import AsyncDependenciesBlock from "../AsyncDependenciesBlock" */
@@ -226,35 +226,14 @@ ImportDependency.Template = class ImportDependencyTemplate extends (
226
226
  }
227
227
 
228
228
  // A non-static second argument must still be evaluated (for its side
229
- // effects and evaluation order) and validated per spec. Keep it in place
230
- // and wrap it in an inline validator that mirrors the runtime checks of
231
- // the spec's `import(specifier, options)` evaluation.
229
+ // effects and evaluation order) and checked per spec, so keep it in place
230
+ // and wrap it.
232
231
  if (dep.optionsRange) {
233
- const validator = runtimeTemplate.basicFunction("o", [
234
- "try {",
235
- Template.indent([
236
- "if (o !== undefined) {",
237
- Template.indent([
238
- 'if ((typeof o !== "object" && typeof o !== "function") || o === null) throw new TypeError("The second argument to import() must be an object");',
239
- 'var a = o["with"];',
240
- "if (a !== undefined) {",
241
- Template.indent([
242
- 'if ((typeof a !== "object" && typeof a !== "function") || a === null) throw new TypeError("The \'with\' option must be an object");',
243
- "for (var k = Object.keys(a), i = 0; i < k.length; i++) {",
244
- Template.indent([
245
- 'if (typeof a[k[i]] !== "string") throw new TypeError("Import attribute values must be strings");'
246
- ]),
247
- "}"
248
- ]),
249
- "}"
250
- ]),
251
- "}"
252
- ]),
253
- "} catch (e) { return Promise.reject(e); }",
254
- `return ${content};`
255
- ]);
256
- source.replace(dep.range[0], dep.optionsRange[0] - 1, `(${validator})(`);
257
- source.replace(dep.optionsRange[1], dep.range[1] - 1, ")");
232
+ const check = importOptionsCheck(runtimeTemplate, ["o"], content);
233
+ // The options range excludes any parentheses the source had, so a
234
+ // comma expression would otherwise split into arguments of its own.
235
+ source.replace(dep.range[0], dep.optionsRange[0] - 1, `(${check})((`);
236
+ source.replace(dep.optionsRange[1], dep.range[1] - 1, "))");
258
237
  return;
259
238
  }
260
239
 
@@ -0,0 +1,104 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ Author Alexander Akait @alexander-akait
4
+ */
5
+
6
+ "use strict";
7
+
8
+ const makeSerializable = require("../util/makeSerializable");
9
+ const ConstDependency = require("./ConstDependency");
10
+ const NullDependency = require("./NullDependency");
11
+
12
+ /** @import { ReplaceSource } from "webpack-sources" */
13
+ /** @import Dependency, { UpdateHashContext } from "../Dependency" */
14
+ /** @import { DependencyTemplateContext } from "../DependencyTemplate" */
15
+ /** @import { Range } from "../javascript/JavascriptParser" */
16
+ /**
17
+ * @import {
18
+ * ObjectDeserializerContext,
19
+ * ObjectSerializerContext
20
+ * } from "../serialization/ObjectMiddleware"
21
+ */
22
+ /** @import Hash from "../util/Hash" */
23
+
24
+ /**
25
+ * `import.meta.main` asks whether the module is the entry, which needs the
26
+ * module argument scope hoisting removes. An inner concatenated module is
27
+ * never an entry module, so it answers with a separate constant expression.
28
+ */
29
+ class ImportMetaMainDependency extends ConstDependency {
30
+ /**
31
+ * Creates an instance of ImportMetaMainDependency.
32
+ * @param {string} expression the expression a module outside a concatenation evaluates
33
+ * @param {string} concatenatedExpression the expression an inner concatenated module evaluates
34
+ * @param {Range} range the source range
35
+ * @param {(string[] | null)=} runtimeRequirements runtime requirements of `expression`
36
+ */
37
+ constructor(expression, concatenatedExpression, range, runtimeRequirements) {
38
+ super(expression, range, runtimeRequirements);
39
+ /** @type {string} */
40
+ this.concatenatedExpression = concatenatedExpression;
41
+ }
42
+
43
+ /**
44
+ * Updates the hash with the data contributed by this instance.
45
+ * @param {Hash} hash hash to be updated
46
+ * @param {UpdateHashContext} context context
47
+ * @returns {void}
48
+ */
49
+ updateHash(hash, context) {
50
+ super.updateHash(hash, context);
51
+ hash.update(this.concatenatedExpression);
52
+ }
53
+
54
+ /**
55
+ * Serializes this instance into the provided serializer context.
56
+ * @param {ObjectSerializerContext} context context
57
+ */
58
+ serialize(context) {
59
+ context.write(this.concatenatedExpression);
60
+ super.serialize(context);
61
+ }
62
+
63
+ /**
64
+ * Restores this instance from the provided deserializer context.
65
+ * @param {ObjectDeserializerContext} context context
66
+ */
67
+ deserialize(context) {
68
+ this.concatenatedExpression = context.read();
69
+ super.deserialize(context.rest);
70
+ }
71
+ }
72
+
73
+ makeSerializable(
74
+ ImportMetaMainDependency,
75
+ "webpack/lib/dependencies/ImportMetaMainDependency"
76
+ );
77
+
78
+ ImportMetaMainDependency.Template = class ImportMetaMainDependencyTemplate extends (
79
+ NullDependency.Template
80
+ ) {
81
+ /**
82
+ * Applies the plugin by registering its hooks on the compiler.
83
+ * @param {Dependency} dependency the dependency for which the template should be applied
84
+ * @param {ReplaceSource} source the current replace source which can be modified
85
+ * @param {DependencyTemplateContext} templateContext the context object
86
+ * @returns {void}
87
+ */
88
+ apply(dependency, source, templateContext) {
89
+ const dep = /** @type {ImportMetaMainDependency} */ (dependency);
90
+ const concatenated = templateContext.concatenationScope !== undefined;
91
+ if (!concatenated && dep.runtimeRequirements) {
92
+ for (const req of dep.runtimeRequirements) {
93
+ templateContext.runtimeRequirements.add(req);
94
+ }
95
+ }
96
+ const expression = concatenated
97
+ ? dep.concatenatedExpression
98
+ : dep.expression;
99
+ const range = /** @type {Range} */ (dep.range);
100
+ source.replace(range[0], range[1] - 1, expression);
101
+ }
102
+ };
103
+
104
+ module.exports = ImportMetaMainDependency;