Skip to content

Fix native AOT crash in ReactorApplication at XAML bootstrap#71

Merged
codemonkeychris merged 1 commit into
mainfrom
fix/aot-reactor-xaml-crash
Apr 23, 2026
Merged

Fix native AOT crash in ReactorApplication at XAML bootstrap#71
codemonkeychris merged 1 commit into
mainfrom
fix/aot-reactor-xaml-crash

Conversation

@codemonkeychris
Copy link
Copy Markdown
Collaborator

Summary

Reactor-based WinUI apps published with PublishAot=true crashed at Application startup with STATUS_APPLICATION_INTERNAL_EXCEPTION (0xc000027b) inside Microsoft.UI.Xaml.dll. The faulting call was Resources.MergedDictionaries.Add(new XamlControlsResources()) in ReactorApplication.OnLaunched — under native AOT the runtime XAML parse path that programmatic construction triggers is not safe, whereas the same type loaded via an App.xaml-compiled XBF (as App.xaml-based projects do) is safe. This affected every consumer of ReactorApp.Run that published AOT.

Fix

  • ReactorApplication.xaml (new) — Application-level XAML companion in the Reactor library that declares <XamlControlsResources/> in Application.Resources. The XAML compiler precompiles this to XBF and emits ReactorApplication.g.i.cs with InitializeComponent(), matching the pattern any App.xaml-based project uses.
  • ReactorApp.csReactorApplication constructor now calls InitializeComponent(); removed the programmatic new XamlControlsResources() from OnLaunched. GetXamlType delegates primarily to the XAML-compiler-generated Reactor_XamlTypeInfo.XamlMetaDataProvider (late-bound via Type.GetType with [DynamicDependency] to survive trimming), with a hand-rolled fallback.
  • ReactorCoreXamlMetaDataProvider.cs (new) — fallback provider covering system primitives, core Microsoft.UI.Xaml types (DependencyObject, ResourceDictionary, Style, Setter, DataTemplate, …), enums referenced by theme-dictionary Setter values, and common value structs. Chained after the generated provider.

The late-bound Type.GetType for the generated provider is necessary because referencing Reactor_XamlTypeInfo.XamlMetaDataProvider directly would fail the C# pre-compile that the XAML compiler runs before generating that type — classic chicken-and-egg. The [DynamicDependency] attribute keeps the generated type alive under AOT trimming.

Benchmark

StressPerf.Reactor and StressPerf.ReactorGrid both previously crashed under AOT publish. Now both run cleanly end-to-end (ARM64, 7s per cell):

Variant 10% FPS 50% FPS 100% FPS Avg update ms
WinUI.Reactor (AOT) 18.5 8.0 5.2 ~0.1
WinUI.ReactorGrid (AOT) 12.6 8.8 7.0 ~0.1

Update cost (~0.1 ms) is the lowest of any WinUI variant — Reactor's diffing layer + AOT is a good combination once it runs. Other AOT variants (Direct, DirectX) show small FPS wins and ~30-40 MB memory drops vs JIT builds.

Test plan

  • dotnet publish -c Release -r win-arm64 succeeds for StressPerf.Reactor and StressPerf.ReactorGrid with 0 warnings
  • Both published AOT binaries run to completion in --headless mode and write report files
  • tests/stress_perf/run_bench_aot_publish.sh full 10/50/100% sweep passes for all 6 variants
  • Verify non-AOT (JIT) builds still work unchanged
  • Sanity check: launch an interactive (non-headless) Reactor app under AOT and confirm controls render with correct themes

🤖 Generated with Claude Code

Reactor-based WinUI apps published with PublishAot=true crashed at
Application startup with STATUS_APPLICATION_INTERNAL_EXCEPTION
(0xc000027b) inside Microsoft.UI.Xaml.dll. The crash happened when
OnLaunched ran `Resources.MergedDictionaries.Add(new XamlControlsResources())`
— under AOT the runtime XAML parse path that programmatic construction
triggers is not safe, whereas the same type loaded via an
App.xaml-compiled XBF (as App.xaml-based projects do) is safe.

Fix routes XamlControlsResources through the XAML-compiled path by
adding ReactorApplication.xaml as a library-level App-style companion
and calling InitializeComponent() in the ReactorApplication constructor,
matching the order and code path used by App.xaml-based consumers.

GetXamlType now delegates to the XAML-compiler-generated
Reactor_XamlTypeInfo.XamlMetaDataProvider (late-bound via Type.GetType
with a DynamicDependency to survive trimming) with a hand-rolled
ReactorCoreXamlMetaDataProvider as a fallback for primitives, core
Microsoft.UI.Xaml types, enums and structs that the Controls-only
provider does not carry.

Benchmark (ARM64, 7s per cell; previously both Reactor variants crashed
under AOT): WinUI.Reactor runs 18.5/8.0/5.2 FPS at 10/50/100% updates;
WinUI.ReactorGrid runs 12.6/8.8/7.0 FPS. Both show ~0.1 ms average
update cost — the lowest of any WinUI variant.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Addresses a native AOT startup crash for Reactor-based WinUI apps by shifting XamlControlsResources loading to the XAML-compiled (XBF) bootstrap path and adjusting XAML metadata provider delegation accordingly.

Changes:

  • Adds ReactorApplication.xaml and calls InitializeComponent() to load <XamlControlsResources/> via XBF instead of programmatic construction.
  • Updates ReactorApplication’s IXamlMetadataProvider implementation to prefer the XAML-compiler-generated provider (late-bound for trimming/AOT) with a fallback provider.
  • Adds/updates stress perf AOT publish benchmarking script and result CSVs.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tests/stress_perf/run_bench_aot_publish.sh New script to run 10/50/100% benchmarks against AOT-published outputs and emit CSV.
tests/stress_perf/benchmark_results_aot_publish.csv Captures baseline results from the new AOT publish benchmark sweep.
tests/stress_perf/benchmark_results.csv Updates the “current” benchmark results dataset.
src/Reactor/Hosting/ReactorCoreXamlMetaDataProvider.cs Adds a fallback IXamlMetadataProvider for core primitives/enums/structs used during WinUI theme resource loading under AOT.
src/Reactor/Hosting/ReactorApplication.xaml New application-level XAML that declares <XamlControlsResources/> in Application.Resources.
src/Reactor/Hosting/ReactorApp.cs Switches to XAML-based resource bootstrap + generated metadata provider delegation; removes programmatic new XamlControlsResources() in OnLaunched.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/Reactor/Hosting/ReactorApp.cs
@codemonkeychris codemonkeychris merged commit cbc5752 into main Apr 23, 2026
7 checks passed
Copilot stopped work on behalf of codemonkeychris due to an error April 23, 2026 01:01
@codemonkeychris codemonkeychris deleted the fix/aot-reactor-xaml-crash branch April 23, 2026 01:03
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.

2 participants