Skip to content

Fix calc() computation in trimmed / NativeAOT applications - #236

Merged
FlorianRappl merged 1 commit into
AngleSharp:develfrom
sebastienros:fix/aot-calc-metric-values
Sep 4, 2026
Merged

Fix calc() computation in trimmed / NativeAOT applications#236
FlorianRappl merged 1 commit into
AngleSharp:develfrom
sebastienros:fix/aot-calc-metric-values

Conversation

@sebastienros

@sebastienros sebastienros commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Problem

Computing any calc() that combines two metric values throws in NativeAOT (and trimmed) apps:

System.MissingMethodException: No parameterless constructor defined for type 'AngleSharp.Css.Values.CssLengthValue'.
   at AngleSharp.Css.Values.CssCalcAddExpression.AngleSharp.Css.Dom.ICssValue.Compute(ICssComputeContext)
   at AngleSharp.Css.Dom.CssProperty.Compute(ICssComputeContext)

Repro (NativeAOT, net10.0): <style>p { width: calc(100px + 20px) }</style> + GetComputedStyle returns 120px on JIT but throws under AOT.

The four calc expressions build their result with Activator.CreateInstance(x.GetType(), result). The trimmer cannot follow that, so it removes the CssXyzValue(Double) constructors that nothing else calls. Publishing an app with these packages surfaced this as 4 IL2072 trim warnings — the only trim warnings coming out of AngleSharp.Css (AngleSharp, AngleSharp.Xml and AngleSharp.XPath produce none).

Change

  • Moved the reflection call into a single internal helper ICssMetricValue.WithValue(Double) that roots the public constructors of the eight built-in metric values via [DynamicDependency], plus a documented [UnconditionalSuppressMessage] for IL2072. ICssMetricValue is public, so the dynamic path is kept for external implementations — those simply have to preserve their own single-Double constructor (the justification text says so).
  • Did not enable IsAotCompatible in this bug-fix PR. That property should be considered in a later release because it also opts the assembly into trimming; enabling it now could cause unexpected trimming in applications referencing AngleSharp.Css.
  • Added tests: computed calc() addition/subtraction for lengths and times, and a WithValue round-trip for all eight metric types.

Verification

  • dotnet test src/AngleSharp.Css.Tests/AngleSharp.Css.Tests.csproj → 2084 passed.
  • dotnet build src/AngleSharp.Css.sln -c Release → 0 warnings.
  • NativeAOT publish (osx-arm64, net10.0) of a sample app against this branch → 0 IL warnings, and calc(100px + 20px) / calc(100px - 20px) now compute 120px / 80px just like on JIT.

Note: calc(2 * 8px) and calc(30px / 2) still fail with InvalidOperationException: Unsupported unit cannot be converted. — that is a pre-existing issue that reproduces identically on JIT and is out of scope here.

@CLAassistant

CLAassistant commented Sep 3, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@sebastienros
sebastienros force-pushed the fix/aot-calc-metric-values branch from d367563 to 0e8f9e1 Compare September 3, 2026 23:37
@sebastienros
sebastienros changed the base branch from main to devel September 3, 2026 23:38
The calc add/sub/mul/div expressions create the resulting metric value via
Activator.CreateInstance(x.GetType(), result). The trimmer cannot see that
call target, so the single-Double constructors of the built-in metric values
were removed, making every calc() computation throw MissingMethodException in
NativeAOT (and trimmed) applications.

The reflection call now lives in a single helper that roots the public
constructors of all built-in metric values via DynamicDependency, so the
behavior matches the JIT one. ICssMetricValue is public, hence external
implementations stay supported - they just have to preserve their own
constructor.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a2612f6f-7d43-40de-a31f-96a2600e6f81
@sebastienros
sebastienros force-pushed the fix/aot-calc-metric-values branch from 0e8f9e1 to 3680c6a Compare September 3, 2026 23:43

@FlorianRappl FlorianRappl left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great catch - thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug .NET Pull requests that update .NET code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants