Skip to content

fix: expand HTML parser tag and attribute coverage#21159

Merged
alexander-akait merged 9 commits into
mainfrom
fix/html-parser-source-coverage
Jun 11, 2026
Merged

fix: expand HTML parser tag and attribute coverage#21159
alexander-akait merged 9 commits into
mainfrom
fix/html-parser-source-coverage

Conversation

@alexander-akait

@alexander-akait alexander-akait commented Jun 10, 2026

Copy link
Copy Markdown
Member

Summary

Expand the experimental HTML parser's tag/attribute coverage (<template> content, SVG script href/feImage/textPath/mpath, more meta names) and decode HTML character references in attribute values (URLs, srcset candidates, filters, style attributes with re-escaping on write-back), fixing several matching bugs (camelCase SVG tags in sources, meta filter short-circuit, prototype-named tag lookups) along the way.

What kind of change does this PR introduce?

fix

Did you add tests for your changes?

Yes — new config cases under test/configCases/html/ (template-content, svg-script-href, entities, parser-sources-svg-tag, svg-references), extensions to sources, srcset and style-attribute cases, and unit tests in buildHtmlAst.unittest.js / walkHtmlTokens.unittest.js.

Does this PR introduce a breaking change?

No.

If relevant, what needs to be documented once your changes are merged or what have you already documented?

n/a

Use of AI

This PR was developed with Claude Code under my direction: I specified each change, and reviewed/tested the results; tests were written first for the bug fixes.

@changeset-bot

changeset-bot Bot commented Jun 10, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: d4a816e

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
webpack Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@alexander-akait alexander-akait force-pushed the fix/html-parser-source-coverage branch from 70a2e98 to 3b38301 Compare June 10, 2026 08:57
@github-actions

github-actions Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

This PR is packaged and the instant preview is available (f6e52d0).

Install it locally:

  • npm
npm i -D webpack@https://pkg.pr.new/webpack@f6e52d0
  • yarn
yarn add -D webpack@https://pkg.pr.new/webpack@f6e52d0
  • pnpm
pnpm add -D webpack@https://pkg.pr.new/webpack@f6e52d0

@alexander-akait alexander-akait force-pushed the fix/html-parser-source-coverage branch from 3b38301 to 3281835 Compare June 10, 2026 08:59
@codecov

codecov Bot commented Jun 10, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 92.57%. Comparing base (bbb8c3f) to head (d4a816e).
⚠️ Report is 5 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #21159      +/-   ##
==========================================
+ Coverage   92.36%   92.57%   +0.21%     
==========================================
  Files         581      587       +6     
  Lines       63411    63640     +229     
  Branches    17544    17629      +85     
==========================================
+ Hits        58567    58917     +350     
+ Misses       4844     4723     -121     
Flag Coverage Δ
css-parsing 28.73% <ø> (+0.03%) ⬆️
html5lib 31.09% <36.06%> (+<0.01%) ⬆️
integration 88.61% <91.80%> (+0.06%) ⬆️
test262 45.41% <ø> (+0.05%) ⬆️
unit 40.36% <63.93%> (-0.83%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@codspeed-hq

codspeed-hq Bot commented Jun 10, 2026

Copy link
Copy Markdown

Merging this PR will improve performance by 76.81%

⚡ 2 improved benchmarks
❌ 2 regressed benchmarks
✅ 140 untouched benchmarks

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
Memory benchmark "react", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 151.2 KB 330.1 KB -54.19%
Memory benchmark "future-defaults", scenario '{"name":"mode-production","mode":"production"}' 7.4 MB 9.6 MB -22.68%
Memory benchmark "lodash", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 859.3 KB 126 KB ×6.8
Memory benchmark "asset-modules-inline", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 1,293 KB 319.7 KB ×4

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing fix/html-parser-source-coverage (d4a816e) with main (7917dd1)

Open in CodSpeed

- walk <template> content fragments so assets inside templates are processed
- handle SVG <script href> and <script xlink:href> as script entries
- handle <feImage href|xlink:href>
- parse icon-uri from msapplication-task meta and add twitter:image:src
- split link rel on any ASCII whitespace, consistent with other rel checks

https://claude.ai/code/session_016NpnTnhr7hLt3E4wof2XYi
…ta attributes

- register user-configured sources entries under the adjusted camelCase
  tag name (e.g. feimage -> feImage) so they match the AST
- filterMetaContent now checks every present name/property/itemprop
  attribute instead of returning on the first one
- make the tree builder's SVG/foreign adjustment tables null-prototype so
  markup-controlled names like <constructor> can't resolve to inherited
  object members

https://claude.ai/code/session_016NpnTnhr7hLt3E4wof2XYi
Tokenization and srcset splitting still see the raw attribute text (so
dependency spans stay source offsets), but each extracted URL is decoded
with attribute-mode WHATWG semantics and normalized like raw values
before module resolution. Inline style attribute CSS is decoded too.

https://claude.ai/code/session_016NpnTnhr7hLt3E4wof2XYi
The CSS pipeline now sees the entity-decoded attribute value (so
url(a&amp;b.png) resolves), and HtmlInlineStyleDependency re-escapes
the processed CSS when its range is an attribute value, keeping the
rewritten markup valid in any quoting context. <style> content stays
raw both ways (rawtext has no character references).

https://claude.ai/code/session_016NpnTnhr7hLt3E4wof2XYi
@alexander-akait alexander-akait force-pushed the fix/html-parser-source-coverage branch from 75f964e to e8a95a8 Compare June 10, 2026 10:18
- srcset/src/msapplication-task parsers now run on the entity-decoded
  value (entity-encoded ASCII whitespace separates candidates, like in
  browsers); a decoded->raw boundary map from the new
  decodeHtmlEntitiesWithMap keeps rewrite spans on raw source offsets
- the attributes map used by filters and type resolvers carries decoded
  values, so e.g. rel="&#105;con" is recognized as icon
- the style attribute url() pre-filter tests the decoded CSS text
- regenerate srcset errors.js for decoded parse-error messages

https://claude.ai/code/session_016NpnTnhr7hLt3E4wof2XYi
- <iframe srcdoc> content is entity-decoded, parsed as HTML and walked
  with offsets composed back to raw source positions (recursively for
  nested srcdoc); every reference stays a plain asset URL since the
  iframe is a separate browsing context that can't join the outer
  page's entry graph
- SVG presentation attributes (fill, stroke, filter, clip-path, mask,
  marker-*, cursor) resolve external url(file.svg#id) references via a
  new url() extractor; same-document fragments stay untouched
- textPath and mpath href/xlink:href join the defaults table

https://claude.ai/code/session_016NpnTnhr7hLt3E4wof2XYi
…ling

Back out the srcdoc restricted walk and the CSS url() extractor for SVG
presentation attributes, leaving TODO markers to revisit both. The
simple textPath/mpath href/xlink:href handling stays.

https://claude.ai/code/session_016NpnTnhr7hLt3E4wof2XYi
…dges

Covers the patch lines codecov flagged: icon-uri trailing-whitespace trim
and absent/empty icon-uri, empty style attribute, and a URL decoding to
whitespace-only.

https://claude.ai/code/session_016NpnTnhr7hLt3E4wof2XYi
@github-actions

Copy link
Copy Markdown
Contributor

Types Coverage

Coverage after merging fix/html-parser-source-coverage into main will be
99.35%
Coverage Report
FileStmtsBranchesFuncsLinesUncovered Lines
bin
   webpack.js98.77%100%100%98.77%91
examples
   build-common.js100%100%100%100%
   buildAll.js100%100%100%100%
   examples.js100%100%100%100%
   template-common.js98.21%100%100%98.21%72
examples/custom-javascript-parser
   test.filter.js100%100%100%100%
examples/custom-javascript-parser/internals
   acorn-parse.js100%100%100%100%
   meriyah-parse.js100%100%100%100%
   oxc-parse.js91.30%100%100%91.30%140, 142–143, 145, 147, 153–154, 161, 168, 90
examples/markdown
   webpack.config.mjs100%100%100%100%
examples/typescript
   test.filter.js100%100%100%100%
examples/typescript-non-erasable
   test.filter.js50%100%100%50%5
examples/virtual-modules
   test.filter.js100%100%100%100%
examples/wasm-bindgen-esm
   test.filter.js100%100%100%100%
examples/wasm-complex
   test.filter.js100%100%100%100%
examples/wasm-simple
   test.filter.js100%100%100%100%
examples/wasm-simple-source-phase
   test.filter.js100%100%100%100%
lib
   APIPlugin.js100%100%100%100%
   AsyncDependenciesBlock.js100%100%100%100%
   AutomaticPrefetchPlugin.js100%100%100%100%
   BannerPlugin.js100%100%100%100%
   Cache.js98.21%100%100%98.21%101
   CacheFacade.js100%100%100%100%
   Chunk.js99.72%100%100%99.72%39
   ChunkGraph.js100%100%100%100%
   ChunkGroup.js100%100%100%100%
   ChunkTemplate.js100%100%100%100%
   CleanPlugin.js99.15%100%100%99.15%206, 226
   CodeGenerationResults.js100%100%100%100%
   CompatibilityPlugin.js100%100%100%100%
   Compilation.js98.44%100%100%98.44%1609, 1905, 1912, 1920, 1942, 2838, 3317–3318, 3350, 4014, 4044, 4097–4098, 4102, 4107, 4123–4124, 4138–4139, 4144–4145, 4622, 4648, 513, 518, 5456, 5488, 5505, 5521, 5537, 5552, 5577–5578, 5580, 5908, 5913, 5919, 5922, 5934, 5936, 5940, 5956, 5971, 6003, 6057, 6081, 6195, 763–764
   Compiler.js99.56%100%100%99.56%1135–1136, 1144
   ConcatenationScope.js98.59%100%100%98.59%189
   ConditionalInitFragment.js100%100%100%100%
   ConstPlugin.js100%100%100%100%
   ContextExclusionPlugin.js100%100%100%100%
   ContextModule.js100%100%100%100%
   ContextModuleFactory.js97.40%100%100%97.40%258, 395, 418, 420, 424, 433–434
   ContextReplacementPlugin.js100%100%100%100%
   DefinePlugin.js99%100%100%99%170–171, 187, 206, 280
   DependenciesBlock.js100%100%100%100%
   Dependency.js98.15%100%100%98.15%379, 425
   DependencyTemplate.js100%100%100%100%
   DependencyTemplates.js100%100%100%100%
   DotenvPlugin.js98.41%100%100%98.41%378, 391–392
   DynamicEntryPlugin.js100%100%100%100%
   EntryOptionPlugin.js100%100%100%100%
   EntryPlugin.js100%100%100%100%
   Entrypoint.js100%100%100%100%
   EnvironmentPlugin.js97.14%100%100%97.14%49
   ErrorHelpers.js100%100%100%100%
   EvalDevToolModulePlugin.js100%100%100%100%
   EvalSourceMapDevToolPlugin.js100%100%100%100%
   ExportsInfo.js100%100%100%100%
   ExportsInfoApiPlugin.js100%100%100%100%
   ExternalModule.js98.97%100%100%98.97%425–429, 577
   ExternalModuleFactoryPlugin.js100%100%100%100%
   ExternalsPlugin.js100%100%100%100%
   FileSystemInfo.js99.50%100%100%99.50%182, 2252–2253, 2256, 2267, 2278, 2289, 278, 3693, 3708, 3732
   FlagAllModulesAsUsedPlugin.js100%100%100%100%
   FlagDependencyExportsPlugin.js98.85%100%100%98.85%434, 436, 440
   FlagDependencyUsagePlugin.js100%100%100%100%
   FlagEntryExportAsUsedPlugin.js100%100%100%100%
   Generator.js100%100%100%100%
   HotModuleReplacementPlugin.js100%100%100%100%
   HotUpdateChunk.js100%100%100%100%
   IgnorePlugin.js100%100%100%100%
   IgnoreWarningsPlugin.js100%100%100%100%
   InitFragment.js100%100%100%100%
   JavascriptMetaInfoPlugin.js100%100%100%100%
   LibraryTemplatePlugin.js100%100%100%100%
   LoaderOptionsPlugin.js100%100%100%100%
   LoaderTargetPlugin.js100%100%100%100%
   MainTemplate.js100%100%100%100%
   ManifestPlugin.js100%100%100%100%
   Module.js98.50%100%100%98.50%1311, 1316, 1376, 1390, 1452, 1461
   ModuleFactory.js100%100%100%100%
   ModuleFilenameHelpers.js98.85%100%100%98.85%106, 108
   ModuleGraph.js99.73%100%100%99.73%1005
   ModuleGraphConnection.js100%100%100%100%
   ModuleInfoHeaderPlugin.js100%100%100%100%
   ModuleNotFoundError.js100%100%100%100%
   ModuleProfile.js100%100%100%100%
   ModuleSourceTypeConstants.js100%100%100%100%
   ModuleTemplate.js100%100%100%100%
   ModuleTypeConstants.js100%100%100%100%
   MultiCompiler.js99.69%100%100%99.69%659
   MultiStats.js100%100%100%100%
   MultiWatching.js100%100%100%100%
   NoEmitOnErrorsPlugin.js100%100%100%100%
   NodeStuffPlugin.js100%100%100%100%
   NormalModule.js97.90%100%100%97.90%1219, 1222, 1239, 1256, 1503, 1537, 1553, 1640, 1994, 2293, 2298–2308, 417, 421, 575
   NormalModuleFactory.js99.47%100%100%99.47%1083, 1392, 486, 498
   NormalModuleReplacementPlugin.js100%100%100%100%
   NullFactory.js100%100%100%100%
   OptimizationStages.js100%100%100%100%
   OptionsApply.js100%100%100%100%
   Parser.js100%100%100%100%
   PlatformPlugin.js100%100%100%100%
   PrefetchPlugin.js100%100%100%100%
   ProgressPlugin.js98.85%100%100%98.85%519–520, 525, 527, 591
   ProvidePlugin.js100%100%100%100%
   RawModule.js100%100%100%100%
   RecordIdsPlugin.js100%100%100%100%
   RequestShortener.js100%100%100%100%
   ResolverFactory.js100%100%100%100%
   RuntimeGlobals.js100%100%100%100%
   RuntimeModule.js100%100%100%100%
   RuntimePlugin.js100%100%100%100%
   RuntimeTemplate.js100%100%100%100%
   SelfModuleFactory.js100%100%100%100%
   SingleEntryPlugin.js100%100%100%100%
   SourceMapDevToolModuleOptionsPlugin.js100%100%100%100%
   SourceMapDevToolPlugin.js98.62%100%100%98.62%220, 224, 226, 419, 430, 891
   Stats.js100%100%100%100%
   Template.js100%100%100%100%
   TemplatedPathPlugin.js99.17%100%100%99.17%176–177
   UseStrictPlugin.js100%100%100%100%
   WarnCaseSensitiveModulesPlugin.js100%100%100%100%
   WarnDeprecatedOptionPlugin.js100%100%100%100%
   WarnNoModeSetPlugin.js100%100%100%100%
   WatchIgnorePlugin.js100%100%100%100%
   Watching.js100%100%100%100%
   WebpackError.js100%100%100%100%
   WebpackIsIncludedPlugin.js100%100%100%100%
   WebpackOptionsApply.js100%100%100%100%
   WebpackOptionsDefaulter.js100%100%100%100%
   buildChunkGraph.js99.87%100%100%99.87%326
   cli.js98.62%100%100%98.62%10, 119, 545, 577, 627, 897
   index.js99.72%100%100%99.72%165
   validateSchema.js94.67%100%100%94.67%100, 87, 89, 98
   webpack.js96.33%100%100%96.33%10, 198, 220, 222
lib/asset
   AssetBytesGenerator.js100%100%100%100%
   AssetBytesParser.js100%100%100%100%
   AssetGenerator.js100%100%100%100%
   AssetModule.js100%100%100%100%
   AssetModulesPlugin.js97.31%100%100%97.31%279, 303, 306, 358, 36, 41
   AssetParser.js100%100%100%100%
   AssetSourceGenerator.js100%100%100%100%
   AssetSourceParser.js100%100%100%100%
   RawDataUrlModule.js100%100%100%100%
lib/async-modules
   AsyncModuleHelpers.js100%100%100%100%
   AwaitDependenciesInitFragment.js100%100%100%100%
   InferAsyncModulesPlugin.js100%100%100%100%
lib/cache
   AddBuildDependenciesPlugin.js100%100%100%100%
   AddManagedPathsPlugin.js100%100%100%100%
   IdleFileCachePlugin.js97.92%100%100%97.92%71, 83, 91
   MemoryCachePlugin.js95.83%100%100%95.83%33
   MemoryWithGcCachePlugin.js93.15%100%100%93.15%106, 113–114, 122, 89
   PackFileCacheStrategy.js96.40%100%100%96.40%1250, 1350, 1354, 1416, 628, 647, 657–659, 661, 677–678, 683, 686, 688, 693, 698, 722, 728, 762, 768, 774, 779, 790, 799, 804–805, 807, 824, 830–831, 833
   ResolverCachePlugin.js100%100%100%100%
   getLazyHashedEtag.js100%100%100%100%
   mergeEtags.js100%100%100%100%
lib/config
   browserslistTargetHandler.js100%100%100%100%
   defaults.js99.30%100%100%99.30%1439–1441, 1449, 274, 277, 282, 286
   normalization.js99.01%100%100%99.01%191–192, 258, 273
   target.js100%100%100%100%
lib/container
   ContainerEntryDependency.js100%100%100%100%
   ContainerEntryModule.js100%100%100%100%
   ContainerEntryModuleFactory.js100%100%100%100%
   ContainerExposedDependency.js100%100%100%100%
   

@alexander-akait alexander-akait merged commit f6e52d0 into main Jun 11, 2026
66 checks passed
@alexander-akait alexander-akait deleted the fix/html-parser-source-coverage branch June 11, 2026 09:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant