Skip to content

fix: make ReactiveUserControl and ReactiveWindow trim and AOT safe; build without runtime-async - #221

Merged
glennawatson merged 1 commit into
mainfrom
fix/aot-safe-reactive-controls
Oct 3, 2026
Merged

glennawatson merged 1 commit into
mainfrom
fix/aot-safe-reactive-controls

Conversation

@glennawatson

@glennawatson glennawatson commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

Summary

ReactiveUserControl and ReactiveWindow are now trim and AOT safe. The .NET 11 build no longer uses runtime-async, and the example runs on every Avalonia platform.

  • The reactive control and window constructors no longer need [RequiresUnreferencedCode]. They pass the view's ViewModelProperty observable to ReactiveUI's reflection-free WhenActivated overload.
  • ReactiveUI.Avalonia and ReactiveUI.Avalonia.Reactive are now marked AOT compatible, so the trim and AOT analyzers check them.
  • The ViewRegistrar Activator fallback gains the [RequiresUnreferencedCode] that its callers already carry.
  • The .NET 11 assemblies are built without runtime-async, which Mono does not support.
  • The example is now a shared library plus Desktop, Browser, Android and iOS heads. The platform packages follow $(AvaloniaVersion).
  • Tests run through ReactiveUI.Avalonia.Tests.slnf, because the solution now contains app heads.
  • Updates ReactiveUI to 26.0.0, ReactiveUI.Binding.Avalonia to 9.0.0 and TUnit to 1.72.16.

Why

Every view that derived from ReactiveUserControl or ReactiveWindow produced trim warnings under Native AOT, because activation found the view model by reflection. Separately, Avalonia's browser, Android and iOS apps run on Mono, where a runtime-async build can fail.

Breaking changes

None. The constructors lose an attribute, and the public API is otherwise unchanged. This ships as a patch release to keep in step with Avalonia's version numbers.

How this was verified

New tests cover swapping the view model while a control is shown, and the example's desktop, single-view, browser and no-storage paths. The iOS head was compiled for net10.0-ios on a host with the iOS workload. The Browser, Android and iOS apps were not run in a browser, emulator or simulator.

Notes for the reviewer

Start with ViewModelPropertySync.ForwardActivation and the two base constructors. The example split, the platform heads and the public API baseline changes are mostly mechanical. The iOS head builds its iOS target only when BuildAppleHead is true, which defaults to macOS hosts. CI and SonarCloud test only the test projects, because dotnet test asks the app heads for a device.

Checklist

  • I have read the Contribute guide
  • The PR title follows Conventional Commits
  • Tests cover this change, or the summary says why they do not
  • New or changed public API has XML documentation

@glennawatson
glennawatson marked this pull request as draft October 3, 2026 04:58
@glennawatson
glennawatson force-pushed the fix/aot-safe-reactive-controls branch 3 times, most recently from 57fcccc to 34a7893 Compare October 3, 2026 10:38
@glennawatson glennawatson changed the title fix: make ReactiveUserControl and ReactiveWindow trim and AOT safe fix: make ReactiveUserControl and ReactiveWindow trim and AOT safe; build without runtime-async Oct 3, 2026
@glennawatson
glennawatson marked this pull request as ready for review October 3, 2026 10:38
@glennawatson
glennawatson force-pushed the fix/aot-safe-reactive-controls branch from 34a7893 to a6c96a1 Compare October 3, 2026 10:58
@codecov

codecov Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.42%. Comparing base (0c7c656) to head (f879d84).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #221      +/-   ##
==========================================
+ Coverage   98.31%   99.42%   +1.10%     
==========================================
  Files          51       54       +3     
  Lines        1010     1042      +32     
  Branches      110      114       +4     
==========================================
+ Hits          993     1036      +43     
+ Misses         13        3      -10     
+ Partials        4        3       -1     

☔ 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.

- Forward view model activation with the view's ViewModelProperty observable, not reflection.
- Remove RequiresUnreferencedCode from the reactive control and window constructors.
- Turn on IsAotCompatible for ReactiveUI.Avalonia and ReactiveUI.Avalonia.Reactive.
- Mark the ViewRegistrar Activator fallback as RequiresUnreferencedCode, as its callers already are.
- Add a test for swapping the view model while the control is shown.
- Build the .NET 11 assemblies without runtime-async. Mono does not support it, so it breaks Avalonia browser, Android and iOS apps.
- Split the example into a shared library with Desktop, Browser, Android and iOS heads.
- Test the example's desktop, browser and no-storage paths.
- Install workloads in CI and run tests through ReactiveUI.Avalonia.Tests.slnf.
- Update ReactiveUI to 26.0.0, ReactiveUI.Binding to 9.0.0 and TUnit to 1.72.16.
@glennawatson
glennawatson force-pushed the fix/aot-safe-reactive-controls branch from a6c96a1 to f879d84 Compare October 3, 2026 12:14
@sonarqubecloud

sonarqubecloud Bot commented Oct 3, 2026

Copy link
Copy Markdown

@glennawatson
glennawatson enabled auto-merge (squash) October 3, 2026 13:26
@glennawatson
glennawatson disabled auto-merge October 3, 2026 13:51
@glennawatson
glennawatson merged commit 8e92310 into main Oct 3, 2026
17 checks passed
@glennawatson
glennawatson deleted the fix/aot-safe-reactive-controls branch October 3, 2026 13:51
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