From 6147c9744911181d4a2c0791a21fcafbe4349f1a Mon Sep 17 00:00:00 2001 From: Larry Ewing Date: Sat, 18 Jul 2026 17:21:16 -0500 Subject: [PATCH] [wasm] Fix AOT + BlazorWebAssemblyLazyLoad startup crash When an app is published with AOT and uses BlazorWebAssemblyLazyLoad, the Mono runtime crashes during startup (appdomain.c assertion / interp.c NIY 'should not be reached'). Root cause: an AOT image hard-binds to every assembly it references when the image is loaded (see load_aot_module in aot-runtime.c, which eagerly calls load_image for all referenced images unless aot-lazy-assembly-load is set). A lazy-loaded assembly is not present at runtime startup, so any AOT image that references it is marked 'unusable because dependency is not found' and its methods fall back to the interpreter, which then hits an unsupported construct and aborts. Enable the runtime's 'aot-lazy-assembly-load' option automatically from the WebAssembly SDK when AOT is combined with BlazorWebAssemblyLazyLoad, so referenced lazy assemblies are only bound when they are actually loaded. Also add AOT + lazy-load regression coverage to LazyLoadingTests, which previously only exercised the interpreter (Debug) configuration. Fixes #125794 (cherry picked from commit 3816e04674acccc8120fb1680c3cf99eb388613d) --- ...rosoft.NET.Sdk.WebAssembly.Browser.targets | 6 +++++ .../wasm/Wasm.Build.Tests/LazyLoadingTests.cs | 22 +++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets b/src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets index ef3a27f424f8aa..0c0df98871681b 100644 --- a/src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets +++ b/src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets @@ -197,6 +197,12 @@ Copyright (c) .NET Foundation. All rights reserved. <_WasmEnableWebcil Condition="'$(_WasmEnableWebcil)' == ''">true <_BlazorWebAssemblyJiterpreter>$(BlazorWebAssemblyJiterpreter) <_BlazorWebAssemblyRuntimeOptions>$(BlazorWebAssemblyRuntimeOptions) + + <_BlazorWebAssemblyRuntimeOptions Condition="'$(RunAOTCompilation)' == 'true' and @(BlazorWebAssemblyLazyLoad->Count()) != 0 and !$(_BlazorWebAssemblyRuntimeOptions.Contains('--aot-lazy-assembly-load'))">$([System.String]::Concat('$(_BlazorWebAssemblyRuntimeOptions)', ' --aot-lazy-assembly-load').Trim()) <_WasmInlineBootConfig>$(WasmInlineBootConfig) <_WasmInlineBootConfig Condition="'$(_WasmInlineBootConfig)' == '' and '$(_TargetingNET100OrLater)' == 'true' and '$(WasmBootConfigFileName)' == ''">true <_WasmInlineBootConfig Condition="'$(_WasmInlineBootConfig)' == ''">false diff --git a/src/mono/wasm/Wasm.Build.Tests/LazyLoadingTests.cs b/src/mono/wasm/Wasm.Build.Tests/LazyLoadingTests.cs index 65011962374221..9dc68a80e2a5c0 100644 --- a/src/mono/wasm/Wasm.Build.Tests/LazyLoadingTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/LazyLoadingTests.cs @@ -50,6 +50,28 @@ public async Task LoadLazyAssemblyBeforeItIsNeeded(string lazyLoadingTestExtensi } } + [Fact] + [TestCategory("native-mono")] + public async Task LoadLazyAssemblyWithAOT() + { + // Regression coverage for https://github.com/dotnet/runtime/issues/125794: + // AOT combined with BlazorWebAssemblyLazyLoad must still initialize the runtime + // and lazily load assemblies at runtime. AOT is only supported when publishing + // in Release, so this exercises the publish + AOT + lazy-load combination that + // the Debug build/run tests above do not cover. + Configuration config = Configuration.Release; + ProjectInfo info = CopyTestAsset(config, aot: true, TestAsset.WasmBasicTestApp, "LazyLoadingTestsAOT"); + PublishProject(info, config, new PublishOptions(AOT: true, ExtraMSBuildArgs: "-p:TestLazyLoading=true")); + + RunResult result = await RunForPublishWithWebServer(new BrowserRunOptions( + config, + AOT: true, + TestScenario: "LazyLoadingTest" + )); + + Assert.True(result.TestOutput.Any(m => m.Contains("FirstName")), "The lazy loading test didn't emit expected message with JSON"); + } + [Fact] public async Task FailOnMissingLazyAssembly() {