webpack 5.111.0 → 5.111.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. package/lib/APIPlugin.js +3 -4
  2. package/lib/CompatibilityPlugin.js +3 -4
  3. package/lib/Compilation.js +16 -35
  4. package/lib/Compiler.js +4 -5
  5. package/lib/ConstPlugin.js +16 -132
  6. package/lib/DependencyTemplate.js +2 -1
  7. package/lib/DotenvPlugin.js +24 -28
  8. package/lib/ErrorHelpers.js +113 -0
  9. package/lib/ExportsInfo.js +20 -16
  10. package/lib/ExternalModule.js +6 -8
  11. package/lib/FlagDependencyExportsPlugin.js +8 -13
  12. package/lib/FlagDependencyUsagePlugin.js +9 -13
  13. package/lib/Generator.js +24 -2
  14. package/lib/HotModuleReplacementPlugin.js +2 -0
  15. package/lib/IgnorePlugin.js +1 -1
  16. package/lib/LoaderOptionsPlugin.js +1 -1
  17. package/lib/Module.js +3 -3
  18. package/lib/ModuleGraph.js +6 -9
  19. package/lib/MultiCompiler.js +6 -16
  20. package/lib/NormalModule.js +96 -44
  21. package/lib/RuntimeTemplate.js +33 -43
  22. package/lib/SourceMapDevToolPlugin.js +53 -103
  23. package/lib/TemplatedPathPlugin.js +16 -59
  24. package/lib/asset/AssetBytesGenerator.js +7 -1
  25. package/lib/asset/AssetGenerator.js +25 -16
  26. package/lib/asset/AssetSourceGenerator.js +7 -1
  27. package/lib/buildChunkGraph.js +11 -15
  28. package/lib/cache/MemoryCachePlugin.js +4 -4
  29. package/lib/cache/MemoryWithGcCachePlugin.js +7 -8
  30. package/lib/cache/PackFileCacheStrategy.js +3 -18
  31. package/lib/cache/getLazyHashedEtag.js +3 -5
  32. package/lib/config/browserslistTargetHandler.js +2 -8
  33. package/lib/config/defaults.js +52 -78
  34. package/lib/config/getClaimedAssetTypes.js +10 -11
  35. package/lib/config/target.js +3 -4
  36. package/lib/{ContextExclusionPlugin.js → context/ContextExclusionPlugin.js} +1 -1
  37. package/lib/{ContextModule.js → context/ContextModule.js} +37 -34
  38. package/lib/{ContextModuleFactory.js → context/ContextModuleFactory.js} +19 -21
  39. package/lib/{ContextReplacementPlugin.js → context/ContextReplacementPlugin.js} +4 -4
  40. package/lib/css/CssGenerator.js +19 -11
  41. package/lib/css/CssParser.js +18 -20
  42. package/lib/css/cssMinify.js +32 -29
  43. package/lib/css/data.js +797 -288
  44. package/lib/css/syntax.js +2250 -934
  45. package/lib/debug/ProfilingPlugin.js +3 -4
  46. package/lib/dependencies/CommonJsExportRequireDependency.js +10 -11
  47. package/lib/dependencies/CommonJsImportsParserPlugin.js +4 -5
  48. package/lib/dependencies/CommonJsSelfReferenceDependency.js +2 -4
  49. package/lib/dependencies/ContextDependency.js +1 -1
  50. package/lib/dependencies/ContextDependencyHelpers.js +3 -9
  51. package/lib/dependencies/ContextElementDependency.js +1 -1
  52. package/lib/dependencies/CssIcssExportDependency.js +6 -8
  53. package/lib/dependencies/CssIcssImportDependency.js +3 -6
  54. package/lib/dependencies/CssUrlDependency.js +3 -5
  55. package/lib/dependencies/HarmonyCompatibilityDependency.js +11 -20
  56. package/lib/dependencies/HarmonyDetectionParserPlugin.js +3 -4
  57. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +2 -4
  58. package/lib/dependencies/HarmonyExportExpressionDependency.js +3 -4
  59. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +3 -4
  60. package/lib/dependencies/HarmonyExportInitFragment.js +26 -19
  61. package/lib/dependencies/HarmonyExportSpecifierDependency.js +7 -28
  62. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +103 -16
  63. package/lib/dependencies/HarmonyImportSideEffectDependency.js +3 -4
  64. package/lib/dependencies/HarmonyImportSpecifierDependency.js +16 -2
  65. package/lib/dependencies/HtmlEntryDependency.js +74 -102
  66. package/lib/dependencies/HtmlInlineScriptDependency.js +3 -4
  67. package/lib/dependencies/HtmlInlineStyleDependency.js +3 -4
  68. package/lib/dependencies/ImportMetaContextDependencyParserPlugin.js +1 -1
  69. package/lib/dependencies/ImportMetaGlobHelpers.js +1 -1
  70. package/lib/dependencies/ImportMetaPlugin.js +8 -10
  71. package/lib/dependencies/ImportParserPlugin.js +1 -1
  72. package/lib/dependencies/LoaderPlugin.js +26 -1
  73. package/lib/dependencies/RequireContextDependencyParserPlugin.js +1 -1
  74. package/lib/dependencies/URLContextDependency.js +1 -1
  75. package/lib/dependencies/URLDependency.js +6 -5
  76. package/lib/dependencies/WorkerAndWorkletPlugin.js +15 -21
  77. package/lib/dependencies/WorkerDependency.js +6 -5
  78. package/lib/dependencies/WorkletDependency.js +6 -9
  79. package/lib/errors/HookWebpackError.js +3 -2
  80. package/lib/hmr/LazyCompilationPlugin.js +3 -5
  81. package/lib/html/HtmlGenerator.js +61 -82
  82. package/lib/html/HtmlModulesPlugin.js +88 -139
  83. package/lib/html/HtmlParser.js +97 -141
  84. package/lib/html/data.js +21 -0
  85. package/lib/html/htmlMinify.js +10 -11
  86. package/lib/html/syntax.js +883 -993
  87. package/lib/index.js +46 -3
  88. package/lib/javascript/ChunkFormatHelpers.js +4 -3
  89. package/lib/javascript/JavascriptGenerator.js +8 -1
  90. package/lib/javascript/JavascriptModulesPlugin.js +21 -48
  91. package/lib/javascript/JavascriptParser.js +721 -178
  92. package/lib/javascript/parser.js +6 -0
  93. package/lib/javascript/syntax.js +420 -92
  94. package/lib/json/JsonGenerator.js +7 -1
  95. package/lib/library/ModuleLibraryPlugin.js +64 -136
  96. package/lib/loaders/LoaderRunner.js +137 -9
  97. package/lib/node/NodeWatchFileSystem.js +3 -9
  98. package/lib/optimize/AggressiveMergingPlugin.js +3 -5
  99. package/lib/optimize/ConcatenatedModule.js +81 -100
  100. package/lib/optimize/FlagIncludedChunksPlugin.js +3 -11
  101. package/lib/optimize/InnerGraphPlugin.js +7 -13
  102. package/lib/optimize/LimitChunkCountPlugin.js +5 -8
  103. package/lib/optimize/MangleExportsPlugin.js +3 -4
  104. package/lib/optimize/ModuleConcatenationPlugin.js +3 -4
  105. package/lib/optimize/SideEffectsFlagPlugin.js +7 -19
  106. package/lib/optimize/SplitChunksPlugin.js +2 -4
  107. package/lib/performance/BroadContextsPlugin.js +1 -1
  108. package/lib/performance/CacheEffectivenessPlugin.js +3 -4
  109. package/lib/performance/SizeLimitsPlugin.js +2 -4
  110. package/lib/prefetch/ChunkPrefetchPreloadPlugin.js +6 -8
  111. package/lib/prefetch/ResourceHintPlugin.js +17 -21
  112. package/lib/prefetch/StartupAssetHintRuntimeModule.js +7 -10
  113. package/lib/runtime/AsyncModuleRuntimeModule.js +3 -5
  114. package/lib/runtime/GetChunkFilenameRuntimeModule.js +3 -4
  115. package/lib/runtime/GlobalRuntimeModule.js +2 -4
  116. package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +55 -85
  117. package/lib/schemes/DataUriPlugin.js +3 -6
  118. package/lib/schemes/VirtualUrlPlugin.js +1 -1
  119. package/lib/serialization/BinaryMiddleware.js +9 -9
  120. package/lib/serialization/FileMiddleware.js +16 -16
  121. package/lib/serialization/ObjectMiddleware.js +30 -33
  122. package/lib/stats/DefaultStatsFactoryPlugin.js +3 -4
  123. package/lib/typescript/TypeScriptPlugin.js +2 -3
  124. package/lib/url/URLParserPlugin.js +6 -8
  125. package/lib/util/LocConverter.js +4 -7
  126. package/lib/util/SourceProcessor.js +15 -22
  127. package/lib/util/chainedImports.js +3 -4
  128. package/lib/util/concatenate.js +4 -4
  129. package/lib/util/createHooksRegistry.js +1 -2
  130. package/lib/util/dataURL.js +2 -3
  131. package/lib/util/deterministicGrouping.js +8 -13
  132. package/lib/util/findGraphRoots.js +6 -13
  133. package/lib/util/globUtils.js +1 -1
  134. package/lib/util/hash/wasm-hash.js +3 -4
  135. package/lib/util/internalSerializables.js +1 -1
  136. package/lib/util/semver.js +5 -3
  137. package/lib/wasm-async/AsyncWebAssemblyGenerator.js +6 -1
  138. package/lib/wasm-async/AsyncWebAssemblyJavascriptGenerator.js +5 -1
  139. package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +3 -4
  140. package/lib/wasm-sync/WebAssemblyGenerator.js +6 -1
  141. package/lib/wasm-sync/WebAssemblyJavascriptGenerator.js +5 -1
  142. package/lib/wasm-sync/WebAssemblyUtils.js +2 -4
  143. package/package.json +30 -23
  144. package/types.d.ts +299 -280
@@ -90,10 +90,9 @@ const STYLE_ATTR_URL_REGEXP = /url\(|src\(|image\(|image-set\(/i;
90
90
  // hold a `url(...)` FuncIRI. Most are plain colors/keywords (`#fff`, `red`).
91
91
  const FUNC_IRI_URL_REGEXP = /url\(/i;
92
92
 
93
- // Cheap pre-filter for `<iframe srcdoc>` markup: only spin up a nested HTML
94
- // module when the document can reference an asset — via any attribute (`src=`,
95
- // `href=`, `style=`, …), a CSS `url(...)`, or a CSS `@import`. Pure
96
- // formatting/text markup (`<p>hi</p>`) rewrites to itself, so skip it.
93
+ // Cheap pre-filter for `<iframe srcdoc>`: a nested HTML module is only worth
94
+ // building when the markup can reference an asset — any attribute, a CSS
95
+ // `url(...)` or an `@import`. Pure text markup rewrites to itself.
97
96
  const SRCDOC_ASSET_REGEXP = /[=]|url\(|@import/i;
98
97
 
99
98
  // A URL carrying its own scheme (`https:`, `data:`, …) ignores the document
@@ -370,10 +369,9 @@ const isLinkStylesheet = (attributes) => {
370
369
  */
371
370
  const dict = (...bags) => Object.assign(Object.create(null), ...bags);
372
371
 
373
- // Shared `SourceItem` singletons used by the built-in defaults —
374
- // keeping one instance per kind stabilizes V8's hidden classes across
375
- // lookups in the walk. `srcset` is its own type; the walk picks the
376
- // `parseSrcset` parser for it and otherwise treats it like `src`.
372
+ // One shared `SourceItem` per kind, so the walk's lookups stay on a single V8
373
+ // hidden class. `srcset` is its own type: the walk picks `parseSrcset` for it
374
+ // and otherwise treats it like `src`.
377
375
  /** @type {SourceItem} */
378
376
  const PLAIN_SRC = { type: "src", filter: undefined };
379
377
  /** @type {SourceItem} */
@@ -389,10 +387,9 @@ const LINK_HREF = {
389
387
  type: (attrs, css) => {
390
388
  if (isLinkModulePreload(attrs)) return "modulepreload";
391
389
  if (css && isLinkStylesheet(attrs)) return "stylesheet";
392
- // `rel="preload"/"prefetch"` with `as="script"` (or `as="style"` when
393
- // `experiments.css` is on) becomes a bundled, non-executing entry whose
394
- // `href` is rewritten to the built chunk; other `as` targets (image,
395
- // font, fetch, …) stay plain asset URLs.
390
+ // `rel="preload"/"prefetch"` with `as="script"` — or `as="style"` under
391
+ // `experiments.css` — becomes a non-executing entry pointing at the built
392
+ // chunk; every other `as` target stays a plain asset URL.
396
393
  const rel = getAttributeValue(attrs, "rel");
397
394
  if (rel) {
398
395
  const rels = rel.trim().toLowerCase().split(/\s+/);
@@ -446,11 +443,9 @@ const META_CONTENT = {
446
443
  filter: filterMetaContent
447
444
  };
448
445
 
449
- // Built-in lookup table, written directly in its final resolved shape:
450
- // `DEFAULT_SOURCES_BY_TAG[tag][attribute] = item`. No module-load
451
- // loop, no separate array representation — every parser created with
452
- // the default `sources` config just references this table and pays
453
- // zero per-parser work.
446
+ // Written in its final resolved shape, `[tag][attribute] = item`, rather than
447
+ // built from an array at module load: a parser on the default `sources` config
448
+ // references this table and pays nothing per instance.
454
449
  /** @type {Record<string, Record<string, SourceItem>>} */
455
450
  const DEFAULT_SOURCES_BY_TAG = dict({
456
451
  // Obsolete Java-applet element; `code`/`object` are single class/object URLs.
@@ -489,13 +484,14 @@ const DEFAULT_SOURCES_BY_TAG = dict({
489
484
  th: dict({ background: PLAIN_SRC }),
490
485
  track: dict({ src: PLAIN_SRC }),
491
486
  video: dict({ poster: PLAIN_SRC, src: PLAIN_SRC }),
492
- // SVG. Tag names match the tree builder's adjusted camelCase
493
- // (`feImage`/`textPath`/`linearGradient`/`radialGradient`). `href`/
494
- // `xlink:href` reference another element/resource; fragment-only `#id`
495
- // values are left untouched, so only external `file.svg#id` is rewritten.
496
- // `color-profile`'s `xlink:href` points at an external ICC profile file.
497
- // `cursor`/`font-face-uri` point at an external image/font file; `altGlyph`/
498
- // `glyphRef`/`tref` are legacy element references (removed in SVG 2).
487
+ // WHY: SVG. Tag names match the tree builder's adjusted camelCase
488
+ // (`feImage`/`textPath`/`linearGradient`/`radialGradient`). `href` and
489
+ // `xlink:href` reference another element or resource, and a fragment-only
490
+ // `#id` value is left untouched, so only an external `file.svg#id` is
491
+ // rewritten. `color-profile`'s `xlink:href` points at an external ICC profile
492
+ // file; `cursor` and `font-face-uri` at an external image or font file; and
493
+ // `altGlyph`, `glyphRef` and `tref` are legacy element references, removed in
494
+ // SVG 2.
499
495
  altGlyph: dict({ "xlink:href": PLAIN_SRC, href: PLAIN_SRC }),
500
496
  "color-profile": dict({ "xlink:href": PLAIN_SRC, href: PLAIN_SRC }),
501
497
  cursor: dict({ "xlink:href": PLAIN_SRC, href: PLAIN_SRC }),
@@ -515,11 +511,11 @@ const DEFAULT_SOURCES_BY_TAG = dict({
515
511
  // clip-path, …) are handled separately during the walk (`parseCssUrls`).
516
512
  });
517
513
 
518
- // SVG presentation attributes (`fill`, `stroke`, …) carry CSS `url(...)`
519
- // FuncIRIs; `parseCssUrls` extracts external refs as assets (internal
520
- // `url(#id)` is left untouched). They apply to every SVG-namespace element, so
521
- // the item is `namespace`-gated rather than placed in a tag bucket. The filter
522
- // is a cheap pre-check skipping the common plain values (`red`, `none`, `#fff`).
514
+ // WHY: SVG presentation attributes (`fill`, `stroke`, …) carry CSS `url(...)`
515
+ // FuncIRIs, whose external refs `parseCssUrls` extracts as assets, leaving an
516
+ // internal `url(#id)` untouched. They apply to every SVG-namespace element, so
517
+ // the item is `namespace`-gated rather than placed in a tag bucket, and the
518
+ // filter is a cheap pre-check skipping the common plain values (`red`, `none`).
523
519
  /** @type {SourceItem} */
524
520
  const SVG_CSS_URL = {
525
521
  type: "css-url",
@@ -527,21 +523,18 @@ const SVG_CSS_URL = {
527
523
  namespace: NS_SVG
528
524
  };
529
525
 
530
- // The global `style=""` attribute (a CSS declaration list), available on every
531
- // tag and even with `sources: false`. Like every `stylesheet-style*` source it
532
- // only emits when `experiments.css` is on (checked where the dependency is
533
- // created); the filter is a cheap pre-check skipping declarations without a
534
- // `url()`/`src()`/… .
526
+ // The global `style=""` attribute, available on every tag and even under
527
+ // `sources: false`. Like every `stylesheet-style*` source it only emits when
528
+ // `experiments.css` is on, checked where the dependency is created.
535
529
  /** @type {SourceItem} */
536
530
  const STYLE_ATTRIBUTE = {
537
531
  type: "stylesheet-style-attribute",
538
532
  filter: (attributes, value) => STYLE_ATTR_URL_REGEXP.test(value)
539
533
  };
540
534
 
541
- // Any-tag sources — applied to every element as a fallback and folded into
542
- // each tag bucket, so the walk resolves one object per element and reads one
543
- // property per attribute. `DEFAULT` (svg presentation + style) is active
544
- // unless `sources: false`; only the always-on style attribute survives `false`.
535
+ // Any-tag sources, folded into each tag bucket so the walk resolves one object
536
+ // per element and one property per attribute. `sources: false` leaves only the
537
+ // always-on style attribute.
545
538
  /** @type {Record<string, SourceItem>} */
546
539
  const DEFAULT_ANY_SOURCES = dict({ style: STYLE_ATTRIBUTE });
547
540
  for (const name of [
@@ -625,10 +618,9 @@ const styleContentFilter = (attrs) => {
625
618
  return t === "" || t === "text/css";
626
619
  };
627
620
 
628
- // Element-body sources, independent of the `sources` option (even `sources:
629
- // false`): inline `<script>` bodies are always processed; the `<style>` body
630
- // only emits when `experiments.css` is on (checked where the dependency is
631
- // created, like every `stylesheet-style*` source).
621
+ // Element-body sources, independent of the `sources` option: a `<script>` body
622
+ // is always processed, while a `<style>` body only emits when `experiments.css`
623
+ // is on, checked where the dependency is created.
632
624
  /** @type {Record<string, ContentSourceItem>} */
633
625
  const CONTENT_SOURCES = dict({
634
626
  script: { type: scriptContentType, filter: scriptContentFilter },
@@ -649,11 +641,9 @@ class HtmlParser extends Parser {
649
641
  this.template = options.template;
650
642
  /** @type {import("../../declarations/WebpackOptions").UrlHintRule[] | undefined} */
651
643
  this._urlHints = options.urlHints;
652
- // `as` selects the parse mode — the HTML analog of the CSS parser's `as`.
653
- // `"document"` (default) parses a full page; any other value is the
654
- // context element whose inner HTML the source is parsed as (a fragment),
655
- // so context-sensitive tags (`<tr>`, `<td>`, `<option>`, …) in a partial
656
- // are kept, not dropped. `"template"` is the neutral generic fragment.
644
+ // `as` selects the parse mode: `"document"` parses a full page, any other
645
+ // value names the context element whose inner HTML this is, so that a
646
+ // partial's `<tr>`, `<td>` or `<option>` is kept rather than dropped.
657
647
  /** @type {string | undefined} */
658
648
  this.fragmentContext =
659
649
  options.as === undefined || options.as === "document"
@@ -673,13 +663,9 @@ class HtmlParser extends Parser {
673
663
  return;
674
664
  }
675
665
 
676
- // User array — `"..."` anywhere opts the per-tag defaults in as the
677
- // base; the built-in any-tag sources (svg presentation + style) are
678
- // always present. A user entry with no `tag` is an any-tag source (e.g.
679
- // `{ attribute: "data-style", type: "stylesheet-style-attribute" }`).
680
- // User entries override regardless of position. `dict()` keeps every
681
- // table null-prototype (see its doc), and per-tag writes rebuild the
682
- // bucket so the aliased default buckets stay intact.
666
+ // `"..."` anywhere opts the per-tag defaults in as the base, and a user
667
+ // entry with no `tag` is an any-tag source; user entries override wherever
668
+ // they sit. Per-tag writes rebuild the bucket, so the defaults stay intact.
683
669
  /** @type {SourceTable} */
684
670
  const byTag = sources.includes("...")
685
671
  ? dict(DEFAULT_SOURCES_BY_TAG)
@@ -804,14 +790,9 @@ class HtmlParser extends Parser {
804
790
  const css = Boolean(compilation.options.experiments.css);
805
791
  const urlHints = this._urlHints;
806
792
 
807
- // Stable, per-HTML-module prefix used when generating entry names for
808
- // script src / modulepreload references so they don't collide across
809
- // HTML modules in the same compilation. We hash the module's resource
810
- // path (a plain absolute path) — going through `contextify` against
811
- // the compilation root keeps the hash machine-stable for the same
812
- // project layout. Note: `module.identifier()` returns `html|<path>`
813
- // for HTML modules, which doesn't start with `/`, so contextify would
814
- // leave it absolute. `module.resource` is the bare path.
793
+ // Per-module prefix keeping generated entry names from colliding across the
794
+ // HTML modules of one compilation. It hashes `module.resource` rather than
795
+ // `identifier()`, whose `html|` prefix `contextify` would leave absolute.
815
796
  /** @type {string} */
816
797
  const resource =
817
798
  /** @type {EXPECTED_ANY} */ (module).resource || module.identifier();
@@ -820,11 +801,9 @@ class HtmlParser extends Parser {
820
801
  .digest("hex")
821
802
  .slice(0, 8);
822
803
 
823
- // `output.html` head injection: facts are collected during the walk and
824
- // become presentational dependencies afterwards — no later asset pass has
825
- // to re-parse the page. `data:` documents are skipped: synthetic entry
826
- // wrappers already carry the tags and iframe srcdoc pages must stay
827
- // untouched.
804
+ // `output.html` head injection collects facts during the walk and turns
805
+ // them into presentational dependencies after, so no later pass re-parses
806
+ // the page. `data:` documents are skipped — they already carry the tags.
828
807
  const htmlOutputOptions =
829
808
  compilation.options && compilation.options.output
830
809
  ? compilation.options.output.html
@@ -846,10 +825,9 @@ class HtmlParser extends Parser {
846
825
  let inHead = false;
847
826
  // `<template>` contents are inert
848
827
  let headTemplateDepth = 0;
849
- // Depth of open `<template>` elements anywhere in the tree. Template
850
- // content is an inert, separate fragment per spec, so a `<base>` inside
851
- // it must NOT set the document base (`headTemplateDepth` only covers
852
- // templates seen while in `<head>`, so it can't guard body templates).
828
+ // Depth of open `<template>` elements anywhere in the tree: their content
829
+ // is an inert fragment, so a `<base>` inside one must not set the document
830
+ // base. `headTemplateDepth` covers only `<head>`, so it cannot guard this.
853
831
  let templateDepth = 0;
854
832
  let headHasTitle = false;
855
833
  let headHasBase = false;
@@ -857,13 +835,9 @@ class HtmlParser extends Parser {
857
835
  /** @type {Set<string> | undefined} */
858
836
  let headMetaNames;
859
837
 
860
- // Script src / modulepreload references are collected per-type
861
- // during the walk; HtmlModulesPlugin later turns them into real
862
- // entries. `script` and `script-module` entries are chained via a
863
- // leader-only dependOn so they share a runtime.
864
- // `<link rel="modulepreload">` entries are kept independent — they
865
- // must preload without running, so they can never become a runtime
866
- // leader that other entries would import.
838
+ // Collected per type during the walk; HtmlModulesPlugin turns them into
839
+ // entries. `script` and `script-module` chain through a leader-only
840
+ // dependOn; modulepreload stays independent, as it must not run.
867
841
  /**
868
842
  * @typedef {object} HtmlEntryInfo
869
843
  * @property {string} request
@@ -892,28 +866,26 @@ class HtmlParser extends Parser {
892
866
  /** @type {HtmlEntryInfo[]} */
893
867
  const prefetchEntries = [];
894
868
 
895
- // Offset of the first classic blocking script tag; injected stylesheet
896
- // `<link>`s stay ahead of it. `defer`/`async`/module scripts don't
897
- // anchor — they execute after parsing (and after pending stylesheets),
898
- // so CSS may follow their tags (the order Vite emits).
869
+ // Offset of the first classic blocking script tag, which injected stylesheet
870
+ // `<link>`s stay ahead of. `defer`/`async`/module scripts do not anchor: they
871
+ // run after parsing and after pending stylesheets.
899
872
  let firstBlockingScriptStart = -1;
900
873
 
901
874
  let nextEntryIndex = 0;
902
875
 
903
- // `<base href>` resolves the relative URLs that follow it. A relative base
904
- // (`./assets/`) rewrites them into a subdirectory — still bundled; a
905
- // root-relative or absolute base (`/`, `https://cdn/`) points them outside
906
- // the build, so those URLs are left untouched. Resolved in the walk below
907
- // from the first `<base href>` seen (`documentBase` undefined until then).
876
+ // WHY: `<base href>` resolves the relative URLs that follow it. A relative base
877
+ // (`./assets/`) rewrites them into a subdirectory and they stay bundled; a
878
+ // root-relative or absolute one (`/`, `https://cdn/`) points outside the
879
+ // build, so those URLs are left untouched. Resolved in the walk below from
880
+ // the first `<base href>` seen, `documentBase` being undefined until then.
908
881
  /** @type {string | undefined} */
909
882
  let documentBase;
910
883
  /** @type {string | undefined} */
911
884
  let baseDir;
912
885
  let baseIsExternal = false;
913
- // Prepended to the emitted URLs' auto-public-path undo path so the base
914
- // doesn't misdirect them: the browser resolves rewritten (relative)
915
- // output URLs against the base dir, so one `../` per base segment cancels
916
- // it. Undefined for absolute publicPath (no undo path is emitted).
886
+ // Prepended to the emitted URLs' auto-public-path undo path: the browser
887
+ // resolves them against the base dir, so one `../` per base segment cancels
888
+ // it. Undefined for an absolute publicPath, which emits no undo path.
917
889
  /** @type {string | undefined} */
918
890
  let baseUrlPrefix;
919
891
 
@@ -1017,10 +989,9 @@ class HtmlParser extends Parser {
1017
989
  baseIsExternal = true;
1018
990
  return;
1019
991
  }
1020
- // Normalize the base path into its descending directory segments,
1021
- // resolving `.`/`..` like the URL spec. The final segment is the
1022
- // referenced file (dropped) unless the href ends with `/` or a
1023
- // dot-segment; `up` counts `..`s that climb above the document dir.
992
+ // Normalize the base path into descending directory segments, resolving
993
+ // `.`/`..` as the URL spec does. The final segment names a file and is
994
+ // dropped; `up` counts the `..`s climbing above the document dir.
1024
995
  const parts = documentBase.split("/");
1025
996
  /** @type {string[]} */
1026
997
  const dirs = [];
@@ -1070,9 +1041,8 @@ class HtmlParser extends Parser {
1070
1041
  };
1071
1042
 
1072
1043
  // TODO implement full HTML parser (WASM)
1073
- // The walker descends into children (and `<template>` content) itself;
1074
- // the Element `exit` clears a pending `webpackIgnore` once an element's
1075
- // children are done (the old `walkChildren` behaviour).
1044
+ // The walker descends into children and `<template>` content itself, and the
1045
+ // Element `exit` clears a pending `webpackIgnore` once they are done.
1076
1046
  new SourceProcessor()
1077
1047
  .use({
1078
1048
  [NodeType.Comment]: (path) => {
@@ -1220,9 +1190,8 @@ class HtmlParser extends Parser {
1220
1190
  pendingWebpackIgnore = undefined;
1221
1191
  pendingWebpackInline = undefined;
1222
1192
 
1223
- // `<head>` anchors are collected for every page — they place
1224
- // `inject: "head"` siblings and resource hints; the
1225
- // title/meta/base facts only when configured. Structural, so it
1193
+ // `<head>` anchors are collected for every page, since they place
1194
+ // `inject: "head"` siblings and resource hints. Structural, so this
1226
1195
  // runs even for `webpackIgnore`d elements.
1227
1196
  {
1228
1197
  const name = path.tagName();
@@ -1447,11 +1416,9 @@ class HtmlParser extends Parser {
1447
1416
  module.addCodeGenerationDependency(dep);
1448
1417
  break;
1449
1418
  }
1450
- // `<iframe srcdoc>`: an entity-encoded HTML document. Feed the
1451
- // decoded markup back through the HTML pipeline as a nested
1452
- // `data:text/html` module. Per spec the value is a full document
1453
- // whose URL is `about:srcdoc`, so its base URL is inherited from
1454
- // this document — asset URLs resolve against this file's context.
1419
+ // `<iframe srcdoc>` is an entity-encoded document, fed back through
1420
+ // the pipeline as a nested `data:text/html` module. Its URL is
1421
+ // `about:srcdoc`, so asset URLs resolve against this file.
1455
1422
  case "srcdoc": {
1456
1423
  const htmlText = decodeEntities(value, true);
1457
1424
  // Only spin up a nested module when there is markup that can
@@ -1579,10 +1546,9 @@ class HtmlParser extends Parser {
1579
1546
  }
1580
1547
  const s = start + (map ? map[us] : us);
1581
1548
  const e = start + (map ? map[ue] : ue);
1582
- // `html` links the URL as its own emitted page: the same
1583
- // `HtmlEntryDependency` as `<script src>` / `<link>`, but the `html`
1584
- // kind rewrites to the page's filename and emits no sibling tags.
1585
- // Recorded as an independent entry (no `dependOn`), like an entry point.
1549
+ // `html` links the URL as its own emitted page: the same dependency
1550
+ // as `<script src>`, but rewriting to the page's filename and
1551
+ // emitting no siblings. Independent, like an entry point.
1586
1552
  if (type === "html") {
1587
1553
  const index = nextEntryIndex++;
1588
1554
  const entryName = `__html_${moduleHash}_${index}`;
@@ -1598,10 +1564,9 @@ class HtmlParser extends Parser {
1598
1564
  htmlLinkEntries.push({ request, entryName, index, type });
1599
1565
  continue;
1600
1566
  }
1601
- // `rel="preload"/"prefetch"` of a bundled resource: an
1602
- // independent, non-executing entry whose `href` is rewritten to
1603
- // the built chunk's URL (CSS for `as="style"`, JS otherwise). No
1604
- // sibling tags — a resource hint references exactly one URL.
1567
+ // `rel="preload"/"prefetch"` of a bundled resource: an independent,
1568
+ // non-executing entry rewritten to the built chunk's URL. No
1569
+ // siblings — a resource hint references exactly one URL.
1605
1570
  if (type === "preload" || type === "prefetch") {
1606
1571
  const as = getAttributeValue(getAttributesMap(), "as");
1607
1572
  const asStyle = as
@@ -1609,10 +1574,9 @@ class HtmlParser extends Parser {
1609
1574
  : false;
1610
1575
  const index = nextEntryIndex++;
1611
1576
  const entryName = `__html_${moduleHash}_${index}`;
1612
- // Tag metadata so the template can mirror `crossorigin`/
1613
- // `integrity` onto a native `preload` `<link>` (integrity-
1614
- // eligible per the SRI spec). `prefetch` gets none — the spec
1615
- // doesn't list it — so its `integrity` is left uncaptured.
1577
+ // Tag metadata letting the template mirror `crossorigin` and
1578
+ // `integrity` onto a native `preload` `<link>`. `prefetch` is not
1579
+ // integrity-eligible per the SRI spec, so its is left uncaptured.
1616
1580
  const isNativeLink = elementName === "link";
1617
1581
  const dep = new HtmlEntryDependency(
1618
1582
  request,
@@ -1700,13 +1664,9 @@ class HtmlParser extends Parser {
1700
1664
  }
1701
1665
  }
1702
1666
  }
1703
- // Blocking-ness of the tag as *emitted*:
1704
- // `reconcileScriptTypeAttr` upgrades every script entry
1705
- // to `type="module"` under `output.module` and strips an
1706
- // authored `type="module"` otherwise — so only non-module
1707
- // output without `defer`/`async` blocks. Non-native
1708
- // elements anchor conservatively (their synthesized
1709
- // siblings may be plain blocking `<script>`s).
1667
+ // Blocking-ness of the tag as emitted, not as authored:
1668
+ // `reconcileScriptTypeAttr` decides the final `type`, so only
1669
+ // non-module output without `defer`/`async` blocks.
1710
1670
  if (
1711
1671
  firstBlockingScriptStart === -1 &&
1712
1672
  (type === "script" || type === "script-module") &&
@@ -1717,11 +1677,9 @@ class HtmlParser extends Parser {
1717
1677
  ) {
1718
1678
  firstBlockingScriptStart = elementStart;
1719
1679
  }
1720
- // Sibling-clone attribute edits, captured from the parsed
1721
- // attributes (offsets relative to the tag) so the template
1722
- // needn't re-parse the tag text: `integrity` is dropped
1723
- // (content-specific) and `script-module` clones are forced
1724
- // to `type="module"` (its value range, else inserted).
1680
+ // Sibling-clone attribute edits, captured as offsets relative to
1681
+ // the tag so the template need not re-parse it: `integrity` is
1682
+ // content-specific and dropped, `script-module` forces `type`.
1725
1683
  const integrityRange =
1726
1684
  elementStart >= 0 && elementName === nativeTag
1727
1685
  ? captureIntegrityRange(path, source, elementStart)
@@ -1823,10 +1781,9 @@ class HtmlParser extends Parser {
1823
1781
  }
1824
1782
  }
1825
1783
  })
1826
- // Skip AST output this walk never reads: `text` (script/style bodies are
1827
- // read by offset via `contentEnd`) and `doctype` — unless head injection
1828
- // needs the doctype as an insertion anchor; keep `comments` for
1829
- // magic comments (`webpackIgnore`).
1784
+ // Skip AST output this walk never reads: `text`, since script and style
1785
+ // bodies are read by offset, and `doctype` unless head injection needs it
1786
+ // as an anchor. `comments` stays, for `webpackIgnore`.
1830
1787
  .process(source, {
1831
1788
  fragmentContext: this.fragmentContext,
1832
1789
  skip: { text: true, doctype: headOptions === undefined }
@@ -1881,13 +1838,12 @@ class HtmlParser extends Parser {
1881
1838
  const buildInfo = /** @type {HtmlModuleBuildInfo} */ (module.buildInfo);
1882
1839
  buildInfo.strict = true;
1883
1840
  if (baseUrlPrefix !== undefined) buildInfo.baseUrlPrefix = baseUrlPrefix;
1884
- // Hand off the collected entries to HtmlModulesPlugin; it creates the
1885
- // real compilation entries during the finishMake hook. The `script`
1886
- // and `script-module` groups are chained via a leader-only dependOn
1887
- // so they share a runtime; `modulepreload` and `stylesheet` entries
1888
- // are emitted as independent entries since `<link rel=modulepreload>`
1889
- // must preload without running and stylesheets have no runtime. `html`
1890
- // links are independent page entries too.
1841
+ // WHY: hand the collected entries to HtmlModulesPlugin, which creates the
1842
+ // real compilation entries during the finishMake hook. The `script` and
1843
+ // `script-module` groups chain through a leader-only `dependOn` so they share
1844
+ // a runtime, while `modulepreload` and `stylesheet` entries are independent:
1845
+ // `<link rel=modulepreload>` must preload without running, and a stylesheet
1846
+ // has no runtime. `html` links are independent page entries too.
1891
1847
  if (
1892
1848
  scriptEntries.length > 0 ||
1893
1849
  scriptModuleEntries.length > 0 ||
package/lib/html/data.js CHANGED
@@ -130,6 +130,7 @@ const REWRITABLE_ATTRIBUTES = new Set([
130
130
  "blocking",
131
131
  "cite",
132
132
  "class",
133
+ "closedby",
133
134
  "codebase",
134
135
  "cols",
135
136
  "colspan",
@@ -170,6 +171,7 @@ const REWRITABLE_ATTRIBUTES = new Set([
170
171
  "part",
171
172
  "ping",
172
173
  "popover",
174
+ "popovertargetaction",
173
175
  "poster",
174
176
  "preload",
175
177
  "referrerpolicy",
@@ -180,6 +182,7 @@ const REWRITABLE_ATTRIBUTES = new Set([
180
182
  "scope",
181
183
  "scrollamount",
182
184
  "scrolldelay",
185
+ "shadowrootmode",
183
186
  "size",
184
187
  "sizes",
185
188
  "span",
@@ -206,6 +209,7 @@ const REWRITABLE_ATTRIBUTES = new Set([
206
209
  const ENUMERATED_ATTRIBUTE_NAMES = new Set([
207
210
  "autocapitalize",
208
211
  "autocomplete",
212
+ "closedby",
209
213
  "contenteditable",
210
214
  "crossorigin",
211
215
  "decoding",
@@ -222,9 +226,11 @@ const ENUMERATED_ATTRIBUTE_NAMES = new Set([
222
226
  "loading",
223
227
  "method",
224
228
  "popover",
229
+ "popovertargetaction",
225
230
  "preload",
226
231
  "referrerpolicy",
227
232
  "scope",
233
+ "shadowrootmode",
228
234
  "spellcheck",
229
235
  "translate",
230
236
  "type",
@@ -1767,8 +1773,12 @@ const ENUMERATED_KEYWORDS = Object.assign(Object.create(null), {
1767
1773
  "text/plain"
1768
1774
  ]),
1769
1775
  formmethod: new Set(["get", "post", "dialog"]),
1776
+ popovertargetaction: new Set(["toggle", "show", "hide"]),
1770
1777
  type: new Set(["submit", "reset", "button"])
1771
1778
  }),
1779
+ dialog: Object.assign(Object.create(null), {
1780
+ closedby: new Set(["any", "closerequest", "none"])
1781
+ }),
1772
1782
  form: Object.assign(Object.create(null), {
1773
1783
  autocomplete: new Set(["on", "off"]),
1774
1784
  enctype: new Set([
@@ -1794,6 +1804,7 @@ const ENUMERATED_KEYWORDS = Object.assign(Object.create(null), {
1794
1804
  "text/plain"
1795
1805
  ]),
1796
1806
  formmethod: new Set(["get", "post", "dialog"]),
1807
+ popovertargetaction: new Set(["toggle", "show", "hide"]),
1797
1808
  type: new Set([
1798
1809
  "hidden",
1799
1810
  "text",
@@ -1830,6 +1841,9 @@ const ENUMERATED_KEYWORDS = Object.assign(Object.create(null), {
1830
1841
  td: Object.assign(Object.create(null), {
1831
1842
  scope: new Set(["row", "col", "rowgroup", "colgroup"])
1832
1843
  }),
1844
+ template: Object.assign(Object.create(null), {
1845
+ shadowrootmode: new Set(["open", "closed"])
1846
+ }),
1833
1847
  th: Object.assign(Object.create(null), {
1834
1848
  scope: new Set(["row", "col", "rowgroup", "colgroup"])
1835
1849
  }),
@@ -1848,6 +1862,12 @@ const ENUMERATED_KEYWORDS = Object.assign(Object.create(null), {
1848
1862
  })
1849
1863
  });
1850
1864
 
1865
+ /**
1866
+ * `<element> <attribute>` for each enumerated attribute whose invalid value default names a different state from its missing value default, so a value matching no keyword may not be dropped as redundant.
1867
+ * @type {Set<string>}
1868
+ */
1869
+ const INVALID_VALUE_DEFAULT_DIFFERS = new Set(["track kind"]);
1870
+
1851
1871
  /**
1852
1872
  * Elements `removeEmptyElements` never drops: with no children and no attributes each is still doing its job, so an empty one is not a leftover.
1853
1873
  * @type {Set<string>}
@@ -1991,6 +2011,7 @@ module.exports.IGNORED_BODY_TABLE_STARTS = IGNORED_BODY_TABLE_STARTS;
1991
2011
  module.exports.IMPLIED = IMPLIED;
1992
2012
  module.exports.IMPLIED_THOROUGH = IMPLIED_THOROUGH;
1993
2013
  module.exports.INTEGER_ATTRIBUTES = INTEGER_ATTRIBUTES;
2014
+ module.exports.INVALID_VALUE_DEFAULT_DIFFERS = INVALID_VALUE_DEFAULT_DIFFERS;
1994
2015
  module.exports.IN_HEAD_NOSCRIPT_PASSTHROUGH = IN_HEAD_NOSCRIPT_PASSTHROUGH;
1995
2016
  module.exports.IN_TABLE_IGNORED_ENDS = IN_TABLE_IGNORED_ENDS;
1996
2017
  module.exports.JAVASCRIPT_SCRIPT_TYPES = JAVASCRIPT_SCRIPT_TYPES;
@@ -44,8 +44,6 @@ const htmlMinify = async (input, sourceMap, minimizerOptions = {}) => {
44
44
  require(/** @type {string} */ ("webpack"))
45
45
  );
46
46
 
47
- // TODO widen the value rewrites the switches below name: an enumerated
48
- // value the spec does not name.
49
47
  const {
50
48
  askEmbeddedRenderer,
51
49
  builtinEmbeddedRenderer,
@@ -105,9 +103,10 @@ const htmlMinify = async (input, sourceMap, minimizerOptions = {}) => {
105
103
  sortTokenLists,
106
104
  removeImpliedTags
107
105
  };
108
- // Handed each body the print offers, with what it reported kept: how the
109
- // element or attribute around one is written is decided from the answer, and
110
- // a body declined or thrown on is spelled as an untapped run spells it.
106
+ // Handed each body the print offers, keeping what it reported: the element or
107
+ // attribute around one is written from that answer, and a body declined or
108
+ // thrown on is spelled as an untapped run spells it.
109
+
111
110
  // A caller's renderer is asked first; whatever it declines this minifies
112
111
  // itself, for the languages webpack ships a minifier for.
113
112
  const renderer = async (
@@ -151,8 +150,9 @@ const htmlMinify = async (input, sourceMap, minimizerOptions = {}) => {
151
150
 
152
151
  // Recursion goes through this local name, never the module's own: the plugin
153
152
  // ships this function to its workers as source, where that binding is absent.
154
- // A marker cannot cross a parse — the HTML preprocessor turns its NUL into
155
- // U+FFFD — so each nested document is finished before it is spliced in.
153
+
154
+ // A marker cannot cross a parse, the preprocessor turning its NUL into U+FFFD,
155
+ // so each nested document is finished before it is spliced in.
156
156
  /**
157
157
  * @param {string} text a whole document
158
158
  * @returns {Promise<string>} the same document, minified
@@ -246,10 +246,9 @@ htmlMinify.getEmbeddedTypes = () => {
246
246
  return languages;
247
247
  };
248
248
 
249
- // When several minify functions share one `minimizer-webpack-plugin` instance,
250
- // each asset is dispatched only to the ones whose `filter` accepts it — this
251
- // claims HTML, so terser (JS), cssMinify and this can coexist in a single
252
- // plugin / worker pool.
249
+ // Sharing one `minimizer-webpack-plugin` instance, each asset reaches only the
250
+ // minify functions whose `filter` accepts it. This claims HTML, so terser and
251
+ // cssMinify coexist with it in one worker pool.
253
252
  /**
254
253
  * @param {string} name asset filename
255
254
  * @returns {boolean} true for HTML assets