[blazor][wasm] Fix hot reload IL trimming#65903
Merged
pavelsavara merged 11 commits intomainfrom Apr 7, 2026
Merged
Conversation
Copilot created this pull request from a session on behalf of
pavelsavara
March 23, 2026 00:13
View session
afe574f to
e83a0f7
Compare
This was referenced Mar 26, 2026
Open
Contributor
There was a problem hiding this comment.
Pull request overview
This PR aims to improve IL trimming for Blazor WebAssembly published apps by making hot reload support trimmer-visible (via a feature-switch-based HotReloadManager.IsSupported guard), updating hot reload call sites to use a two-level guard (IsSupported + runtime-mutable IsEnabled), and adding E2E coverage to validate trimming behavior.
Changes:
- Introduces
HotReloadManager.IsSupported(feature switch) and renames the runtime toggle toHotReloadManager.Default.IsEnabled. - Updates hot reload cache/event-hook call sites to gate on
HotReloadManager.IsSupported && HotReloadManager.Default.IsEnabled. - Adds a trimming check component + E2E test, and updates linker substitutions to target
get_IsSupported.
Reviewed changes
Copilot reviewed 34 out of 34 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| src/Components/Shared/src/HotReloadManager.cs | Adds IsSupported feature switch and renames runtime toggle to IsEnabled. |
| src/Components/Components/src/Properties/ILLink.Substitutions.xml | Updates substitution to stub get_IsSupported. |
| src/Components/Components/src/RenderTree/Renderer.cs | Makes renderer hot reload manager nullable and updates hot reload guards/registration. |
| src/Components/Authorization/src/AttributeAuthorizeDataCache.cs | Updates hot reload cache clearing guard to new two-level check. |
| src/Components/Components/src/BindConverter.cs | Updates formatter/parser caches’ hot reload clear hooks to new guard. |
| src/Components/Components/src/ChangeDetection.cs | Updates hot reload cache clearing guard. |
| src/Components/Components/src/ComponentFactory.cs | Updates hot reload cache clearing guard. |
| src/Components/Components/src/DefaultComponentActivator.cs | Updates hot reload cache clearing guard. |
| src/Components/Components/src/DefaultComponentPropertyActivator.cs | Updates hot reload cache clearing guard. |
| src/Components/Components/src/PersistentState/PersistentServicesRegistry.cs | Updates hot reload cache clearing guard. |
| src/Components/Components/src/PersistentState/PersistentStateValueProviderKeyResolver.cs | Updates hot reload cache clearing guard. |
| src/Components/Components/src/PersistentState/PersistentValueProviderComponentSubscription.cs | Updates hot reload cache clearing guard. |
| src/Components/Components/src/Reflection/ComponentProperties.cs | Updates hot reload cache clearing guard. |
| src/Components/Components/src/RenderTree/EventArgsTypeCache.cs | Updates hot reload cache clearing guard. |
| src/Components/Components/src/RenderTree/RenderTreeDiffBuilder.cs | Updates hot reload diff behavior guard to new two-level check. |
| src/Components/Components/src/RenderHandle.cs | Updates IsRenderingOnMetadataUpdate to use the new guard. |
| src/Components/Components/src/Routing/Router.cs | Updates hot reload route cache clearing hook guard. |
| src/Components/Components/src/Routing/RouteTable.cs | Updates hot reload route cache clearing hook guard. |
| src/Components/Components/src/RouteView.cs | Updates hot reload layout cache clearing hook guard. |
| src/Components/Endpoints/src/Rendering/EndpointComponentState.cs | Updates hot reload cache clearing guard. |
| src/Components/Forms/src/FieldIdentifier.cs | Updates hot reload cache clearing guard. |
| src/Components/Shared/src/RootTypeCache.cs | Updates cache clear subscription/unsubscription to new guard. |
| src/Components/Shared/src/ExpressionFormatting/ExpressionFormatter.cs | Updates hot reload cache clearing guard. |
| src/Components/Web/src/Forms/ExpressionMemberAccessor.cs | Updates hot reload cache clearing guard. |
| src/Components/Web/src/JSComponents/JSComponentInterop.cs | Updates hot reload cache clearing guard. |
| src/Components/Components/test/RendererTest.cs | Updates tests to use IsEnabled and adjusts global default state handling. |
| src/Components/test/E2ETest/Tests/WebAssemblyTrimmingTest.cs | Adds a new trimming-related E2E test. |
| src/Components/test/E2ETest/Infrastructure/ServerFixtures/BasicTestAppServerSiteFixture.cs | Adds a flag for trimmed/multithreading execution mode to support conditional test behavior. |
| src/Components/test/E2ETest/ServerExecutionTests/HotReloadTest.cs | Skips hot reload test in trimmed/multithreading mode. |
| src/Components/test/testassets/BasicTestApp/HotReloadTrimmingCheck.razor | Adds runtime reflection checks for hot reload type/method presence. |
| src/Components/test/testassets/BasicTestApp/Index.razor | Registers the new trimming check component in the test app UI. |
| src/Components/test/testassets/BasicTestApp/BasicTestApp.csproj | Adds MetadataUpdaterSupport property for test configurations. |
| src/Components/test/testassets/Components.TestServer/HotReloadStartup.cs | Updates startup to enable hot reload via IsEnabled. |
| src/Components/test/testassets/Components.TestServer/Components.TestServer.csproj | Adds MetadataUpdaterSupport property for test server configuration. |
tmat
reviewed
Mar 31, 2026
maraf
approved these changes
Apr 1, 2026
javiercn
added a commit
that referenced
this pull request
Apr 11, 2026
…hesis - Enable Chrome performance logging to capture HTTP status codes and MIME types for network requests on assertion failure - Include browser URL and filtered network response details (_framework, _blazor, 4xx/5xx) in BrowserAssertFailedException - Skip verbose performance logs from routine after-test log dump - Set MetadataUpdaterSupport=false in BasicTestApp.csproj to test hypothesis that PR #65903 change causes intermittent MIME type failures for dotnet.js in E2E tests Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
javiercn
added a commit
that referenced
this pull request
Apr 11, 2026
…hesis - Enable Chrome performance logging to capture HTTP status codes and MIME types for network requests on assertion failure - Include browser URL and filtered network response details (_framework, _blazor, 4xx/5xx) in BrowserAssertFailedException - Skip verbose performance logs from routine after-test log dump - Set MetadataUpdaterSupport=false in BasicTestApp.csproj to test hypothesis that PR #65903 change causes intermittent MIME type failures for dotnet.js in E2E tests Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fix hot reload IL trimming
Summary
This PR improves IL trimming effectiveness for Blazor WebAssembly apps by making the hot reload feature switch properly recognized by the IL trimmer. Previously, hot reload–related code (caches, event subscriptions, metadata update handlers) was not trimmed away in published WASM apps because the trimmer could not statically determine that
MetadataUpdater.IsSupportedwasfalse.Problem
HotReloadManager.MetadataUpdateSupportedwas backed byMetadataUpdater.IsSupported, which returnsfalseat runtime in trimmed/published WASM builds. However, the IL trimmer could not prove this statically. As a result:HotReloadManagertype itself and its dependency graph survived trimming.Solution
Introduced
HotReloadManager.IsSupported— astatic boolproperty annotated with[FeatureSwitchDefinition("System.Reflection.Metadata.MetadataUpdater.IsSupported")]. This tells the IL trimmer to substitute this property withfalsewhen the feature switch is disabled, enabling it to eliminate dead code behind the guard.Split the check into two levels:
HotReloadManager.IsSupported(static, trimmer-visible) — controls whether any hot reload infrastructure is linked.HotReloadManager.IsEnabled(instance, runtime-mutable) — replaces the oldMetadataUpdateSupportedproperty, used for testing scenarios where hot reload behavior needs to be toggled at runtime.Updated all ~20 call sites from:
to:
The static
IsSupportedcheck comes first so the trimmer can eliminate the entireifblock when the feature is disabled.Updated
Rendererto use the same two-level guard pattern, replacing direct references to the old staticHotReloadManager.MetadataUpdateSupported.Updated ILLink substitutions in
ILLink.Substitutions.xmlto target the newget_IsSupportedmethod.Testing
RendererTest.cs): Updated to use the newIsEnabledproperty for controlling hot reload behavior in tests.WebAssemblyTrimmingTest.cs): Added a new test that verifiesHotReloadManagertype is trimmed away in published WASM builds. Uses reflection (Type.GetType) to confirm the type is absent in trimmed output.HotReloadTrimmingCheck.razor): A Blazor component that checks at runtime whetherHotReloadManageris present via reflection, reportingtrue/false.Files changed
Core change
HotReloadManager.cs— Added[FeatureSwitchDefinition]-annotatedIsSupportedproperty; renamedMetadataUpdateSupportedtoIsEnabled.Updated call sites (mechanical)
All files below changed from
HotReloadManager.Default.MetadataUpdateSupportedtoHotReloadManager.IsSupported:AttributeAuthorizeDataCache.csBindConverter.csChangeDetection.csComponentFactory.csDefaultComponentActivator.csDefaultComponentPropertyActivator.csPersistentServicesRegistry.csPersistentStateValueProviderKeyResolver.csPersistentValueProviderComponentSubscription.csComponentProperties.csRenderHandle.csEventArgsTypeCache.csRenderTreeDiffBuilder.csRenderer.csRouteView.csRouteTable.csRouter.csEndpointComponentState.csFieldIdentifier.csExpressionFormatter.csRootTypeCache.csExpressionMemberAccessor.csJSComponentInterop.csTrimmer configuration
ILLink.Substitutions.xml— Updated method signature fromget_MetadataUpdateSupportedtoget_IsSupported.Tests
RendererTest.cs— Updated to useIsEnabledinstead ofMetadataUpdateSupported.WebAssemblyTrimmingTest.cs— New E2E test verifyingHotReloadManageris trimmed in WASM publish.HotReloadTrimmingCheck.razor— New test component for runtime type presence check.Index.razor— Registered the new test component.Components.TestServer.csproj— SetMetadataUpdaterSupport=truefor trimmed test builds.HotReloadStartup.cs— Updated to useIsEnabled.