From d712202748b36662e4c7a0ac817bfbd07f2268e6 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Fri, 10 Jul 2026 19:12:08 +0200 Subject: [PATCH 1/3] [wasm] Bump Linux helix image to exnref-capable V8, re-enable tests (#129849) The ubuntu-26.04 helix-webassembly image now bakes V8 15.2.47, which supports --experimental-wasm-exnref. Bump the pinned digest and revert the two temporary workarounds (sendToHelix:false for Mono runtime tests, SkipTrimmingTestsRun=true for trimming tests) that were skipping V8 execution while the old V8 15.0.243 image was in use. --- eng/pipelines/common/templates/wasm-runtime-tests.yml | 5 ----- eng/pipelines/coreclr/templates/helix-queues-setup.yml | 4 ++-- eng/pipelines/libraries/helix-queues-setup.yml | 6 +++--- eng/pipelines/runtime-linker-tests.yml | 8 +------- 4 files changed, 6 insertions(+), 17 deletions(-) diff --git a/eng/pipelines/common/templates/wasm-runtime-tests.yml b/eng/pipelines/common/templates/wasm-runtime-tests.yml index 47afc62f16ce54..8f84bdb93038db 100644 --- a/eng/pipelines/common/templates/wasm-runtime-tests.yml +++ b/eng/pipelines/common/templates/wasm-runtime-tests.yml @@ -48,10 +48,5 @@ jobs: creator: dotnet-bot testRunNamePrefixSuffix: Mono_$(_BuildConfig) testBuildArgs: /p:InstallV8ForTests=false - # Build the runtime tests for browser, but don't send them to Helix to run on V8: the - # V8 baked into the helix-webassembly container doesn't support exnref - # yet, so the tests abort at startup. Re-enable the run once the new V8 image is - # available. See ActiveIssue https://github.com/dotnet/runtime/issues/129849 - sendToHelix: false extraVariablesTemplates: - template: /eng/pipelines/common/templates/runtimes/test-variables.yml diff --git a/eng/pipelines/coreclr/templates/helix-queues-setup.yml b/eng/pipelines/coreclr/templates/helix-queues-setup.yml index 1da5749cfcf9c2..0d01038f734c35 100644 --- a/eng/pipelines/coreclr/templates/helix-queues-setup.yml +++ b/eng/pipelines/coreclr/templates/helix-queues-setup.yml @@ -70,9 +70,9 @@ jobs: # Browser wasm - ${{ if eq(parameters.platform, 'browser_wasm') }}: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - - (Ubuntu.2604.Amd64.Open)AzureLinux.3.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-26.04-helix-webassembly-amd64@sha256:3ef1314b50ac039078f6406d649d5ac72715deccd07bcbfe3dd43fa438be3fbd + - (Ubuntu.2604.Amd64.Open)AzureLinux.3.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-26.04-helix-webassembly-amd64@sha256:73db6e433bb7e9ef8546b35688b727f2f559b9ac5fea21c77d56795b74b197b8 - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - - (Ubuntu.2604.Amd64)AzureLinux.3.Amd64@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-26.04-helix-webassembly-amd64@sha256:3ef1314b50ac039078f6406d649d5ac72715deccd07bcbfe3dd43fa438be3fbd + - (Ubuntu.2604.Amd64)AzureLinux.3.Amd64@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-26.04-helix-webassembly-amd64@sha256:73db6e433bb7e9ef8546b35688b727f2f559b9ac5fea21c77d56795b74b197b8 # iOS devices - ${{ if in(parameters.platform, 'ios_arm64') }}: diff --git a/eng/pipelines/libraries/helix-queues-setup.yml b/eng/pipelines/libraries/helix-queues-setup.yml index c02f02b5a30f2a..e6fe84bebb3dab 100644 --- a/eng/pipelines/libraries/helix-queues-setup.yml +++ b/eng/pipelines/libraries/helix-queues-setup.yml @@ -170,15 +170,15 @@ jobs: # WASI - ${{ if eq(parameters.platform, 'wasi_wasm') }}: - - (Ubuntu.2604.Amd64.Open)AzureLinux.3.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-26.04-helix-webassembly-amd64@sha256:3ef1314b50ac039078f6406d649d5ac72715deccd07bcbfe3dd43fa438be3fbd + - (Ubuntu.2604.Amd64.Open)AzureLinux.3.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-26.04-helix-webassembly-amd64@sha256:73db6e433bb7e9ef8546b35688b727f2f559b9ac5fea21c77d56795b74b197b8 # Browser WebAssembly - ${{ if eq(parameters.platform, 'browser_wasm') }}: - - (Ubuntu.2604.Amd64.Open)AzureLinux.3.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-26.04-helix-webassembly-amd64@sha256:3ef1314b50ac039078f6406d649d5ac72715deccd07bcbfe3dd43fa438be3fbd + - (Ubuntu.2604.Amd64.Open)AzureLinux.3.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-26.04-helix-webassembly-amd64@sha256:73db6e433bb7e9ef8546b35688b727f2f559b9ac5fea21c77d56795b74b197b8 # Browser WebAssembly Firefox - ${{ if eq(parameters.platform, 'browser_wasm_firefox') }}: - - (Ubuntu.2604.Amd64.Open)AzureLinux.3.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-26.04-helix-webassembly-amd64@sha256:3ef1314b50ac039078f6406d649d5ac72715deccd07bcbfe3dd43fa438be3fbd + - (Ubuntu.2604.Amd64.Open)AzureLinux.3.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-26.04-helix-webassembly-amd64@sha256:73db6e433bb7e9ef8546b35688b727f2f559b9ac5fea21c77d56795b74b197b8 # Browser WebAssembly windows - ${{ if in(parameters.platform, 'browser_wasm_win', 'wasi_wasm_win') }}: diff --git a/eng/pipelines/runtime-linker-tests.yml b/eng/pipelines/runtime-linker-tests.yml index 5b618aebab5be8..d7fc85743e17dd 100644 --- a/eng/pipelines/runtime-linker-tests.yml +++ b/eng/pipelines/runtime-linker-tests.yml @@ -135,11 +135,5 @@ extends: postBuildSteps: - template: /eng/pipelines/libraries/execute-trimming-tests-steps.yml parameters: - # Publish the trimmed browser apps, but don't run them on V8: the V8 baked into - # the helix-webassembly container doesn't support exnref yet, - # so run-v8.sh aborts at startup. SkipTrimmingTestsRun keeps the build/publish - # coverage and only skips ExecuteApplications. Re-enable the run once the new V8 - # image is available. See - # ActiveIssue https://github.com/dotnet/runtime/issues/129849 - extraTestArgs: '/p:WasmBuildNative=false /p:RuntimeFlavor=Mono /p:ToolsConfiguration=Debug /p:SkipTrimmingTestsRun=true' + extraTestArgs: '/p:WasmBuildNative=false /p:RuntimeFlavor=Mono /p:ToolsConfiguration=Debug' runAotTests: false From d5a1d27a8eb45b2f938e5fd1a01543db7fe1b701 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Fri, 10 Jul 2026 19:18:49 +0200 Subject: [PATCH 2/3] [wasm] Guard auto-updater against downgrading V8 below the exnref floor (#129849) UpdateChromeVersions derives the V8 version from the Chrome milestone, which already reverted the pinned V8 below the exnref-capable floor (15.1.103) once. Add a minimum-version guard that keeps the existing V8 version whenever the recomputed value would drop below the floor, mirroring the existing CDN-unavailable fallback. --- .../WasmBuildTasks/UpdateChromeVersions.cs | 42 ++++++++++++++----- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/src/tasks/WasmBuildTasks/UpdateChromeVersions.cs b/src/tasks/WasmBuildTasks/UpdateChromeVersions.cs index b0d145cd17815d..ce93d2a9412e18 100644 --- a/src/tasks/WasmBuildTasks/UpdateChromeVersions.cs +++ b/src/tasks/WasmBuildTasks/UpdateChromeVersions.cs @@ -25,6 +25,11 @@ public partial class UpdateChromeVersions : MBU.Task private const string s_v8CanaryBaseUrl = "https://storage.googleapis.com/chromium-v8/official/canary"; private const int s_versionCheckThresholdDays = 1; + // The V8 used for testing must support the standardized exnref exception-handling proposal. + // Chrome milestones can map to older V8 builds, so never downgrade the pinned V8 below this + // floor. See https://github.com/dotnet/runtime/issues/129849 + private static readonly Version s_minV8Version = new(15, 1, 103); + private static readonly HttpClient s_httpClient = new(); [GeneratedRegex("#define V8_BUILD_NUMBER (\\d+)")] @@ -215,23 +220,24 @@ private static void UpdateNodeValue(XmlDocument xmlDoc, string nodeName, string string foundV8Version = await FindV8VersionFromChromeVersion(foundRelease.version).ConfigureAwait(false); + // Never downgrade V8 below the exnref-capable floor, even if the Chrome milestone maps to an older build. + if (Version.TryParse(foundV8Version, out Version? candidateV8Version) && candidateV8Version < s_minV8Version) + { + string existingV8Version = GetExistingV8Version(osIdentifier); + Log.LogWarning($"Computed V8 version {foundV8Version} for {osIdentifier} is below the minimum " + + $"exnref-capable version {s_minV8Version} — keeping the existing V8 version {existingV8Version}."); + foundV8Version = existingV8Version; + if (string.IsNullOrEmpty(foundV8Version)) + throw new LogAsErrorException($"Computed V8 version for {osIdentifier} is below {s_minV8Version} and no existing version found in {ChromeVersionsPath}"); + } // Validate that a prebuilt V8 binary exists on the CDN that jsvu uses for downloading. - if (!await IsV8BinaryAvailableAsync(osPrefix, foundV8Version).ConfigureAwait(false)) + else if (!await IsV8BinaryAvailableAsync(osPrefix, foundV8Version).ConfigureAwait(false)) { string v8BinaryUrl = GetV8BinaryUrl(osPrefix, foundV8Version); Log.LogWarning($"V8 binary not available at {v8BinaryUrl} — keeping the existing V8 version for {osIdentifier}."); // Fall back to the existing V8 version from BrowserVersions.props - XmlDocument existingDoc = new XmlDocument(); - existingDoc.Load(ChromeVersionsPath); - string existingV8VersionNodeName = string.Equals(osIdentifier, "linux", StringComparison.OrdinalIgnoreCase) - ? "linux_V8Version" - : string.Equals(osIdentifier, "windows", StringComparison.OrdinalIgnoreCase) - ? "win_V8Version" - : string.Equals(osIdentifier, "Mac", StringComparison.OrdinalIgnoreCase) - ? "macos_V8Version" - : throw new LogAsErrorException($"Unknown OS identifier '{osIdentifier}' for V8 version fallback"); - foundV8Version = GetNodeValue(existingDoc, existingV8VersionNodeName); + foundV8Version = GetExistingV8Version(osIdentifier); if (string.IsNullOrEmpty(foundV8Version)) throw new LogAsErrorException($"V8 binary for {osIdentifier} not available on CDN and no existing version found in {ChromeVersionsPath}"); } @@ -279,6 +285,20 @@ async Task FindV8VersionFromChromeVersion(string chromeVersion) } } + private string GetExistingV8Version(string osIdentifier) + { + XmlDocument existingDoc = new XmlDocument(); + existingDoc.Load(ChromeVersionsPath); + string existingV8VersionNodeName = string.Equals(osIdentifier, "linux", StringComparison.OrdinalIgnoreCase) + ? "linux_V8Version" + : string.Equals(osIdentifier, "windows", StringComparison.OrdinalIgnoreCase) + ? "win_V8Version" + : string.Equals(osIdentifier, "Mac", StringComparison.OrdinalIgnoreCase) + ? "macos_V8Version" + : throw new LogAsErrorException($"Unknown OS identifier '{osIdentifier}' for V8 version fallback"); + return GetNodeValue(existingDoc, existingV8VersionNodeName); + } + private static string GetV8BinaryUrl(string osPrefix, string v8Version) { string jsvuPlatform = osPrefix switch From 52fe23f11048e1176ea50100a009e294fa813df8 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Fri, 10 Jul 2026 20:03:51 +0200 Subject: [PATCH 3/3] [wasm] Re-enable perf wasm v8 pipeline and CoreCLR WasmTestOnV8 (#129849) With the atob feature-detection polyfill (#130142) covering both the Mono and CoreCLR loaders and an exnref-capable V8 now in the helix image and pinned in BrowserVersions.props, restore the perf wasm v8 PR trigger and the CoreCLR WasmTestOnV8 smoke scenario that were disabled while the engine could not run exnref. --- eng/pipelines/performance/runtime-wasm-perf.yml | 14 +++++++++----- eng/pipelines/runtime.yml | 3 +-- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/eng/pipelines/performance/runtime-wasm-perf.yml b/eng/pipelines/performance/runtime-wasm-perf.yml index 837eadeb2aaa31..bb99c421344af8 100644 --- a/eng/pipelines/performance/runtime-wasm-perf.yml +++ b/eng/pipelines/performance/runtime-wasm-perf.yml @@ -4,11 +4,15 @@ trigger: none -# Disabled: the perf wasm v8 job installs V8 via jsvu, and the V8 binary it currently -# installs does not support exnref yet, so the MicroBenchmarks Helix -# job aborts at startup. Re-enable once an exnref-capable V8 is pinned. See -# ActiveIssue https://github.com/dotnet/runtime/issues/129849 -pr: none +pr: + branches: + include: + - main + paths: + include: + - eng/pipelines/performance/* + - eng/testing/performance/* + - eng/testing/BrowserVersions.props resources: repositories: diff --git a/eng/pipelines/runtime.yml b/eng/pipelines/runtime.yml index 231972e1b90084..22f318ca42c953 100644 --- a/eng/pipelines/runtime.yml +++ b/eng/pipelines/runtime.yml @@ -1009,8 +1009,7 @@ extends: extraBuildArgs: /p:AotHostArchitecture=x64 /p:AotHostOS=$(_hostedOS) scenarios: - WasmTestOnFirefox - # ActiveIssue https://github.com/dotnet/runtime/issues/129849 - # - WasmTestOnV8 + - WasmTestOnV8 # EAT Library tests - only run on linux - template: /eng/pipelines/common/templates/wasm-library-aot-tests.yml