WebAssembly Out-of-Process Renderer#66442
Open
pavelsavara wants to merge 9 commits intodotnet:mainfrom
Open
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Adds an opt-in “out-of-process” rendering path for Blazor WebAssembly that serializes RenderBatch data into a self-contained byte[] and passes it to JavaScript, avoiding shared-heap pointer access and the associated heap lock. It also extends the existing out-of-process batch parser to support a UTF-16LE string table encoding and adds E2E coverage plus CI execution for the new mode.
Changes:
- Add a WebAssembly renderer mode that serializes render batches via
RenderBatchWriterand dispatches them through a newrenderBatchOOPJSImport. - Add UTF-16LE string-table serialization in .NET and decoding support in the JS out-of-process batch reader.
- Add a test page + E2E tests and run an additional CI test pass with the OOP renderer enabled.
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/Components/WebAssembly/WebAssembly/src/Rendering/WebAssemblyRenderer.cs | Adds OOP rendering branch and new RenderBatchOOP JSImport to send serialized batches. |
| src/Components/WebAssembly/WebAssembly/src/Microsoft.AspNetCore.Components.WebAssembly.csproj | Links shared rendering infrastructure (ArrayBuilder*, RenderBatchWriter) into the WASM assembly. |
| src/Components/WebAssembly/WebAssembly/src/Hosting/WebAssemblyHost.cs | Enables OOP rendering via __BLAZOR_WEBASSEMBLY_OOP_RENDERER env var. |
| src/Components/Web.JS/src/Rendering/WebRendererId.ts | Adds WebAssemblyOOP enum value. |
| src/Components/Web.JS/src/Rendering/RenderBatch/OutOfProcessRenderBatch.ts | Adds UTF-16LE string reader and plumbs a flag for string-table encoding selection. |
| src/Components/Web.JS/src/GlobalExports.ts | Extends internal Blazor exports typing with renderBatchOOP. |
| src/Components/Web.JS/src/Boot.WebAssembly.Common.ts | Registers Blazor._internal.renderBatchOOP handler to apply OOP batches without heap lock. |
| src/Components/test/testassets/Components.WasmMinimal/Pages/OOPRendererInteractivity.razor | Adds a WASM interactivity test page used by E2E tests for the OOP renderer. |
| src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsStartup.cs | Propagates the OOP renderer env var into the WASM environment for test runs. |
| src/Components/test/E2ETest/Tests/WebAssemblyOOPRendererTest.cs | Adds E2E tests validating rendering + interactivity scenarios under the OOP renderer. |
| src/Components/test/E2ETest/Infrastructure/ServerFixtures/OOPRendererServerFixture.cs | Adds a server fixture that turns on OOP rendering for test runs. |
| src/Components/Shared/src/WebRendererId.cs | Adds WebAssemblyOOP enum value on the .NET side. |
| src/Components/Shared/src/RenderBatchWriter.cs | Adds UTF-16LE string-table serialization option and constructor flag. |
| src/Components/Shared/src/ArrayBuilderMemoryStream.cs | Adds WASM conditional namespace support for linked shared stream helper. |
| src/Components/Shared/src/ArrayBuilder.cs | Adds WASM conditional namespace support for linked shared buffer helper. |
| .azure/pipelines/components-e2e-tests.yml | Adds an additional CI run executing WebAssembly E2E tests with the OOP renderer enabled and publishes results. |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…PRendererInteractivity.razor Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+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.
WebAssembly Out-of-Process Renderer
Summary
Introduces a new WebAssembly rendering mode that serializes render batches to a binary
byte[]and passes them to JavaScript viaJSImport, instead of sharing raw pointers into the .NET managed heap. This decouples the C# and JS heaps, eliminating the need for a heap lock during rendering and paving the way for future Web Worker isolation.Current Flow (Shared-Memory Renderer)
Problems: Requires heap lock that freezes all .NET execution during DOM patching. Struct field offsets are brittle. Cannot move .NET to a Web Worker because JS and C# must share an address space.
New Flow (Out-of-Process Renderer)
Benefits: No heap lock. Self-contained batch data. Reuses Server's proven serialization path. UTF-16LE string table avoids double UTF-8 transcoding (C# and JS are both natively UTF-16). Future-proof for Web Worker isolation.
What Changed
New Files
OOPRendererInteractivity.razorWebAssemblyOOPRendererTest.csOOPRendererServerFixture.cs--EnableOOPRenderer=trueModified Files
WebAssemblyRenderer.csuseOutOfProcessRenderingconstructor flag; OOP path serializes viaRenderBatchWriterand callsRenderBatchOOPJSImportRenderBatchWriter.csWriteStringTableUtf16()for UTF-16LE string table encoding; new constructor flaguseUtf16StringTableOutOfProcessRenderBatch.tsOutOfProcessStringReaderUtf16class usingTextDecoder('utf-16le'); constructor acceptsuseUtf16StringTableflagBoot.WebAssembly.Common.tsBlazor._internal.renderBatchOOPhandlerGlobalExports.tsrenderBatchOOPtoIBlazor._internaltypeWebRendererId.cs/.tsWebAssemblyOOP = 4enum valueArrayBuilder.cs,ArrayBuilderMemoryStream.csCOMPONENTS_WEBASSEMBLYnamespace conditionalWebAssembly.csprojRenderBatchWriter.cs,ArrayBuilder.cs,ArrayBuilderMemoryStream.csfrom SharedWebAssemblyHost.csuseOutOfProcessRenderingflag based on__BLAZOR_WEBASSEMBLY_OOP_RENDERERenv varRazorComponentEndpointsStartup.cscomponents-e2e-tests.ymlOpt-In Mechanism
The OOP renderer is opt-in via the
__BLAZOR_WEBASSEMBLY_OOP_RENDERERenvironment variable set to"true". For E2E tests,EnableOOPRendererconfig orASPNETCORE_E2E_OOP_RENDERERenv var propagates this.Test Coverage
Six E2E tests validate the core rendering scenarios through the OOP path:
IJSRuntime.InvokeAsync)