[browser][coreCLR] Loading WebCIL 1.0 - #124268

Closed
pavelsavara wants to merge 29 commits into
dotnet:mainfrom
pavelsavara:loading_webcil1
Closed

[browser][coreCLR] Loading WebCIL 1.0#124268
pavelsavara wants to merge 29 commits into
dotnet:mainfrom
pavelsavara:loading_webcil1

Conversation

@pavelsavara

@pavelsavarapavelsavara commented Feb 11, 2026

Copy link
Copy Markdown
Member

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$di32.const0local.get$nmemory.init1
)

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

Copy link
Copy Markdown
Contributor

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

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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
FileDescription
src/native/libs/Common/JavaScript/types/public-api.tsAdded "webcil1" asset behavior type
src/native/libs/Common/JavaScript/types/exchange.tsAdded instantiateWebCILModule to BrowserHost exports
src/native/libs/Common/JavaScript/cross-module/index.tsUpdated export table to include instantiateWebCILModule
src/native/corehost/browserhost/loader/dotnet.d.tsAdded "webcil1" type definition
src/native/corehost/browserhost/loader/assets.tsAdded WebCIL detection and loading logic, mapping .wasm to .dll paths
src/native/corehost/browserhost/host/index.tsExported instantiateWebCILModule function
src/native/corehost/browserhost/host/host.tsUpdated assembly path mapping to replace .wasm with .dll
src/native/corehost/browserhost/host/assets.tsImplemented instantiateWebCILModule to extract WebCIL payload and register assemblies
src/mono/wasm/Wasm.Build.Tests/Common/BuildEnvironment.csRemoved CoreCLR restriction for WebCIL in tests
src/mono/browser/build/WasmApp.InTree.propsRemoved WasmEnableWebcil=false for CoreCLR, updated TODO comment
src/coreclr/vm/webcildecoder.cppNew file implementing WebCILImageLayout class for parsing and validating WebCIL format
src/coreclr/vm/peimagelayout.hAdded WebCIL header structures and WebCILImageLayout class declaration
src/coreclr/vm/peimagelayout.cppAdded WebCIL format detection in LoadFlat
src/coreclr/vm/peassembly.cppExcluded 32-bit NT headers check for TARGET_BROWSER, added braces for consistency
src/coreclr/vm/coreassemblyspec.cppAdded braces around single-statement if bodies
src/coreclr/vm/CMakeLists.txtAdded webcildecoder.cpp to browser build
src/coreclr/inc/pedecoder.hMade specific PEDecoder methods virtual for browser target to enable WebCILImageLayout overrides
eng/testing/tests.browser.targetsRemoved WasmEnableWebcil=false for CoreCLR, updated TODO comment

Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
@davidwrighton

Copy link
Copy Markdown
Member

Please have @elinor-fung look at this

Comment threadsrc/coreclr/vm/peimagelayout.h Outdated
Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
CopilotAI review requested due to automatic review settings February 11, 2026 20:39

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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.

Comment threadeng/testing/tests.browser.targets
Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
Comment threadsrc/native/corehost/browserhost/host/assets.ts Outdated
Comment threadsrc/native/corehost/browserhost/host/assets.ts Outdated
Comment threadsrc/native/corehost/browserhost/loader/assets.ts Outdated
Comment threadsrc/mono/browser/build/WasmApp.InTree.props
CopilotAI review requested due to automatic review settings February 11, 2026 21:06

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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.

Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
Comment threadsrc/native/corehost/browserhost/host/assets.ts Outdated
Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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.

Comment threadsrc/coreclr/utilcode/pedecoder.cpp
CopilotAI review requested due to automatic review settings February 12, 2026 21:57
Comment threaddocs/design/mono/webcil.md
# Conflicts:
#	src/native/libs/Common/JavaScript/host/assets.ts
#	src/native/libs/Common/JavaScript/host/host.ts
#	src/native/libs/Common/JavaScript/types/exchange.ts
@adamperlin

Copy link
Copy Markdown
Contributor

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 ?

Definitely agreed that it is out of scope for this PR! I was mostly just wanting to understand what direction we are heading in on the host loading side and what work is still required, so I appreciate the clarification here. I don't have any more feedback, and I think this looks good for now as a start! Since I have limited expertise in this area though, it would be great if @elinor-fung could take a look before this goes in.

CopilotAI review requested due to automatic review settings February 20, 2026 21:34

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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 6 comments.

Comment threadsrc/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilReader.cs
Comment threadsrc/native/libs/Common/JavaScript/loader/assets.ts Outdated
Comment threadsrc/mono/browser/build/WasmApp.InTree.props
Comment threadeng/testing/tests.browser.targets
Comment threadsrc/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/ConvertDllsToWebCil.cs Outdated
CopilotAI review requested due to automatic review settings February 23, 2026 10:40
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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 35 out of 36 changed files in this pull request and generated 3 comments.

Comment threadsrc/coreclr/utilcode/pedecoder.cpp
Comment threadsrc/mono/mono/metadata/webcil-loader.c
Comment threadsrc/mono/browser/build/WasmApp.InTree.props
Comment threadsrc/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilReader.cs Outdated
CopilotAI review requested due to automatic review settings February 23, 2026 13:07

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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 35 out of 36 changed files in this pull request and generated no new comments.

@pavelsavara

Copy link
Copy Markdown
MemberAuthor

it would be great if @elinor-fung could take a look before this goes in.

As we are waiting for more feedback on native part, I split of JS part, for which I'm pretty confident into #124758 and will merge that first.

@elinor-fung

Copy link
Copy Markdown
Member

This feels a bit like PEDecoder has been hijacked to also handle Webcil. There are a number of things on it that simply don't apply or make sense for Webcil. While they can share some logic around reading, they are not fundamentally the same format. I would prefer something like:

  • Separate PEDecoder and WebcilDecoder
  • Helper functions the decoders can use for shared logic like reading the IMAGE_SECTION_HEADER
  • PEImageLayout stops inheriting from PEDecoder and instead contains either a PEDecoder or WebcilDecoder (exposing what is needed for callers that were directly calling into PEDecoder)

I know that may be a significant amount of refactoring, but hopefully somewhat mechanical and something copilot would be good at.

@jkotas

Copy link
Copy Markdown
Member

Also, we won't need to artificially inflate the section headers if we go with Elinor's suggestion.

@pavelsavara

Copy link
Copy Markdown
MemberAuthor

The new PEImageLayout will forward about 80 methods to a particular assembly decoder.
About 50 of them are PE only members (some of them would be shared when we add R2R to webcil later).

It will be massive change, are you sure ?
I will do it into separate branch, so that we could compare it

I think we would like to avoid C++ virtual methods, so that DAC is easier, right ?
Probably via on discriminated union.

@pavelsavara

Copy link
Copy Markdown
MemberAuthor

Closing in favor of #124904

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-wasmWebAssembly architecturearea-Hostos-browserBrowser variant of arch-wasm

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[browser][coreCLR] support loading WebCIL

10 participants

@pavelsavara@davidwrighton@steveisok@adamperlin@elinor-fung@jkotas@kg@maraf@AaronRobinsonMSFT
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

[browser][coreCLR] Loading WebCIL 1.0 - #124268

Closed
pavelsavara wants to merge 29 commits into
dotnet:mainfrom
pavelsavara:loading_webcil1
Closed

[browser][coreCLR] Loading WebCIL 1.0#124268
pavelsavara wants to merge 29 commits into
dotnet:mainfrom
pavelsavara:loading_webcil1

Conversation

@pavelsavara

@pavelsavarapavelsavara commented Feb 11, 2026

Copy link
Copy Markdown
Member

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$di32.const0local.get$nmemory.init1
)

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

Copy link
Copy Markdown
Contributor

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

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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
FileDescription
src/native/libs/Common/JavaScript/types/public-api.tsAdded "webcil1" asset behavior type
src/native/libs/Common/JavaScript/types/exchange.tsAdded instantiateWebCILModule to BrowserHost exports
src/native/libs/Common/JavaScript/cross-module/index.tsUpdated export table to include instantiateWebCILModule
src/native/corehost/browserhost/loader/dotnet.d.tsAdded "webcil1" type definition
src/native/corehost/browserhost/loader/assets.tsAdded WebCIL detection and loading logic, mapping .wasm to .dll paths
src/native/corehost/browserhost/host/index.tsExported instantiateWebCILModule function
src/native/corehost/browserhost/host/host.tsUpdated assembly path mapping to replace .wasm with .dll
src/native/corehost/browserhost/host/assets.tsImplemented instantiateWebCILModule to extract WebCIL payload and register assemblies
src/mono/wasm/Wasm.Build.Tests/Common/BuildEnvironment.csRemoved CoreCLR restriction for WebCIL in tests
src/mono/browser/build/WasmApp.InTree.propsRemoved WasmEnableWebcil=false for CoreCLR, updated TODO comment
src/coreclr/vm/webcildecoder.cppNew file implementing WebCILImageLayout class for parsing and validating WebCIL format
src/coreclr/vm/peimagelayout.hAdded WebCIL header structures and WebCILImageLayout class declaration
src/coreclr/vm/peimagelayout.cppAdded WebCIL format detection in LoadFlat
src/coreclr/vm/peassembly.cppExcluded 32-bit NT headers check for TARGET_BROWSER, added braces for consistency
src/coreclr/vm/coreassemblyspec.cppAdded braces around single-statement if bodies
src/coreclr/vm/CMakeLists.txtAdded webcildecoder.cpp to browser build
src/coreclr/inc/pedecoder.hMade specific PEDecoder methods virtual for browser target to enable WebCILImageLayout overrides
eng/testing/tests.browser.targetsRemoved WasmEnableWebcil=false for CoreCLR, updated TODO comment

Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
@davidwrighton

Copy link
Copy Markdown
Member

Please have @elinor-fung look at this

Comment threadsrc/coreclr/vm/peimagelayout.h Outdated
Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
CopilotAI review requested due to automatic review settings February 11, 2026 20:39

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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.

Comment threadeng/testing/tests.browser.targets
Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
Comment threadsrc/native/corehost/browserhost/host/assets.ts Outdated
Comment threadsrc/native/corehost/browserhost/host/assets.ts Outdated
Comment threadsrc/native/corehost/browserhost/loader/assets.ts Outdated
Comment threadsrc/mono/browser/build/WasmApp.InTree.props
CopilotAI review requested due to automatic review settings February 11, 2026 21:06

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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.

Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
Comment threadsrc/native/corehost/browserhost/host/assets.ts Outdated
Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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.

Comment threadsrc/coreclr/utilcode/pedecoder.cpp
CopilotAI review requested due to automatic review settings February 12, 2026 21:57
Comment threaddocs/design/mono/webcil.md
# Conflicts:
#	src/native/libs/Common/JavaScript/host/assets.ts
#	src/native/libs/Common/JavaScript/host/host.ts
#	src/native/libs/Common/JavaScript/types/exchange.ts
@adamperlin

Copy link
Copy Markdown
Contributor

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 ?

Definitely agreed that it is out of scope for this PR! I was mostly just wanting to understand what direction we are heading in on the host loading side and what work is still required, so I appreciate the clarification here. I don't have any more feedback, and I think this looks good for now as a start! Since I have limited expertise in this area though, it would be great if @elinor-fung could take a look before this goes in.

CopilotAI review requested due to automatic review settings February 20, 2026 21:34

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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 6 comments.

Comment threadsrc/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilReader.cs
Comment threadsrc/native/libs/Common/JavaScript/loader/assets.ts Outdated
Comment threadsrc/mono/browser/build/WasmApp.InTree.props
Comment threadeng/testing/tests.browser.targets
Comment threadsrc/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/ConvertDllsToWebCil.cs Outdated
CopilotAI review requested due to automatic review settings February 23, 2026 10:40
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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 35 out of 36 changed files in this pull request and generated 3 comments.

Comment threadsrc/coreclr/utilcode/pedecoder.cpp
Comment threadsrc/mono/mono/metadata/webcil-loader.c
Comment threadsrc/mono/browser/build/WasmApp.InTree.props
Comment threadsrc/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilReader.cs Outdated
CopilotAI review requested due to automatic review settings February 23, 2026 13:07

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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 35 out of 36 changed files in this pull request and generated no new comments.

@pavelsavara

Copy link
Copy Markdown
MemberAuthor

it would be great if @elinor-fung could take a look before this goes in.

As we are waiting for more feedback on native part, I split of JS part, for which I'm pretty confident into #124758 and will merge that first.

@elinor-fung

Copy link
Copy Markdown
Member

This feels a bit like PEDecoder has been hijacked to also handle Webcil. There are a number of things on it that simply don't apply or make sense for Webcil. While they can share some logic around reading, they are not fundamentally the same format. I would prefer something like:

  • Separate PEDecoder and WebcilDecoder
  • Helper functions the decoders can use for shared logic like reading the IMAGE_SECTION_HEADER
  • PEImageLayout stops inheriting from PEDecoder and instead contains either a PEDecoder or WebcilDecoder (exposing what is needed for callers that were directly calling into PEDecoder)

I know that may be a significant amount of refactoring, but hopefully somewhat mechanical and something copilot would be good at.

@jkotas

Copy link
Copy Markdown
Member

Also, we won't need to artificially inflate the section headers if we go with Elinor's suggestion.

@pavelsavara

Copy link
Copy Markdown
MemberAuthor

The new PEImageLayout will forward about 80 methods to a particular assembly decoder.
About 50 of them are PE only members (some of them would be shared when we add R2R to webcil later).

It will be massive change, are you sure ?
I will do it into separate branch, so that we could compare it

I think we would like to avoid C++ virtual methods, so that DAC is easier, right ?
Probably via on discriminated union.

@pavelsavara

Copy link
Copy Markdown
MemberAuthor

Closing in favor of #124904

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-wasmWebAssembly architecturearea-Hostos-browserBrowser variant of arch-wasm

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[browser][coreCLR] support loading WebCIL

10 participants

@pavelsavara@davidwrighton@steveisok@adamperlin@elinor-fung@jkotas@kg@maraf@AaronRobinsonMSFT
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[browser][coreCLR] Loading WebCIL 1.0 - #124268

Closed
pavelsavara wants to merge 29 commits into
dotnet:mainfrom
pavelsavara:loading_webcil1
Closed

[browser][coreCLR] Loading WebCIL 1.0#124268
pavelsavara wants to merge 29 commits into
dotnet:mainfrom
pavelsavara:loading_webcil1

Conversation

@pavelsavara

@pavelsavarapavelsavara commented Feb 11, 2026

Copy link
Copy Markdown
Member

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$di32.const0local.get$nmemory.init1
)

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

Copy link
Copy Markdown
Contributor

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

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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
FileDescription
src/native/libs/Common/JavaScript/types/public-api.tsAdded "webcil1" asset behavior type
src/native/libs/Common/JavaScript/types/exchange.tsAdded instantiateWebCILModule to BrowserHost exports
src/native/libs/Common/JavaScript/cross-module/index.tsUpdated export table to include instantiateWebCILModule
src/native/corehost/browserhost/loader/dotnet.d.tsAdded "webcil1" type definition
src/native/corehost/browserhost/loader/assets.tsAdded WebCIL detection and loading logic, mapping .wasm to .dll paths
src/native/corehost/browserhost/host/index.tsExported instantiateWebCILModule function
src/native/corehost/browserhost/host/host.tsUpdated assembly path mapping to replace .wasm with .dll
src/native/corehost/browserhost/host/assets.tsImplemented instantiateWebCILModule to extract WebCIL payload and register assemblies
src/mono/wasm/Wasm.Build.Tests/Common/BuildEnvironment.csRemoved CoreCLR restriction for WebCIL in tests
src/mono/browser/build/WasmApp.InTree.propsRemoved WasmEnableWebcil=false for CoreCLR, updated TODO comment
src/coreclr/vm/webcildecoder.cppNew file implementing WebCILImageLayout class for parsing and validating WebCIL format
src/coreclr/vm/peimagelayout.hAdded WebCIL header structures and WebCILImageLayout class declaration
src/coreclr/vm/peimagelayout.cppAdded WebCIL format detection in LoadFlat
src/coreclr/vm/peassembly.cppExcluded 32-bit NT headers check for TARGET_BROWSER, added braces for consistency
src/coreclr/vm/coreassemblyspec.cppAdded braces around single-statement if bodies
src/coreclr/vm/CMakeLists.txtAdded webcildecoder.cpp to browser build
src/coreclr/inc/pedecoder.hMade specific PEDecoder methods virtual for browser target to enable WebCILImageLayout overrides
eng/testing/tests.browser.targetsRemoved WasmEnableWebcil=false for CoreCLR, updated TODO comment

Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
@davidwrighton

Copy link
Copy Markdown
Member

Please have @elinor-fung look at this

Comment threadsrc/coreclr/vm/peimagelayout.h Outdated
Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
CopilotAI review requested due to automatic review settings February 11, 2026 20:39

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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.

Comment threadeng/testing/tests.browser.targets
Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
Comment threadsrc/native/corehost/browserhost/host/assets.ts Outdated
Comment threadsrc/native/corehost/browserhost/host/assets.ts Outdated
Comment threadsrc/native/corehost/browserhost/loader/assets.ts Outdated
Comment threadsrc/mono/browser/build/WasmApp.InTree.props
CopilotAI review requested due to automatic review settings February 11, 2026 21:06

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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.

Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
Comment threadsrc/native/corehost/browserhost/host/assets.ts Outdated
Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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.

Comment threadsrc/coreclr/utilcode/pedecoder.cpp
CopilotAI review requested due to automatic review settings February 12, 2026 21:57
Comment threaddocs/design/mono/webcil.md
# Conflicts:
#	src/native/libs/Common/JavaScript/host/assets.ts
#	src/native/libs/Common/JavaScript/host/host.ts
#	src/native/libs/Common/JavaScript/types/exchange.ts
@adamperlin

Copy link
Copy Markdown
Contributor

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 ?

Definitely agreed that it is out of scope for this PR! I was mostly just wanting to understand what direction we are heading in on the host loading side and what work is still required, so I appreciate the clarification here. I don't have any more feedback, and I think this looks good for now as a start! Since I have limited expertise in this area though, it would be great if @elinor-fung could take a look before this goes in.

CopilotAI review requested due to automatic review settings February 20, 2026 21:34

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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 6 comments.

Comment threadsrc/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilReader.cs
Comment threadsrc/native/libs/Common/JavaScript/loader/assets.ts Outdated
Comment threadsrc/mono/browser/build/WasmApp.InTree.props
Comment threadeng/testing/tests.browser.targets
Comment threadsrc/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/ConvertDllsToWebCil.cs Outdated
CopilotAI review requested due to automatic review settings February 23, 2026 10:40
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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 35 out of 36 changed files in this pull request and generated 3 comments.

Comment threadsrc/coreclr/utilcode/pedecoder.cpp
Comment threadsrc/mono/mono/metadata/webcil-loader.c
Comment threadsrc/mono/browser/build/WasmApp.InTree.props
Comment threadsrc/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilReader.cs Outdated
CopilotAI review requested due to automatic review settings February 23, 2026 13:07

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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 35 out of 36 changed files in this pull request and generated no new comments.

@pavelsavara

Copy link
Copy Markdown
MemberAuthor

it would be great if @elinor-fung could take a look before this goes in.

As we are waiting for more feedback on native part, I split of JS part, for which I'm pretty confident into #124758 and will merge that first.

@elinor-fung

Copy link
Copy Markdown
Member

This feels a bit like PEDecoder has been hijacked to also handle Webcil. There are a number of things on it that simply don't apply or make sense for Webcil. While they can share some logic around reading, they are not fundamentally the same format. I would prefer something like:

  • Separate PEDecoder and WebcilDecoder
  • Helper functions the decoders can use for shared logic like reading the IMAGE_SECTION_HEADER
  • PEImageLayout stops inheriting from PEDecoder and instead contains either a PEDecoder or WebcilDecoder (exposing what is needed for callers that were directly calling into PEDecoder)

I know that may be a significant amount of refactoring, but hopefully somewhat mechanical and something copilot would be good at.

@jkotas

Copy link
Copy Markdown
Member

Also, we won't need to artificially inflate the section headers if we go with Elinor's suggestion.

@pavelsavara

Copy link
Copy Markdown
MemberAuthor

The new PEImageLayout will forward about 80 methods to a particular assembly decoder.
About 50 of them are PE only members (some of them would be shared when we add R2R to webcil later).

It will be massive change, are you sure ?
I will do it into separate branch, so that we could compare it

I think we would like to avoid C++ virtual methods, so that DAC is easier, right ?
Probably via on discriminated union.

@pavelsavara

Copy link
Copy Markdown
MemberAuthor

Closing in favor of #124904

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-wasmWebAssembly architecturearea-Hostos-browserBrowser variant of arch-wasm

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[browser][coreCLR] support loading WebCIL

10 participants

@pavelsavara@davidwrighton@steveisok@adamperlin@elinor-fung@jkotas@kg@maraf@AaronRobinsonMSFT
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[browser][coreCLR] Loading WebCIL 1.0 - #124268

Closed
pavelsavara wants to merge 29 commits into
dotnet:mainfrom
pavelsavara:loading_webcil1
Closed

[browser][coreCLR] Loading WebCIL 1.0#124268
pavelsavara wants to merge 29 commits into
dotnet:mainfrom
pavelsavara:loading_webcil1

Conversation

@pavelsavara

@pavelsavarapavelsavara commented Feb 11, 2026

Copy link
Copy Markdown
Member

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$di32.const0local.get$nmemory.init1
)

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

Copy link
Copy Markdown
Contributor

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

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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
FileDescription
src/native/libs/Common/JavaScript/types/public-api.tsAdded "webcil1" asset behavior type
src/native/libs/Common/JavaScript/types/exchange.tsAdded instantiateWebCILModule to BrowserHost exports
src/native/libs/Common/JavaScript/cross-module/index.tsUpdated export table to include instantiateWebCILModule
src/native/corehost/browserhost/loader/dotnet.d.tsAdded "webcil1" type definition
src/native/corehost/browserhost/loader/assets.tsAdded WebCIL detection and loading logic, mapping .wasm to .dll paths
src/native/corehost/browserhost/host/index.tsExported instantiateWebCILModule function
src/native/corehost/browserhost/host/host.tsUpdated assembly path mapping to replace .wasm with .dll
src/native/corehost/browserhost/host/assets.tsImplemented instantiateWebCILModule to extract WebCIL payload and register assemblies
src/mono/wasm/Wasm.Build.Tests/Common/BuildEnvironment.csRemoved CoreCLR restriction for WebCIL in tests
src/mono/browser/build/WasmApp.InTree.propsRemoved WasmEnableWebcil=false for CoreCLR, updated TODO comment
src/coreclr/vm/webcildecoder.cppNew file implementing WebCILImageLayout class for parsing and validating WebCIL format
src/coreclr/vm/peimagelayout.hAdded WebCIL header structures and WebCILImageLayout class declaration
src/coreclr/vm/peimagelayout.cppAdded WebCIL format detection in LoadFlat
src/coreclr/vm/peassembly.cppExcluded 32-bit NT headers check for TARGET_BROWSER, added braces for consistency
src/coreclr/vm/coreassemblyspec.cppAdded braces around single-statement if bodies
src/coreclr/vm/CMakeLists.txtAdded webcildecoder.cpp to browser build
src/coreclr/inc/pedecoder.hMade specific PEDecoder methods virtual for browser target to enable WebCILImageLayout overrides
eng/testing/tests.browser.targetsRemoved WasmEnableWebcil=false for CoreCLR, updated TODO comment

Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
@davidwrighton

Copy link
Copy Markdown
Member

Please have @elinor-fung look at this

Comment threadsrc/coreclr/vm/peimagelayout.h Outdated
Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
CopilotAI review requested due to automatic review settings February 11, 2026 20:39

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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.

Comment threadeng/testing/tests.browser.targets
Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
Comment threadsrc/native/corehost/browserhost/host/assets.ts Outdated
Comment threadsrc/native/corehost/browserhost/host/assets.ts Outdated
Comment threadsrc/native/corehost/browserhost/loader/assets.ts Outdated
Comment threadsrc/mono/browser/build/WasmApp.InTree.props
CopilotAI review requested due to automatic review settings February 11, 2026 21:06

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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.

Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
Comment threadsrc/native/corehost/browserhost/host/assets.ts Outdated
Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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.

Comment threadsrc/coreclr/utilcode/pedecoder.cpp
CopilotAI review requested due to automatic review settings February 12, 2026 21:57
Comment threaddocs/design/mono/webcil.md
# Conflicts:
#	src/native/libs/Common/JavaScript/host/assets.ts
#	src/native/libs/Common/JavaScript/host/host.ts
#	src/native/libs/Common/JavaScript/types/exchange.ts
@adamperlin

Copy link
Copy Markdown
Contributor

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 ?

Definitely agreed that it is out of scope for this PR! I was mostly just wanting to understand what direction we are heading in on the host loading side and what work is still required, so I appreciate the clarification here. I don't have any more feedback, and I think this looks good for now as a start! Since I have limited expertise in this area though, it would be great if @elinor-fung could take a look before this goes in.

CopilotAI review requested due to automatic review settings February 20, 2026 21:34

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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 6 comments.

Comment threadsrc/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilReader.cs
Comment threadsrc/native/libs/Common/JavaScript/loader/assets.ts Outdated
Comment threadsrc/mono/browser/build/WasmApp.InTree.props
Comment threadeng/testing/tests.browser.targets
Comment threadsrc/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/ConvertDllsToWebCil.cs Outdated
CopilotAI review requested due to automatic review settings February 23, 2026 10:40
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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 35 out of 36 changed files in this pull request and generated 3 comments.

Comment threadsrc/coreclr/utilcode/pedecoder.cpp
Comment threadsrc/mono/mono/metadata/webcil-loader.c
Comment threadsrc/mono/browser/build/WasmApp.InTree.props
Comment threadsrc/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilReader.cs Outdated
CopilotAI review requested due to automatic review settings February 23, 2026 13:07

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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 35 out of 36 changed files in this pull request and generated no new comments.

@pavelsavara

Copy link
Copy Markdown
MemberAuthor

it would be great if @elinor-fung could take a look before this goes in.

As we are waiting for more feedback on native part, I split of JS part, for which I'm pretty confident into #124758 and will merge that first.

@elinor-fung

Copy link
Copy Markdown
Member

This feels a bit like PEDecoder has been hijacked to also handle Webcil. There are a number of things on it that simply don't apply or make sense for Webcil. While they can share some logic around reading, they are not fundamentally the same format. I would prefer something like:

  • Separate PEDecoder and WebcilDecoder
  • Helper functions the decoders can use for shared logic like reading the IMAGE_SECTION_HEADER
  • PEImageLayout stops inheriting from PEDecoder and instead contains either a PEDecoder or WebcilDecoder (exposing what is needed for callers that were directly calling into PEDecoder)

I know that may be a significant amount of refactoring, but hopefully somewhat mechanical and something copilot would be good at.

@jkotas

Copy link
Copy Markdown
Member

Also, we won't need to artificially inflate the section headers if we go with Elinor's suggestion.

@pavelsavara

Copy link
Copy Markdown
MemberAuthor

The new PEImageLayout will forward about 80 methods to a particular assembly decoder.
About 50 of them are PE only members (some of them would be shared when we add R2R to webcil later).

It will be massive change, are you sure ?
I will do it into separate branch, so that we could compare it

I think we would like to avoid C++ virtual methods, so that DAC is easier, right ?
Probably via on discriminated union.

@pavelsavara

Copy link
Copy Markdown
MemberAuthor

Closing in favor of #124904

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-wasmWebAssembly architecturearea-Hostos-browserBrowser variant of arch-wasm

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[browser][coreCLR] support loading WebCIL

10 participants

@pavelsavara@davidwrighton@steveisok@adamperlin@elinor-fung@jkotas@kg@maraf@AaronRobinsonMSFT
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

[browser][coreCLR] Loading WebCIL 1.0 - #124268

Closed
pavelsavara wants to merge 29 commits into
dotnet:mainfrom
pavelsavara:loading_webcil1
Closed

[browser][coreCLR] Loading WebCIL 1.0#124268
pavelsavara wants to merge 29 commits into
dotnet:mainfrom
pavelsavara:loading_webcil1

Conversation

@pavelsavara

@pavelsavarapavelsavara commented Feb 11, 2026

Copy link
Copy Markdown
Member

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$di32.const0local.get$nmemory.init1
)

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

Copy link
Copy Markdown
Contributor

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

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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
FileDescription
src/native/libs/Common/JavaScript/types/public-api.tsAdded "webcil1" asset behavior type
src/native/libs/Common/JavaScript/types/exchange.tsAdded instantiateWebCILModule to BrowserHost exports
src/native/libs/Common/JavaScript/cross-module/index.tsUpdated export table to include instantiateWebCILModule
src/native/corehost/browserhost/loader/dotnet.d.tsAdded "webcil1" type definition
src/native/corehost/browserhost/loader/assets.tsAdded WebCIL detection and loading logic, mapping .wasm to .dll paths
src/native/corehost/browserhost/host/index.tsExported instantiateWebCILModule function
src/native/corehost/browserhost/host/host.tsUpdated assembly path mapping to replace .wasm with .dll
src/native/corehost/browserhost/host/assets.tsImplemented instantiateWebCILModule to extract WebCIL payload and register assemblies
src/mono/wasm/Wasm.Build.Tests/Common/BuildEnvironment.csRemoved CoreCLR restriction for WebCIL in tests
src/mono/browser/build/WasmApp.InTree.propsRemoved WasmEnableWebcil=false for CoreCLR, updated TODO comment
src/coreclr/vm/webcildecoder.cppNew file implementing WebCILImageLayout class for parsing and validating WebCIL format
src/coreclr/vm/peimagelayout.hAdded WebCIL header structures and WebCILImageLayout class declaration
src/coreclr/vm/peimagelayout.cppAdded WebCIL format detection in LoadFlat
src/coreclr/vm/peassembly.cppExcluded 32-bit NT headers check for TARGET_BROWSER, added braces for consistency
src/coreclr/vm/coreassemblyspec.cppAdded braces around single-statement if bodies
src/coreclr/vm/CMakeLists.txtAdded webcildecoder.cpp to browser build
src/coreclr/inc/pedecoder.hMade specific PEDecoder methods virtual for browser target to enable WebCILImageLayout overrides
eng/testing/tests.browser.targetsRemoved WasmEnableWebcil=false for CoreCLR, updated TODO comment

Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
@davidwrighton

Copy link
Copy Markdown
Member

Please have @elinor-fung look at this

Comment threadsrc/coreclr/vm/peimagelayout.h Outdated
Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
CopilotAI review requested due to automatic review settings February 11, 2026 20:39

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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.

Comment threadeng/testing/tests.browser.targets
Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
Comment threadsrc/native/corehost/browserhost/host/assets.ts Outdated
Comment threadsrc/native/corehost/browserhost/host/assets.ts Outdated
Comment threadsrc/native/corehost/browserhost/loader/assets.ts Outdated
Comment threadsrc/mono/browser/build/WasmApp.InTree.props
CopilotAI review requested due to automatic review settings February 11, 2026 21:06

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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.

Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
Comment threadsrc/native/corehost/browserhost/host/assets.ts Outdated
Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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.

Comment threadsrc/coreclr/utilcode/pedecoder.cpp
CopilotAI review requested due to automatic review settings February 12, 2026 21:57
Comment threaddocs/design/mono/webcil.md
# Conflicts:
#	src/native/libs/Common/JavaScript/host/assets.ts
#	src/native/libs/Common/JavaScript/host/host.ts
#	src/native/libs/Common/JavaScript/types/exchange.ts
@adamperlin

Copy link
Copy Markdown
Contributor

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 ?

Definitely agreed that it is out of scope for this PR! I was mostly just wanting to understand what direction we are heading in on the host loading side and what work is still required, so I appreciate the clarification here. I don't have any more feedback, and I think this looks good for now as a start! Since I have limited expertise in this area though, it would be great if @elinor-fung could take a look before this goes in.

CopilotAI review requested due to automatic review settings February 20, 2026 21:34

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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 6 comments.

Comment threadsrc/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilReader.cs
Comment threadsrc/native/libs/Common/JavaScript/loader/assets.ts Outdated
Comment threadsrc/mono/browser/build/WasmApp.InTree.props
Comment threadeng/testing/tests.browser.targets
Comment threadsrc/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/ConvertDllsToWebCil.cs Outdated
CopilotAI review requested due to automatic review settings February 23, 2026 10:40
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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 35 out of 36 changed files in this pull request and generated 3 comments.

Comment threadsrc/coreclr/utilcode/pedecoder.cpp
Comment threadsrc/mono/mono/metadata/webcil-loader.c
Comment threadsrc/mono/browser/build/WasmApp.InTree.props
Comment threadsrc/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilReader.cs Outdated
CopilotAI review requested due to automatic review settings February 23, 2026 13:07

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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 35 out of 36 changed files in this pull request and generated no new comments.

@pavelsavara

Copy link
Copy Markdown
MemberAuthor

it would be great if @elinor-fung could take a look before this goes in.

As we are waiting for more feedback on native part, I split of JS part, for which I'm pretty confident into #124758 and will merge that first.

@elinor-fung

Copy link
Copy Markdown
Member

This feels a bit like PEDecoder has been hijacked to also handle Webcil. There are a number of things on it that simply don't apply or make sense for Webcil. While they can share some logic around reading, they are not fundamentally the same format. I would prefer something like:

  • Separate PEDecoder and WebcilDecoder
  • Helper functions the decoders can use for shared logic like reading the IMAGE_SECTION_HEADER
  • PEImageLayout stops inheriting from PEDecoder and instead contains either a PEDecoder or WebcilDecoder (exposing what is needed for callers that were directly calling into PEDecoder)

I know that may be a significant amount of refactoring, but hopefully somewhat mechanical and something copilot would be good at.

@jkotas

Copy link
Copy Markdown
Member

Also, we won't need to artificially inflate the section headers if we go with Elinor's suggestion.

@pavelsavara

Copy link
Copy Markdown
MemberAuthor

The new PEImageLayout will forward about 80 methods to a particular assembly decoder.
About 50 of them are PE only members (some of them would be shared when we add R2R to webcil later).

It will be massive change, are you sure ?
I will do it into separate branch, so that we could compare it

I think we would like to avoid C++ virtual methods, so that DAC is easier, right ?
Probably via on discriminated union.

@pavelsavara

Copy link
Copy Markdown
MemberAuthor

Closing in favor of #124904

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-wasmWebAssembly architecturearea-Hostos-browserBrowser variant of arch-wasm

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[browser][coreCLR] support loading WebCIL

10 participants

@pavelsavara@davidwrighton@steveisok@adamperlin@elinor-fung@jkotas@kg@maraf@AaronRobinsonMSFT
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[browser][coreCLR] Loading WebCIL 1.0 - #124268

Closed
pavelsavara wants to merge 29 commits into
dotnet:mainfrom
pavelsavara:loading_webcil1
Closed

[browser][coreCLR] Loading WebCIL 1.0#124268
pavelsavara wants to merge 29 commits into
dotnet:mainfrom
pavelsavara:loading_webcil1

Conversation

@pavelsavara

@pavelsavarapavelsavara commented Feb 11, 2026

Copy link
Copy Markdown
Member

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$di32.const0local.get$nmemory.init1
)

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

Copy link
Copy Markdown
Contributor

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

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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
FileDescription
src/native/libs/Common/JavaScript/types/public-api.tsAdded "webcil1" asset behavior type
src/native/libs/Common/JavaScript/types/exchange.tsAdded instantiateWebCILModule to BrowserHost exports
src/native/libs/Common/JavaScript/cross-module/index.tsUpdated export table to include instantiateWebCILModule
src/native/corehost/browserhost/loader/dotnet.d.tsAdded "webcil1" type definition
src/native/corehost/browserhost/loader/assets.tsAdded WebCIL detection and loading logic, mapping .wasm to .dll paths
src/native/corehost/browserhost/host/index.tsExported instantiateWebCILModule function
src/native/corehost/browserhost/host/host.tsUpdated assembly path mapping to replace .wasm with .dll
src/native/corehost/browserhost/host/assets.tsImplemented instantiateWebCILModule to extract WebCIL payload and register assemblies
src/mono/wasm/Wasm.Build.Tests/Common/BuildEnvironment.csRemoved CoreCLR restriction for WebCIL in tests
src/mono/browser/build/WasmApp.InTree.propsRemoved WasmEnableWebcil=false for CoreCLR, updated TODO comment
src/coreclr/vm/webcildecoder.cppNew file implementing WebCILImageLayout class for parsing and validating WebCIL format
src/coreclr/vm/peimagelayout.hAdded WebCIL header structures and WebCILImageLayout class declaration
src/coreclr/vm/peimagelayout.cppAdded WebCIL format detection in LoadFlat
src/coreclr/vm/peassembly.cppExcluded 32-bit NT headers check for TARGET_BROWSER, added braces for consistency
src/coreclr/vm/coreassemblyspec.cppAdded braces around single-statement if bodies
src/coreclr/vm/CMakeLists.txtAdded webcildecoder.cpp to browser build
src/coreclr/inc/pedecoder.hMade specific PEDecoder methods virtual for browser target to enable WebCILImageLayout overrides
eng/testing/tests.browser.targetsRemoved WasmEnableWebcil=false for CoreCLR, updated TODO comment

Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
@davidwrighton

Copy link
Copy Markdown
Member

Please have @elinor-fung look at this

Comment threadsrc/coreclr/vm/peimagelayout.h Outdated
Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
CopilotAI review requested due to automatic review settings February 11, 2026 20:39

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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.

Comment threadeng/testing/tests.browser.targets
Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
Comment threadsrc/native/corehost/browserhost/host/assets.ts Outdated
Comment threadsrc/native/corehost/browserhost/host/assets.ts Outdated
Comment threadsrc/native/corehost/browserhost/loader/assets.ts Outdated
Comment threadsrc/mono/browser/build/WasmApp.InTree.props
CopilotAI review requested due to automatic review settings February 11, 2026 21:06

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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.

Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
Comment threadsrc/native/corehost/browserhost/host/assets.ts Outdated
Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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.

Comment threadsrc/coreclr/utilcode/pedecoder.cpp
CopilotAI review requested due to automatic review settings February 12, 2026 21:57
Comment threaddocs/design/mono/webcil.md
# Conflicts:
#	src/native/libs/Common/JavaScript/host/assets.ts
#	src/native/libs/Common/JavaScript/host/host.ts
#	src/native/libs/Common/JavaScript/types/exchange.ts
@adamperlin

Copy link
Copy Markdown
Contributor

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 ?

Definitely agreed that it is out of scope for this PR! I was mostly just wanting to understand what direction we are heading in on the host loading side and what work is still required, so I appreciate the clarification here. I don't have any more feedback, and I think this looks good for now as a start! Since I have limited expertise in this area though, it would be great if @elinor-fung could take a look before this goes in.

CopilotAI review requested due to automatic review settings February 20, 2026 21:34

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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 6 comments.

Comment threadsrc/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilReader.cs
Comment threadsrc/native/libs/Common/JavaScript/loader/assets.ts Outdated
Comment threadsrc/mono/browser/build/WasmApp.InTree.props
Comment threadeng/testing/tests.browser.targets
Comment threadsrc/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/ConvertDllsToWebCil.cs Outdated
CopilotAI review requested due to automatic review settings February 23, 2026 10:40
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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 35 out of 36 changed files in this pull request and generated 3 comments.

Comment threadsrc/coreclr/utilcode/pedecoder.cpp
Comment threadsrc/mono/mono/metadata/webcil-loader.c
Comment threadsrc/mono/browser/build/WasmApp.InTree.props
Comment threadsrc/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilReader.cs Outdated
CopilotAI review requested due to automatic review settings February 23, 2026 13:07

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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 35 out of 36 changed files in this pull request and generated no new comments.

@pavelsavara

Copy link
Copy Markdown
MemberAuthor

it would be great if @elinor-fung could take a look before this goes in.

As we are waiting for more feedback on native part, I split of JS part, for which I'm pretty confident into #124758 and will merge that first.

@elinor-fung

Copy link
Copy Markdown
Member

This feels a bit like PEDecoder has been hijacked to also handle Webcil. There are a number of things on it that simply don't apply or make sense for Webcil. While they can share some logic around reading, they are not fundamentally the same format. I would prefer something like:

  • Separate PEDecoder and WebcilDecoder
  • Helper functions the decoders can use for shared logic like reading the IMAGE_SECTION_HEADER
  • PEImageLayout stops inheriting from PEDecoder and instead contains either a PEDecoder or WebcilDecoder (exposing what is needed for callers that were directly calling into PEDecoder)

I know that may be a significant amount of refactoring, but hopefully somewhat mechanical and something copilot would be good at.

@jkotas

Copy link
Copy Markdown
Member

Also, we won't need to artificially inflate the section headers if we go with Elinor's suggestion.

@pavelsavara

Copy link
Copy Markdown
MemberAuthor

The new PEImageLayout will forward about 80 methods to a particular assembly decoder.
About 50 of them are PE only members (some of them would be shared when we add R2R to webcil later).

It will be massive change, are you sure ?
I will do it into separate branch, so that we could compare it

I think we would like to avoid C++ virtual methods, so that DAC is easier, right ?
Probably via on discriminated union.

@pavelsavara

Copy link
Copy Markdown
MemberAuthor

Closing in favor of #124904

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-wasmWebAssembly architecturearea-Hostos-browserBrowser variant of arch-wasm

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[browser][coreCLR] support loading WebCIL

10 participants

@pavelsavara@davidwrighton@steveisok@adamperlin@elinor-fung@jkotas@kg@maraf@AaronRobinsonMSFT
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[browser][coreCLR] Loading WebCIL 1.0 - #124268

Closed
pavelsavara wants to merge 29 commits into
dotnet:mainfrom
pavelsavara:loading_webcil1
Closed

[browser][coreCLR] Loading WebCIL 1.0#124268
pavelsavara wants to merge 29 commits into
dotnet:mainfrom
pavelsavara:loading_webcil1

Conversation

@pavelsavara

@pavelsavarapavelsavara commented Feb 11, 2026

Copy link
Copy Markdown
Member

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$di32.const0local.get$nmemory.init1
)

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

Copy link
Copy Markdown
Contributor

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

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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
FileDescription
src/native/libs/Common/JavaScript/types/public-api.tsAdded "webcil1" asset behavior type
src/native/libs/Common/JavaScript/types/exchange.tsAdded instantiateWebCILModule to BrowserHost exports
src/native/libs/Common/JavaScript/cross-module/index.tsUpdated export table to include instantiateWebCILModule
src/native/corehost/browserhost/loader/dotnet.d.tsAdded "webcil1" type definition
src/native/corehost/browserhost/loader/assets.tsAdded WebCIL detection and loading logic, mapping .wasm to .dll paths
src/native/corehost/browserhost/host/index.tsExported instantiateWebCILModule function
src/native/corehost/browserhost/host/host.tsUpdated assembly path mapping to replace .wasm with .dll
src/native/corehost/browserhost/host/assets.tsImplemented instantiateWebCILModule to extract WebCIL payload and register assemblies
src/mono/wasm/Wasm.Build.Tests/Common/BuildEnvironment.csRemoved CoreCLR restriction for WebCIL in tests
src/mono/browser/build/WasmApp.InTree.propsRemoved WasmEnableWebcil=false for CoreCLR, updated TODO comment
src/coreclr/vm/webcildecoder.cppNew file implementing WebCILImageLayout class for parsing and validating WebCIL format
src/coreclr/vm/peimagelayout.hAdded WebCIL header structures and WebCILImageLayout class declaration
src/coreclr/vm/peimagelayout.cppAdded WebCIL format detection in LoadFlat
src/coreclr/vm/peassembly.cppExcluded 32-bit NT headers check for TARGET_BROWSER, added braces for consistency
src/coreclr/vm/coreassemblyspec.cppAdded braces around single-statement if bodies
src/coreclr/vm/CMakeLists.txtAdded webcildecoder.cpp to browser build
src/coreclr/inc/pedecoder.hMade specific PEDecoder methods virtual for browser target to enable WebCILImageLayout overrides
eng/testing/tests.browser.targetsRemoved WasmEnableWebcil=false for CoreCLR, updated TODO comment

Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
@davidwrighton

Copy link
Copy Markdown
Member

Please have @elinor-fung look at this

Comment threadsrc/coreclr/vm/peimagelayout.h Outdated
Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
CopilotAI review requested due to automatic review settings February 11, 2026 20:39

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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.

Comment threadeng/testing/tests.browser.targets
Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
Comment threadsrc/native/corehost/browserhost/host/assets.ts Outdated
Comment threadsrc/native/corehost/browserhost/host/assets.ts Outdated
Comment threadsrc/native/corehost/browserhost/loader/assets.ts Outdated
Comment threadsrc/mono/browser/build/WasmApp.InTree.props
CopilotAI review requested due to automatic review settings February 11, 2026 21:06

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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.

Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
Comment threadsrc/native/corehost/browserhost/host/assets.ts Outdated
Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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.

Comment threadsrc/coreclr/utilcode/pedecoder.cpp
CopilotAI review requested due to automatic review settings February 12, 2026 21:57
Comment threaddocs/design/mono/webcil.md
# Conflicts:
#	src/native/libs/Common/JavaScript/host/assets.ts
#	src/native/libs/Common/JavaScript/host/host.ts
#	src/native/libs/Common/JavaScript/types/exchange.ts
@adamperlin

Copy link
Copy Markdown
Contributor

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 ?

Definitely agreed that it is out of scope for this PR! I was mostly just wanting to understand what direction we are heading in on the host loading side and what work is still required, so I appreciate the clarification here. I don't have any more feedback, and I think this looks good for now as a start! Since I have limited expertise in this area though, it would be great if @elinor-fung could take a look before this goes in.

CopilotAI review requested due to automatic review settings February 20, 2026 21:34

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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 6 comments.

Comment threadsrc/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilReader.cs
Comment threadsrc/native/libs/Common/JavaScript/loader/assets.ts Outdated
Comment threadsrc/mono/browser/build/WasmApp.InTree.props
Comment threadeng/testing/tests.browser.targets
Comment threadsrc/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/ConvertDllsToWebCil.cs Outdated
CopilotAI review requested due to automatic review settings February 23, 2026 10:40
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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 35 out of 36 changed files in this pull request and generated 3 comments.

Comment threadsrc/coreclr/utilcode/pedecoder.cpp
Comment threadsrc/mono/mono/metadata/webcil-loader.c
Comment threadsrc/mono/browser/build/WasmApp.InTree.props
Comment threadsrc/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilReader.cs Outdated
CopilotAI review requested due to automatic review settings February 23, 2026 13:07

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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 35 out of 36 changed files in this pull request and generated no new comments.

@pavelsavara

Copy link
Copy Markdown
MemberAuthor

it would be great if @elinor-fung could take a look before this goes in.

As we are waiting for more feedback on native part, I split of JS part, for which I'm pretty confident into #124758 and will merge that first.

@elinor-fung

Copy link
Copy Markdown
Member

This feels a bit like PEDecoder has been hijacked to also handle Webcil. There are a number of things on it that simply don't apply or make sense for Webcil. While they can share some logic around reading, they are not fundamentally the same format. I would prefer something like:

  • Separate PEDecoder and WebcilDecoder
  • Helper functions the decoders can use for shared logic like reading the IMAGE_SECTION_HEADER
  • PEImageLayout stops inheriting from PEDecoder and instead contains either a PEDecoder or WebcilDecoder (exposing what is needed for callers that were directly calling into PEDecoder)

I know that may be a significant amount of refactoring, but hopefully somewhat mechanical and something copilot would be good at.

@jkotas

Copy link
Copy Markdown
Member

Also, we won't need to artificially inflate the section headers if we go with Elinor's suggestion.

@pavelsavara

Copy link
Copy Markdown
MemberAuthor

The new PEImageLayout will forward about 80 methods to a particular assembly decoder.
About 50 of them are PE only members (some of them would be shared when we add R2R to webcil later).

It will be massive change, are you sure ?
I will do it into separate branch, so that we could compare it

I think we would like to avoid C++ virtual methods, so that DAC is easier, right ?
Probably via on discriminated union.

@pavelsavara

Copy link
Copy Markdown
MemberAuthor

Closing in favor of #124904

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-wasmWebAssembly architecturearea-Hostos-browserBrowser variant of arch-wasm

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[browser][coreCLR] support loading WebCIL

10 participants

@pavelsavara@davidwrighton@steveisok@adamperlin@elinor-fung@jkotas@kg@maraf@AaronRobinsonMSFT
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

[browser][coreCLR] Loading WebCIL 1.0 - #124268

Closed
pavelsavara wants to merge 29 commits into
dotnet:mainfrom
pavelsavara:loading_webcil1
Closed

[browser][coreCLR] Loading WebCIL 1.0#124268
pavelsavara wants to merge 29 commits into
dotnet:mainfrom
pavelsavara:loading_webcil1

Conversation

@pavelsavara

@pavelsavarapavelsavara commented Feb 11, 2026

Copy link
Copy Markdown
Member

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$di32.const0local.get$nmemory.init1
)

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

Copy link
Copy Markdown
Contributor

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

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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
FileDescription
src/native/libs/Common/JavaScript/types/public-api.tsAdded "webcil1" asset behavior type
src/native/libs/Common/JavaScript/types/exchange.tsAdded instantiateWebCILModule to BrowserHost exports
src/native/libs/Common/JavaScript/cross-module/index.tsUpdated export table to include instantiateWebCILModule
src/native/corehost/browserhost/loader/dotnet.d.tsAdded "webcil1" type definition
src/native/corehost/browserhost/loader/assets.tsAdded WebCIL detection and loading logic, mapping .wasm to .dll paths
src/native/corehost/browserhost/host/index.tsExported instantiateWebCILModule function
src/native/corehost/browserhost/host/host.tsUpdated assembly path mapping to replace .wasm with .dll
src/native/corehost/browserhost/host/assets.tsImplemented instantiateWebCILModule to extract WebCIL payload and register assemblies
src/mono/wasm/Wasm.Build.Tests/Common/BuildEnvironment.csRemoved CoreCLR restriction for WebCIL in tests
src/mono/browser/build/WasmApp.InTree.propsRemoved WasmEnableWebcil=false for CoreCLR, updated TODO comment
src/coreclr/vm/webcildecoder.cppNew file implementing WebCILImageLayout class for parsing and validating WebCIL format
src/coreclr/vm/peimagelayout.hAdded WebCIL header structures and WebCILImageLayout class declaration
src/coreclr/vm/peimagelayout.cppAdded WebCIL format detection in LoadFlat
src/coreclr/vm/peassembly.cppExcluded 32-bit NT headers check for TARGET_BROWSER, added braces for consistency
src/coreclr/vm/coreassemblyspec.cppAdded braces around single-statement if bodies
src/coreclr/vm/CMakeLists.txtAdded webcildecoder.cpp to browser build
src/coreclr/inc/pedecoder.hMade specific PEDecoder methods virtual for browser target to enable WebCILImageLayout overrides
eng/testing/tests.browser.targetsRemoved WasmEnableWebcil=false for CoreCLR, updated TODO comment

Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
@davidwrighton

Copy link
Copy Markdown
Member

Please have @elinor-fung look at this

Comment threadsrc/coreclr/vm/peimagelayout.h Outdated
Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
CopilotAI review requested due to automatic review settings February 11, 2026 20:39

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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.

Comment threadeng/testing/tests.browser.targets
Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
Comment threadsrc/native/corehost/browserhost/host/assets.ts Outdated
Comment threadsrc/native/corehost/browserhost/host/assets.ts Outdated
Comment threadsrc/native/corehost/browserhost/loader/assets.ts Outdated
Comment threadsrc/mono/browser/build/WasmApp.InTree.props
CopilotAI review requested due to automatic review settings February 11, 2026 21:06

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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.

Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated
Comment threadsrc/native/corehost/browserhost/host/assets.ts Outdated
Comment threadsrc/coreclr/vm/webcildecoder.cpp Outdated

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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.

Comment threadsrc/coreclr/utilcode/pedecoder.cpp
CopilotAI review requested due to automatic review settings February 12, 2026 21:57
Comment threaddocs/design/mono/webcil.md
# Conflicts:
#	src/native/libs/Common/JavaScript/host/assets.ts
#	src/native/libs/Common/JavaScript/host/host.ts
#	src/native/libs/Common/JavaScript/types/exchange.ts
@adamperlin

Copy link
Copy Markdown
Contributor

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 ?

Definitely agreed that it is out of scope for this PR! I was mostly just wanting to understand what direction we are heading in on the host loading side and what work is still required, so I appreciate the clarification here. I don't have any more feedback, and I think this looks good for now as a start! Since I have limited expertise in this area though, it would be great if @elinor-fung could take a look before this goes in.

CopilotAI review requested due to automatic review settings February 20, 2026 21:34

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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 6 comments.

Comment threadsrc/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilReader.cs
Comment threadsrc/native/libs/Common/JavaScript/loader/assets.ts Outdated
Comment threadsrc/mono/browser/build/WasmApp.InTree.props
Comment threadeng/testing/tests.browser.targets
Comment threadsrc/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/ConvertDllsToWebCil.cs Outdated
CopilotAI review requested due to automatic review settings February 23, 2026 10:40
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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 35 out of 36 changed files in this pull request and generated 3 comments.

Comment threadsrc/coreclr/utilcode/pedecoder.cpp
Comment threadsrc/mono/mono/metadata/webcil-loader.c
Comment threadsrc/mono/browser/build/WasmApp.InTree.props
Comment threadsrc/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilReader.cs Outdated
CopilotAI review requested due to automatic review settings February 23, 2026 13:07

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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 35 out of 36 changed files in this pull request and generated no new comments.

@pavelsavara

Copy link
Copy Markdown
MemberAuthor

it would be great if @elinor-fung could take a look before this goes in.

As we are waiting for more feedback on native part, I split of JS part, for which I'm pretty confident into #124758 and will merge that first.

@elinor-fung

Copy link
Copy Markdown
Member

This feels a bit like PEDecoder has been hijacked to also handle Webcil. There are a number of things on it that simply don't apply or make sense for Webcil. While they can share some logic around reading, they are not fundamentally the same format. I would prefer something like:

  • Separate PEDecoder and WebcilDecoder
  • Helper functions the decoders can use for shared logic like reading the IMAGE_SECTION_HEADER
  • PEImageLayout stops inheriting from PEDecoder and instead contains either a PEDecoder or WebcilDecoder (exposing what is needed for callers that were directly calling into PEDecoder)

I know that may be a significant amount of refactoring, but hopefully somewhat mechanical and something copilot would be good at.

@jkotas

Copy link
Copy Markdown
Member

Also, we won't need to artificially inflate the section headers if we go with Elinor's suggestion.

@pavelsavara

Copy link
Copy Markdown
MemberAuthor

The new PEImageLayout will forward about 80 methods to a particular assembly decoder.
About 50 of them are PE only members (some of them would be shared when we add R2R to webcil later).

It will be massive change, are you sure ?
I will do it into separate branch, so that we could compare it

I think we would like to avoid C++ virtual methods, so that DAC is easier, right ?
Probably via on discriminated union.

@pavelsavara

Copy link
Copy Markdown
MemberAuthor

Closing in favor of #124904

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-wasmWebAssembly architecturearea-Hostos-browserBrowser variant of arch-wasm

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[browser][coreCLR] support loading WebCIL

10 participants

@pavelsavara@davidwrighton@steveisok@adamperlin@elinor-fung@jkotas@kg@maraf@AaronRobinsonMSFT