Skip to content

Move to AngleSharp.Css 1.1.1-beta.308, the preview with the converter re-entry fix - #3980

Merged
lahma merged 1 commit into
sebastienros:mainfrom
lahma:chore/anglesharp-css-1.1.1-beta.308
Sep 8, 2026
Merged

lahma merged 1 commit into
sebastienros:mainfrom
lahma:chore/anglesharp-css-1.1.1-beta.308

Conversation

@lahma

@lahma lahma commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator

What and why

Refs #3882. Directory.Packages.props moves AngleSharp.Css from 1.1.0 to 1.1.1-beta.308, the preview the maintainer asked this repository to consume. It unblocks draft #3888, which has been waiting for an official package containing AngleSharp/AngleSharp.Css#244 and today carries no dependency change at all.

Core AngleSharp stays at 1.8.0. Verified against nuget.org's flat container: the newest version of AngleSharp is 1.8.0, and the two entries before it (1.8.0-beta.677, 1.8.0-beta.679) are its own pre-release run — there is no post-1.8.0 preview to move to.

Mechanism

AngleSharp.Css 1.1.0 stack-overflows while computing a style for any of CSS Transforms Level 2 §3's individual transform properties (translate, rotate, scale). Each is shaped as an Or of none with an any arm, and CssAnyValue.Compute skipped reparsing only when the compute context's converter was directly that any-converter; through the composite it reparsed the unchanged text with the same composite converter, whose any arm returned another unresolved value, without bound (AngleSharp/AngleSharp.Css#243).

That matters more here than an ordinary upstream bug, because it is the one CSS failure this package cannot contain. Jint.Browser/Dom/Views/CssCascade is the single guarded door onto ComputeCurrentStyle() and turns every CLR failure into a null cascade — but a .NET stack overflow is not an exception and cannot be caught, so <div style="translate: 1px"> ended the host process. A page is not something an embedder can sandbox out of that.

1.1.1-beta.308 is 1.1.0 plus exactly that fix. Checked rather than assumed: GET repos/AngleSharp/AngleSharp.Css/compare/v1.1.0...devel reports ahead_by 3, and the three commits are af16326e (the fix), f48e8ba2 (version bump) and d4e41f29 (the #244 merge).

What moved with it

  • tools/dom-bindings/pin.json — the pin and the package reference are one record, which DomBindingsPinTests enforces.
  • Jint.Tests.Browser/DomBindingsPinTests.cs — its assembly comparison took the pinned version's first three dot-separated parts, which for 1.1.1-beta.308 is 1.1.1-beta and never matches the loaded assembly's 1.1.1. It now drops the prerelease suffix first. This is a real failure the bump produced, not preventive tidying (log below).
  • A comment on the AngleSharp.Css entry saying why the pin is a prerelease and why the core package is not.

Failing-first evidence

New suite: Jint.Tests.Browser/Views/IndividualTransformStyleTests — nine cases over getComputedStyle and over a geometry query.

Run in this worktree with Directory.Packages.props temporarily reverted to AngleSharp.Css 1.1.0, everything else identical:

Run (net8.0, Release) Result on 1.1.0 Result on 1.1.1-beta.308
--filter FullyQualifiedName~IndividualTransformStyleTests run abortedTest host process crashed : Stack overflow. Passed! Failed: 0, Passed: 9
the geometry case alone (AGeometryQueryOverATranslatedSubtreeStillAnswersABox) run aborted — same crash passes
the control alone (TheNoneKeywordStillComputes) Passed! Failed: 0, Passed: 3 passes

The repeating frame in the crash output is the upstream one:

The active test run was aborted. Reason: Test host process crashed : Stack overflow.
   at AngleSharp.Css.Parser.IdentParser.IsIdentifier(AngleSharp.Text.StringSource, System.String)
   ...
   at AngleSharp.Css.Values.CssAnyValue.AngleSharp.Css.Dom.ICssValue.Compute(AngleSharp.Css.Values.ICssComputeContext)
   at AngleSharp.Css.Values.CssAnyValue.AngleSharp.Css.Dom.ICssValue.Compute(AngleSharp.Css.Values.ICssComputeContext)
   ... (repeated to the end of the stack)
Test Run Aborted.

So the "failing" half is a process-fatal crash rather than a test failure, which is exactly why it needs the none control beside it: TheNoneKeywordStillComputes exercises the same three properties through the same converter's keyword arm and passes on 1.1.0, so the new suite going green on the beta is a measurement and not a tautology. The DomBindingsPinTests change has an ordinary failing-first record instead:

Failed TheLoadedAssembliesAreThePinnedOnes
  Expected ... to be the same string, but they differ at index 5:
  "1.1.1"          (actual)
  "1.1.1-beta"     (expected)

Verified

All Release, no --no-build, on this branch's head.

What Command Result
Whole solution dotnet build -c Release Build succeeded. 1 Warning(s), 0 Error(s) — the warning is the pre-existing MSB3277 on Jint.Tests.CommonScripts's net472 test-SDK assets; nothing in it names AngleSharp
Browser suite, net8.0, census on JINT_WPT_BROWSER_CENSUS=1 dotnet test -c Release Jint.Tests.Browser/Jint.Tests.Browser.csproj -f net8.0 Failed: 0, Passed: 2291, Skipped: 36
Browser suite, net10.0, census on same with -f net10.0 Failed: 0, Passed: 2295, Skipped: 36
Wpt browser census the two runs above (TheTableMatchesWhatTheLaneMeasures is not among the 36 skipped) table checked, unchangedJint.Tests.Browser/Wpt/README.md is untouched in the diff, so no =update regeneration was needed or performed
Agent instruction files dotnet test -c Release --filter FullyQualifiedName~AgentInstructionFileTests Passed: 5 on each of net8.0, net10.0, net472
Binding staleness + pin dotnet test -c Release Jint.Tests.Browser/Jint.Tests.Browser.csproj -f net8.0 --filter FullyQualifiedName~DomBindings Passed: 5

The bindings did not need regenerating, and that is a measurement too. The generator was run the long way against both packages with the same pinned AngleSharp 1.8.0 and the same overrides.json:

  • gen(1.1.0) and gen(1.1.1-beta.308) are byte-identical (diff -rq).
  • Their reports differ in exactly one line: AngleSharp.Css 1.1.0.0 becomes AngleSharp.Css 1.1.1.0. Same attribute inventory, same skipped members, Diagnostics (0) on both.
  • The beta's output matches the checked-in Jint.Browser/Dom/Generated/ modulo line endings, which is what DomBindingsStalenessTests independently reports by passing.

Deliberately left out

  • No Jint.Browser/Dom/divergences.md row was added or retired. Clean project.json #243 was a crash, not a divergence, and the search for a Jint-side workaround came up empty — nothing in Jint.Browser/ or Jint.Tests.Browser/ mentions Clean project.json #243/System.Console.WriteLine(JSON.stringify(...)) does not work  #244, no exclusion in WptBrowserExclusions names a transform or a computed-style crash, no fixture declares translate/rotate/scale, and CssCascade's catch filters could never have covered it. There was nothing to retire, and the beta's single change retires none of the recorded rows either (their subjects — colour serialization, :enabled on links, the matchMedia evaluator, explicit inherit — are untouched by System.Console.WriteLine(JSON.stringify(...)) does not work  #244, and the whole suite stays green).
  • No historical "1.1.0" prose was rewritten. docs/, Jint.Browser/AGENTS.md, Jint.Browser/Accessibility/AGENTS.md and divergences.md say things like "shipped in 1.1.0" and "fixed by Css 1.1.0's native computed-style pipeline". Those state which release introduced a behaviour and are still true; only the two records that must agree with the reference — Directory.Packages.props and pin.json — carry the version.
  • No new entry in docs/releases/headless-browser.md. Its upstream-contributions tables are a snapshot of what a specific release consumed (they do not list AngleSharp.Css#242 either), not a running ledger.
  • No geometry, task-budget or Scalar work. That is Improve query-scoped browser geometry and add Scalar reproduction #3888's, and this PR is only the dependency it was waiting on.
  • The new tests assert that the computation terminates and answers, not that a transform moves a box. The flat layout has no transform stage, and System.Console.WriteLine(JSON.stringify(...)) does not work  #244 is a computation-boundary fix, not transform grammar, unit normalization or layout.

Upstream (AngleSharp) findings

None new. For the record, the two this consumes:

One thing worth a maintainer's eye rather than an upstream report: a stable Jint.Browser would now carry a prerelease transitive dependency. That is fine while the package ships as 5.0.0-preview-*, and it is the reason the pin comment says so out loud, but it wants a stable AngleSharp.Css 1.1.1 before a stable Jint.Browser.

🤖 Generated with Claude Code

https://claude.ai/code/session_01SLCujwvKtTvtWD9f6RTyiF

… re-entry fix

AngleSharp.Css 1.1.0 stack-overflows while computing a style for any of CSS
Transforms Level 2's individual transform properties. Those three converters
are an Or of `none` with an any-arm, and CssAnyValue.Compute skipped reparsing
only when the compute context's converter was directly that any-converter;
through the composite it reparsed the unchanged text with the same composite
converter, whose any-arm handed back another unresolved value, without bound
(AngleSharp/AngleSharp.Css#243, fixed by its sebastienros#244). A plain
`<div style="translate: 1px">` therefore ended the process: a stack overflow
is the one CSS failure Dom/Views/CssCascade's guard cannot turn into a null
cascade, because it cannot be caught at all.

1.1.1-beta.308 is v1.1.0 plus exactly that fix — upstream's devel branch is
three commits ahead of the v1.1.0 tag, and they are the fix, its version bump
and the merge. Core AngleSharp stays at 1.8.0: nuget.org lists nothing after
it, prerelease included.

The generator pin moves with the reference, as tools/dom-bindings/README.md
requires. Regenerating against the beta produces a byte-identical
Jint.Browser/Dom/Generated/ and a report differing only in its
assembly-version line, so nothing is regenerated here and no divergence row
is retired: the beta changes a computation boundary, not a [DomName] surface.
DomBindingsPinTests compared the pinned string's first three dot-separated
parts against the loaded assembly version, which reads "1.1.1-beta" against
"1.1.1"; it now drops the prerelease suffix before comparing.

Evidence: Jint.Tests.Browser/Views/IndividualTransformStyleTests, run in this
worktree with the package reverted to 1.1.0, aborts the run — "Test host
process crashed : Stack overflow", the repeating frame being
AngleSharp.Css.Values.CssAnyValue...Compute — both for the getComputedStyle
cases and, running on its own, for the geometry case. The `none` control
passes on 1.1.0, so the suite's green is not vacuous. On the beta all nine
cases pass, and Jint.Tests.Browser is green on net8.0 (2291) and net10.0
(2295) with the wpt browser census checked and unchanged.

Refs sebastienros#3882

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SLCujwvKtTvtWD9f6RTyiF
@lahma
lahma merged commit b31a05f into sebastienros:main Sep 8, 2026
23 of 25 checks passed
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