Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
ed1b70b
[wasm] Dispose the metadata provider in WebcilReader
pavelsavara Sep 7, 2026
a30d8e1
[wasm] Match prebuilt R2R images by MVID instead of assembly version
pavelsavara Sep 7, 2026
d8c1d10
[wasm][coreclr] Move the ReadyToRun crossgen2 wiring into the WebAsse…
pavelsavara Sep 7, 2026
b4110b1
[wasm][coreclr] Wire ReadyToRun into the WebAssembly publish and buil…
pavelsavara Sep 7, 2026
9330b80
[wasm][coreclr] Trigger the native relink on WasmBuildNative as well
pavelsavara Sep 7, 2026
d836bcd
[wasm] Do not reference ILLink.Tasks from the wasm nested publish
pavelsavara Sep 7, 2026
9c51a87
[wasm][coreclr] Add Wasm.Build.Tests coverage for ReadyToRun
pavelsavara Sep 7, 2026
e00a2dd
[wasm][coreclr] Run the JavaScript interop tests with ReadyToRun
pavelsavara Sep 7, 2026
9cbc88f
[wasm][coreclr] Resolve crossgen2 for ReadyToRun via the SDK-restored…
pavelsavara Sep 8, 2026
aee15bf
[wasm][coreclr] Address PR review feedback on the ReadyToRun wiring
pavelsavara Sep 8, 2026
89fdaf4
[wasm][coreclr] Move test-only asset-copy targets to the test infra
pavelsavara Sep 9, 2026
528ec51
Update ReferenceCopyLocalPaths for trimmed closure
pavelsavara Sep 9, 2026
4b894b6
Merge branch 'main' into browsehost_load_r2r_9
pavelsavara Sep 9, 2026
1407d12
fix
pavelsavara Sep 9, 2026
b126e04
publish incrementality fix
pavelsavara Sep 10, 2026
245cb70
Merge branch 'main' into browsehost_load_r2r_9
pavelsavara Sep 10, 2026
7b56eec
Merge branch 'main' into browsehost_load_r2r_9
pavelsavara Sep 14, 2026
75fa704
Merge branch 'main' into browsehost_load_r2r_9
pavelsavara Sep 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions eng/liveILLink.targets
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@

<ItemGroup Condition="'$(_RequiresLiveILLink)' == 'true'">
<!-- The assembly shouldn't be referenced, nor promoted to a package dependency, nor copied to the output directory. -->
<!-- The wasm nested publish evaluates this project with different global properties, so MSBuild builds it a
second time and copies obj -> bin over the assembly the outer pass already loaded (MSB3027). The outer
pass has built it by then, so referencing it again from the nested pass is redundant as well as harmful. -->
<ProjectReference Include="$(_ILLinkTasksSourceDir)ILLink.Tasks.csproj"
Condition="'$(WasmBuildingForNestedPublish)' != 'true'"
ReferenceOutputAssembly="false"
PrivateAssets="all"
Private="false"
Expand Down
33 changes: 33 additions & 0 deletions eng/testing/tests.browser.targets
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,39 @@
so copy framework files to the output directory. See https://github.com/dotnet/runtime/issues/127257. -->
<_WasmFrameworkCopyToOutputDirectory>PreserveNewest</_WasmFrameworkCopyToOutputDirectory>
</PropertyGroup>

<!-- CoreCLR-only, test-infra-only. These two targets exist solely because library tests set
_WasmFrameworkCopyToOutputDirectory=PreserveNewest above (a real app leaves the default Never), so they
live here rather than in the shipped WebAssembly SDK. The CoreCLR nested publish shares $(OutDir) and runs
its build-phase webcil conversion before ILLink/crossgen, so without suppression it would stage the
UNTRIMMED framework into the served bin/ directory beside the outer build's trimmed R2R set. -->
<Target Name="_WasmCoreClrSuppressNestedPublishAssetCopy"
Condition="'$(RuntimeFlavor)' == 'CoreCLR' and '$(WasmBuildingForNestedPublish)' == 'true'"
BeforeTargets="_ComputeWasmBuildCandidates">
<PropertyGroup>
<_WasmFrameworkCopyToOutputDirectory>Never</_WasmFrameworkCopyToOutputDirectory>
</PropertyGroup>
<ItemGroup>
<ReferenceCopyLocalPaths Update="@(ReferenceCopyLocalPaths)" CopyToOutputDirectory="Never" />
</ItemGroup>
</Target>

<!-- The metadata set above is STICKY: a native relink returns the nested publish's assembly set to the outer
build, metadata included, and the outer build would then define those assets in the manifest yet never
copy them - the boot config requests a fingerprint that is not on disk and startup fails on a 500. -->
<Target Name="_WasmCoreClrRestoreCopyToOutputDirectory"
Comment thread
pavelsavara marked this conversation as resolved.
Condition="'$(RuntimeFlavor)' == 'CoreCLR' and '$(_WasmEnableWebcil)' == 'true' and '$(WasmBuildingForNestedPublish)' != 'true'"
BeforeTargets="_ComputeWasmBuildCandidates">
<ItemGroup>
<ReferenceCopyLocalPaths Update="@(ReferenceCopyLocalPaths)"
Condition="'%(ReferenceCopyLocalPaths.CopyToOutputDirectory)' == 'Never'"
CopyToOutputDirectory="$(_WasmFrameworkCopyToOutputDirectory)" />
<WasmAssembliesFinal Update="@(WasmAssembliesFinal)"
Condition="'%(WasmAssembliesFinal.CopyToOutputDirectory)' == 'Never'"
CopyToOutputDirectory="$(_WasmFrameworkCopyToOutputDirectory)" />
</ItemGroup>
</Target>

<PropertyGroup Condition="'$(RuntimeFlavor)' == 'CoreCLR'">
<WasmTestSupport>true</WasmTestSupport>
<WasmTestExitOnUnhandledError>true</WasmTestExitOnUnhandledError>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
Suppress the NU1511 warning in the whole project as putting it on a P2P doesn't work: https://github.com/NuGet/Home/issues/14121 -->
<NoWarn>$(NoWarn);NU1511</NoWarn>
<WasmEnableStreamingResponse>false</WasmEnableStreamingResponse>

<!-- Remove when PublishReadyToRun becomes default https://github.com/dotnet/runtime/issues/132466 -->
<PublishReadyToRun Condition="'$(PublishReadyToRun)' == '' and '$(RuntimeFlavor)' == 'CoreCLR'">true</PublishReadyToRun>
</PropertyGroup>

<!-- Make debugging easier -->
Expand Down
14 changes: 14 additions & 0 deletions src/libraries/sendtohelix-browser.targets
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,20 @@
<HelixCorrelationPayload Include="$(MonoTargetsTasksDir)" Destination="build/MonoTargetsTasks" />
</ItemGroup>

<!-- CoreCLR ReadyToRun: ship the wasm-aware Crossgen2Tasks shim (the wasm-container crossgen tasks) so the
Wasm.Build.Tests opt-in finds it under BASE_DIR. The crossgen2 tool itself is resolved on the worker
from the SDK crossgen2 pack (which the SDK restores when PublishReadyToRun is set), so it is only shipped
as a correlation payload when the in-build crossgen2 is present in this leg (dev/in-tree). The shim ships
whenever it is built - it is gated on its own path, not on the crossgen2 bin dir, which the WBT test leg
does not carry. -->
<ItemGroup Condition="'$(NeedsEMSDK)' == 'true' and '$(RuntimeFlavor)' == 'CoreCLR' and Exists('$(ArtifactsBinDir)Crossgen2Tasks\$(TasksConfiguration)\')">
<HelixCorrelationPayload Include="$(ArtifactsBinDir)Crossgen2Tasks\$(TasksConfiguration)\"
Destination="Crossgen2Tasks/$(Configuration)" />
</ItemGroup>
<ItemGroup Condition="'$(NeedsEMSDK)' == 'true' and '$(RuntimeFlavor)' == 'CoreCLR' and Exists('$(Crossgen2InBuildDir)')">
<HelixCorrelationPayload Include="$(Crossgen2InBuildDir)" Destination="coreclr/browser.wasm.$(Configuration)/$(BuildArchitecture)/crossgen2" />
</ItemGroup>

<!-- copy node separately only if EMSDK is not being included -->
<ItemGroup Condition="'$(IncludeNodePayload)' == 'true'">
<HelixCorrelationPayload Include="$(EmSdkDirForHelixPayload)node" Destination="build/emsdk-node" />
Expand Down
9 changes: 0 additions & 9 deletions src/mono/browser/build/WasmApp.InTree.props
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,6 @@
<UseMonoRuntime>true</UseMonoRuntime>
</PropertyGroup>

<!-- In-tree R2R uses the in-build crossgen2. These two hooks must be props-time (property defaults live
in the CoreCLR .targets); both are inert unless PublishReadyToRun. See dotnet/runtime#121257. -->
<PropertyGroup Condition="'$(RuntimeFlavor)' == 'CoreCLR' and '$(TargetOS)' == 'browser'">
<AfterMicrosoftNETSdkTargets Condition="'$(Crossgen2SdkOverrideTargetsPath)' != '' and Exists('$(Crossgen2SdkOverrideTargetsPath)')">$(AfterMicrosoftNETSdkTargets);$(Crossgen2SdkOverrideTargetsPath)</AfterMicrosoftNETSdkTargets>
<AfterMicrosoftNETSdkTargets>$(AfterMicrosoftNETSdkTargets);$(MSBuildThisFileDirectory)WasmApp.ReadyToRun.targets</AfterMicrosoftNETSdkTargets>
</PropertyGroup>
<Import Project="$(Crossgen2SdkOverridePropsPath)"
Condition="'$(RuntimeFlavor)' == 'CoreCLR' and '$(TargetOS)' == 'browser' and '$(Crossgen2SdkOverridePropsPath)' != '' and Exists('$(Crossgen2SdkOverridePropsPath)')" />

<PropertyGroup Condition="'$(IsTestProject)' == 'true' or '$(IsOutputTypeLibrary)' == 'true'">
<OutputType>library</OutputType>
</PropertyGroup>
Expand Down
18 changes: 0 additions & 18 deletions src/mono/browser/build/WasmApp.ReadyToRun.targets

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<!--
***********************************************************************************************
Microsoft.NET.Sdk.WebAssembly.Browser.CoreCLR.ReadyToRun.targets

ReadyToRun compiler override for CoreCLR browser-wasm, appended to AfterMicrosoftNETSdkTargets by
Microsoft.NET.Sdk.WebAssembly.Browser.CoreCLR.props so it imports after Microsoft.NET.Publish.targets and
its ResolveReadyToRunCompilers wins. Mirrors AppleBuild.ReadyToRun.targets.

When an in-build crossgen2 is available (in-tree / dev builds) the Crossgen2Tool item is set from it. Otherwise
the SDK-resolved crossgen2 pack (@(ResolvedCrossgen2Pack), which the SDK restores when PublishReadyToRun is set)
is used - so this override never shadows that resolution into an empty tool. Inert for normal consumers.

Copyright (c) .NET Foundation. All rights reserved.
***********************************************************************************************
-->
<Project>
<Target Name="ResolveReadyToRunCompilers"
Condition="'$(PublishReadyToRun)' == 'true'"
DependsOnTargets="$(ResolveReadyToRunCompilersDependsOn)">
<PropertyGroup>
<_WasmCrossgen2InBuildUsable Condition="'$(Crossgen2InBuildDir)' != '' and Exists('$(Crossgen2InBuildDir)')">true</_WasmCrossgen2InBuildUsable>
<_WasmCrossgen2ExeSuffix Condition="'$(ExeSuffix)' != ''">$(ExeSuffix)</_WasmCrossgen2ExeSuffix>
<_WasmCrossgen2ExeSuffix Condition="'$(_WasmCrossgen2ExeSuffix)' == '' and $([MSBuild]::IsOSPlatform('windows'))">.exe</_WasmCrossgen2ExeSuffix>
<!-- Accept both layouts: the raw in-build dir has crossgen2 at its root, the shipped
Microsoft.NETCore.App.Crossgen2.<hostRid> pack has it under tools/. -->
<_WasmCrossgen2RootExe>$([MSBuild]::NormalizePath('$(Crossgen2InBuildDir)', 'crossgen2$(_WasmCrossgen2ExeSuffix)'))</_WasmCrossgen2RootExe>
<_WasmCrossgen2ToolsExe>$([MSBuild]::NormalizePath('$([MSBuild]::NormalizeDirectory('$(Crossgen2InBuildDir)', 'tools'))', 'crossgen2$(_WasmCrossgen2ExeSuffix)'))</_WasmCrossgen2ToolsExe>
<Crossgen2Path Condition="'$(_WasmCrossgen2InBuildUsable)' == 'true' and Exists('$(_WasmCrossgen2RootExe)')">$(_WasmCrossgen2RootExe)</Crossgen2Path>
<Crossgen2Path Condition="'$(_WasmCrossgen2InBuildUsable)' == 'true' and '$(Crossgen2Path)' == '' and Exists('$(_WasmCrossgen2ToolsExe)')">$(_WasmCrossgen2ToolsExe)</Crossgen2Path>
<!-- Directory of the resolved crossgen2, so _WasmCoreClrConservativeR2RInputs can add the wasm JIT
crossgen2 auto-loads to the R2R inputs. -->
<_WasmResolvedCrossgen2Dir Condition="'$(Crossgen2Path)' != ''">$([MSBuild]::EnsureTrailingSlash($([System.IO.Path]::GetDirectoryName('$(Crossgen2Path)'))))</_WasmResolvedCrossgen2Dir>
<!-- RunReadyToRunCompiler (NETSDK1158) requires non-empty TargetOS/TargetArch on the Crossgen2Tool item
when JitPath is unset (crossgen2 then auto-loads its own clrjit_universal_wasm). In-tree builds set
$(TargetOS)/$(TargetArchitecture); a standalone SDK app does not. -->
<_WasmR2RTargetOS Condition="'$(TargetOS)' != ''">$(TargetOS)</_WasmR2RTargetOS>
<_WasmR2RTargetOS Condition="'$(_WasmR2RTargetOS)' == ''">browser</_WasmR2RTargetOS>
<_WasmR2RTargetArch Condition="'$(TargetArchitecture)' != ''">$(TargetArchitecture)</_WasmR2RTargetArch>
<_WasmR2RTargetArch Condition="'$(_WasmR2RTargetArch)' == ''">wasm</_WasmR2RTargetArch>
</PropertyGroup>

<!-- Preferred: the in-build crossgen2 (in-tree and dev out-of-tree builds that pass Crossgen2InBuildDir).
When the dir is present but contains no crossgen2, Crossgen2Path stays empty and we fall through to the
pack fallback (and ultimately _WasmCoreClrValidateReadyToRun's actionable error) instead of naming a
non-existent executable. -->
<ItemGroup Condition="'$(Crossgen2Path)' != ''">
<Crossgen2Tool Include="$(Crossgen2Path)"
TargetArch="$(_WasmR2RTargetArch)"
TargetOS="$(_WasmR2RTargetOS)"
PerfmapFormatVersion="$(PublishReadyToRunPerfmapFormatVersion)" />
</ItemGroup>

<!-- Fallback: the SDK-resolved crossgen2 pack (restored when PublishReadyToRun is set, e.g. the no-workload
Helix leg). Mirrors the resolver in Microsoft.NET.CrossGen.targets so the tool is never left empty. -->
<ResolveReadyToRunCompilers Condition="'$(Crossgen2Path)' == '' and '@(ResolvedCrossgen2Pack)' != ''"
RuntimePacks="@(ResolvedRuntimePack)"
Crossgen2Packs="@(ResolvedCrossgen2Pack)"
TargetingPacks="@(ResolvedTargetingPack)"
RuntimeGraphPath="$(RuntimeIdentifierGraphPath)"
NETCoreSdkRuntimeIdentifier="$(NETCoreSdkRuntimeIdentifier)"
EmitSymbols="$(PublishReadyToRunEmitSymbols)"
ReadyToRunUseCrossgen2="$(PublishReadyToRunUseCrossgen2)"
PerfmapFormatVersion="$(PublishReadyToRunPerfmapFormatVersion)">
<Output TaskParameter="CrossgenTool" ItemName="CrossgenTool" />
<Output TaskParameter="Crossgen2Tool" ItemName="Crossgen2Tool" />
</ResolveReadyToRunCompilers>
</Target>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<!--
***********************************************************************************************
Microsoft.NET.Sdk.WebAssembly.Browser.CoreCLR.props

CoreCLR browser-wasm ReadyToRun wiring, isolated from Mono. Imported (props-time) from
Microsoft.NET.Sdk.WebAssembly.Browser.props only when an in-build crossgen2 is provided.

The base SDK's ReadyToRun pipeline predates wasm support (dotnet/sdk#55785) and emits composite images
for wasm, which strip the assembly manifest so the runtime fails coreclr_initialize with 0x80131018.
Activate the runtime's wasm-aware Crossgen2Tasks shim and the ResolveReadyToRunCompilers override, both
appended to AfterMicrosoftNETSdkTargets, shim first so the override wins. Mirrors AppleBuild.props.

Inert for Mono and for normal consumers, which resolve crossgen2 through the base SDK.

Copyright (c) .NET Foundation. All rights reserved.
***********************************************************************************************
-->
<Project>
<Import Project="$(Crossgen2SdkOverridePropsPath)"
Condition="'$(Crossgen2SdkOverridePropsPath)' != '' and Exists('$(Crossgen2SdkOverridePropsPath)')" />

<PropertyGroup>
Comment thread
pavelsavara marked this conversation as resolved.
<AfterMicrosoftNETSdkTargets Condition="'$(Crossgen2SdkOverrideTargetsPath)' != '' and Exists('$(Crossgen2SdkOverrideTargetsPath)')">$(AfterMicrosoftNETSdkTargets);$(Crossgen2SdkOverrideTargetsPath)</AfterMicrosoftNETSdkTargets>
Comment thread
pavelsavara marked this conversation as resolved.
<AfterMicrosoftNETSdkTargets>$(AfterMicrosoftNETSdkTargets);$(MSBuildThisFileDirectory)Microsoft.NET.Sdk.WebAssembly.Browser.CoreCLR.ReadyToRun.targets</AfterMicrosoftNETSdkTargets>
</PropertyGroup>
</Project>
Loading
Loading