Skip to content

[browser][coreCLR] Loading WebCIL 1.0#124268

Open
pavelsavara wants to merge 20 commits intodotnet:mainfrom
pavelsavara:loading_webcil1
Open

[browser][coreCLR] Loading WebCIL 1.0#124268
pavelsavara wants to merge 20 commits intodotnet:mainfrom
pavelsavara:loading_webcil1

Conversation

@pavelsavara
Copy link
Member

@pavelsavara pavelsavara commented Feb 11, 2026

Enable WebCIL support for CoreCLR on Browser/WASM

Fixes #120248

WebCIL format v1.0 with 16-byte section alignment and IMAGE_SECTION_HEADER format

Bumps WebCIL version from 0.0 to 1.0.

  • The WebcilConverter now emits section data at 16-byte-aligned offsets, ensuring RVA static fields backing ReadOnlySpan<T> over types up to Vector128<T> retain their natural alignment.
  • The section headers are full IMAGE_SECTION_HEADER that makes the code of reading much simpler.

CoreCLR PEDecoder: native WebCIL parsing

New src/coreclr/inc/webcil.h defines WebcilHeader and WebcilSectionHeader C structs with static_assert size checks. PEDecoder gains:

  • FLAG_WEBCIL flag; HasWebcilHeaders() validates magic, version, section count/bounds/ordering and synthesizes IMAGE_SECTION_HEADER[] from WebCIL sections so RvaToSection()/RvaToOffset() work uniformly.
  • HasHeaders() / CheckHeaders() as unified entry points that dispatch to WebCIL or NT paths.
  • WebCIL-aware HasDirectoryEntry(), GetDirectoryEntryData() (handles COMHEADER and DEBUG entries via WebcilHeader fields with explicit range validation against section data).
  • CheckCorHeader() and CheckILOnly() WebCIL branches (WebCIL images are always IL-only by definition).
  • GetPEKindAndMachine() reports peILonly / IMAGE_FILE_MACHINE_I386 for WebCIL.
  • GetNumberOfRvaAndSizes() moved from public to private API; GetNumberOfSections() / FindFirstSection() delegate to synthesized headers for WebCIL.
  • Preconditions across the file generalized from CheckNTHeaders() to CheckHeaders() / HasHeaders().

PEImage / PEAssembly integration

PEImage exposes HasHeaders() forwarding to PEDecoder::HasHeaders(). PEAssembly uses HasHeaders() instead of HasNTHeaders() for metadata access.

Browser host loader: WebCIL module instantiation

  • New instantiateWebCILModule() in host assets:
    • instantiates the .wasm wrapper as a WebAssembly module
    • calls getWebcilSize/getWebcilPayload exports to extract the raw WebCIL
    • copies the payload into 16-byte aligned memory, registers it under the .dll virtual path.
  • New getWasmMemory / getWasmTable
  • Enabling WebCIL by default for CoreCLR-on-WASM via WasmEnableWebcil.

DAC support gap

All WebCIL code paths in PEDecoder are gated behind #ifdef TARGET_BROWSER, which is mutually exclusive with DACCESS_COMPILE.
Should we drop #ifdef TARGET_BROWSER ? Or build target specific DAC binaries ?
Follow up in #124467

(func $getWebcilPayload (;1;) (export "getWebcilPayload") (param $d (;0;) i32) (param $n (;1;) i32)
    local.get $d
    i32.const 0
    local.get $n
    memory.init 1
)

@pavelsavara pavelsavara added this to the 11.0.0 milestone Feb 11, 2026
@pavelsavara pavelsavara self-assigned this Feb 11, 2026
@pavelsavara pavelsavara added the arch-wasm WebAssembly architecture label Feb 11, 2026
Copilot AI review requested due to automatic review settings February 11, 2026 12:37
@pavelsavara pavelsavara added area-Host os-browser Browser variant of arch-wasm labels Feb 11, 2026
@dotnet-policy-service
Copy link
Contributor

Tagging subscribers to this area: @agocke, @jeffschwMSFT, @elinor-fung
See info in area-owners.md if you want to be subscribed.

Copy link
Contributor

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

This PR adds support for loading WebCIL version 1.0 assemblies in CoreCLR on browser/WASM targets. WebCIL is an alternative container format for ECMA-335 assemblies that strips PE headers and packages assemblies as WebAssembly modules with a .wasm extension, helping avoid issues with firewalls/antivirus software that block .dll files.

Changes:

  • Added WebCILImageLayout C++ class that extends PEImageLayout to handle WebCIL format, parsing WebCIL headers and mapping RVAs to file offsets
  • Implemented instantiateWebCILModule in TypeScript that instantiates WebCIL .wasm modules and extracts assembly payloads into aligned memory
  • Enabled WebCIL support for CoreCLR by removing WasmEnableWebcil=false restrictions and updating test configurations

Reviewed changes

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

Show a summary per file
File Description
src/native/libs/Common/JavaScript/types/public-api.ts Added "webcil1" asset behavior type
src/native/libs/Common/JavaScript/types/exchange.ts Added instantiateWebCILModule to BrowserHost exports
src/native/libs/Common/JavaScript/cross-module/index.ts Updated export table to include instantiateWebCILModule
src/native/corehost/browserhost/loader/dotnet.d.ts Added "webcil1" type definition
src/native/corehost/browserhost/loader/assets.ts Added WebCIL detection and loading logic, mapping .wasm to .dll paths
src/native/corehost/browserhost/host/index.ts Exported instantiateWebCILModule function
src/native/corehost/browserhost/host/host.ts Updated assembly path mapping to replace .wasm with .dll
src/native/corehost/browserhost/host/assets.ts Implemented instantiateWebCILModule to extract WebCIL payload and register assemblies
src/mono/wasm/Wasm.Build.Tests/Common/BuildEnvironment.cs Removed CoreCLR restriction for WebCIL in tests
src/mono/browser/build/WasmApp.InTree.props Removed WasmEnableWebcil=false for CoreCLR, updated TODO comment
src/coreclr/vm/webcildecoder.cpp New file implementing WebCILImageLayout class for parsing and validating WebCIL format
src/coreclr/vm/peimagelayout.h Added WebCIL header structures and WebCILImageLayout class declaration
src/coreclr/vm/peimagelayout.cpp Added WebCIL format detection in LoadFlat
src/coreclr/vm/peassembly.cpp Excluded 32-bit NT headers check for TARGET_BROWSER, added braces for consistency
src/coreclr/vm/coreassemblyspec.cpp Added braces around single-statement if bodies
src/coreclr/vm/CMakeLists.txt Added webcildecoder.cpp to browser build
src/coreclr/inc/pedecoder.h Made specific PEDecoder methods virtual for browser target to enable WebCILImageLayout overrides
eng/testing/tests.browser.targets Removed WasmEnableWebcil=false for CoreCLR, updated TODO comment

@davidwrighton
Copy link
Member

Please have @elinor-fung look at this

Copilot AI review requested due to automatic review settings February 11, 2026 20:39
Copy link
Contributor

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

Copilot reviewed 18 out of 19 changed files in this pull request and generated 7 comments.

Copilot AI review requested due to automatic review settings February 11, 2026 21:06
Copy link
Contributor

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

Copilot reviewed 18 out of 19 changed files in this pull request and generated 4 comments.

Copy link
Contributor

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

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

Copilot AI review requested due to automatic review settings February 12, 2026 21:57
Copilot AI review requested due to automatic review settings February 18, 2026 13:18
Copy link
Contributor

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

Copilot reviewed 45 out of 46 changed files in this pull request and generated 2 comments.

Copilot AI review requested due to automatic review settings February 18, 2026 15:43
Copy link
Contributor

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

Copilot reviewed 37 out of 38 changed files in this pull request and generated 2 comments.

Copilot AI review requested due to automatic review settings February 18, 2026 20:19
Copy link
Contributor

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

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

@pavelsavara
Copy link
Member Author

What would the RiuJIT team workflow look like for R2R.wasm ?
Loading .wasm module is JavaScript action, It can't be done from C/C++ of the corerun.
There is little src\coreclr\hosts\corerun\wasm\libCorerun.js which could host such code.
How would it be triggered ? Would the VM call pinvoke_override for it ? Or external_assembly_probe ?
Because we can't let the VM just load it from the disk as data (as corerun does for IL only DLL files).

@adamperlin
Copy link
Contributor

What would the RiuJIT team workflow look like for R2R.wasm ? Loading .wasm module is JavaScript action, It can't be done from C/C++ of the corerun. There is little src\coreclr\hosts\corerun\wasm\libCorerun.js which could host such code. How would it be triggered ? Would the VM call pinvoke_override for it ? Or external_assembly_probe ? Because we can't let the VM just load it from the disk as data (as corerun does for IL only DLL files).

I don't know if we're entirely sure of this yet. I think right now, our priority is whatever workflow is easiest to implement so that we can test codegen as soon as possible. What has your testing workflow been @pavelsavara? I'd be curious about @kg's perspective here as well.

@pavelsavara
Copy link
Member Author

What has your testing workflow been @pavelsavara?

I'm used to test with full WASM SDK +http server + browser. The WASM SDK is MSBuild scripts that we ship. It prepares all necessary assets into a form that could be hosted on HTTP server. It also creates manifest - configuration for the browserhost loader, with list of all assets to download. For developers outside of my team, this seems too much.

So, I'm thinking, what's the current R2R inner dev loop for your team, when you test R2R for windows or iOS ?
The VM requesting R2R image would be similar to that, just not dlopen.
What is the call stack for loading R2R image on windows ?
How can I try ? What command lines you use to build and run it ?

I suggest that I could implement loading of R2R.wasm into corerun in next PR, if corerun is the way ...
I will need a sample of R2R.wasm file and a sample app that wants to load it.

# Conflicts:
#	src/native/corehost/browserhost/loader/assets.ts
#	src/native/libs/System.Native.Browser/native/index.ts
Copilot AI review requested due to automatic review settings February 19, 2026 15:43
Copy link
Contributor

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

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

@adamperlin
Copy link
Contributor

adamperlin commented Feb 19, 2026

What has your testing workflow been @pavelsavara?

So, I'm thinking, what's the current R2R inner dev loop for your team, when you test R2R for windows or iOS ? The VM requesting R2R image would be similar to that, just not dlopen. What is the call stack for loading R2R image on windows ? How can I try ? What command lines you use to build and run it ?

I suggest that I could implement loading of R2R.wasm into corerun in next PR, if corerun is the way ... I will need a sample of R2R.wasm file and a sample app that wants to load it.

I haven't done any testing of R2R so far for windows or ios and so I don't have as much context there. However, it sounds like automated tests are generally executed with corerun so that may also point to corerun being what we want to use here. I believe on windows you can execute an R2R image output from crossgen directly with dotnet or with a locally built corerun, if the image has an entrypoint!

If we implement support in corerun, would we then be able to do something like, node /my/build/corerun.js my-r2r-app.wasm? That's assuming the app has an entry point already. That would be a very nice and simple dev loop! Do you have any pointers on what a sample app might look like here? I am truly thinking of simple, self-contained test assemblies for executing basic generated code, i.e.,

// No external dependencies besides corlib
class WasmTest 
{
  public static void Main()
  {
     CodegenTestEntrypoint();
  }
}

@pavelsavara
Copy link
Member Author

something like, node /my/build/corerun.js my-r2r-app.wasm?

In corerun, we don't have the implementation of external_assembly_probe yet and for loading R2R it would be necessary.
Because it needs to be loaded by the "JS host into JS VM" rather than by "dotnet process into WASM linear memory".
I think should do it, but it is out of scope of this PR, which only matches the Mono functionality.

That said, is there more feedback for this PR ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

arch-wasm WebAssembly architecture area-Host os-browser Browser variant of arch-wasm

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[browser][coreCLR] support loading WebCIL

8 participants

Comments