[browser] WASM exception handling to use the standardized exnref #129851
Open
pavelsavara wants to merge 3 commits into
Open
[browser] WASM exception handling to use the standardized exnref #129851pavelsavara wants to merge 3 commits into
pavelsavara wants to merge 3 commits into
Conversation
ActiveIssue dotnet#129849
Member
Author
|
/azp run runtime-wasm |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Contributor
There was a problem hiding this comment.
Pull request overview
This PR updates the browser/WASM stack to use standardized exnref-based WebAssembly exception handling (e.g., try_table / throw_ref) instead of the legacy encoding, and wires the necessary toolchain / runtime / test-runner flags across build and CI.
Changes:
- Switch Emscripten/emsdk builds from
WASM_LEGACY_EXCEPTIONS=1to0, and ensure post-linkwasm-optenables reference types. - Update the browser runtime feature detection and the jiterpreter wasm codegen to use
exceptionsFinal+try_table-based EH constructs. - Update test/sample runners and CI templates to pass
--experimental-wasm-exnref, and temporarily skip V8 execution legs where the engine can’t run the new encoding yet.
Reviewed changes
Copilot reviewed 29 out of 29 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/tests/Common/CLRTest.Execute.Batch.targets | Adds --experimental-wasm-exnref to Node invocation when running browser tests via Node on Windows. |
| src/tests/Common/CLRTest.Execute.Bash.targets | Adds --experimental-wasm-exnref to Node invocation when running browser tests via Node on Unix. |
| src/mono/wasm/build/WasmApp.Common.targets | Adds --enable-reference-types to wasm-opt post-link flags. |
| src/mono/sample/wasm/wasm.mk | Adds --experimental-wasm-exnref when running sample apps under V8/Node. |
| src/mono/sample/wasm/console-v8/Wasm.Console.V8.Sample.csproj | Passes --experimental-wasm-exnref via XHarness engine args for V8 sample runs. |
| src/mono/sample/wasm/console-node/Wasm.Console.Node.Sample.csproj | Passes --experimental-wasm-exnref via XHarness engine args for Node sample runs. |
| src/mono/mono/mini/CMakeLists.txt | Switches mono wasm EH library build to -sWASM_LEGACY_EXCEPTIONS=0. |
| src/mono/browser/runtime/types/internal.ts | Renames loader/runtime helper fields to exceptionsFinal / featureWasmFinalEh. |
| src/mono/browser/runtime/startup.ts | Uses exceptionsFinal feature detection; updates worker instantiate ordering. |
| src/mono/browser/runtime/loader/globals.ts | Switches wasm-feature-detect import from exceptions to exceptionsFinal. |
| src/mono/browser/runtime/jiterpreter-support.ts | Introduces tryTable/tag-index helpers and renames option to enableWasmFinalEh. |
| src/mono/browser/runtime/jiterpreter-opcodes.ts | Replaces legacy EH opcodes with standardized throw_ref / try_table opcodes. |
| src/mono/browser/runtime/jiterpreter-jit-call.ts | Updates jit-call wasm wrapper generation to try_table-based EH (standardized proposal). |
| src/mono/browser/runtime/CMakeLists.txt | Adds --enable-reference-types to wasm-opt for Release post-build. |
| src/mono/browser/build/BrowserWasmApp.targets | Switches to WASM_LEGACY_EXCEPTIONS=0; injects --experimental-wasm-exnref in generated V8 run script. |
| src/mono/browser/build/BrowserWasmApp.CoreCLR.targets | Adds -sWASM_LEGACY_EXCEPTIONS=0 to CoreCLR browser-wasm relink flags. |
| src/mono/browser/browser.proj | Switches mono browser runtime build flags to WASM_LEGACY_EXCEPTIONS=0. |
| eng/testing/WasmRunnerTemplate.sh | Adds --experimental-wasm-exnref to default V8 engine args for wasm test runs. |
| eng/testing/WasmRunnerTemplate.cmd | Adds --experimental-wasm-exnref to default V8 engine args for wasm test runs on Windows. |
| eng/testing/linker/trimmingTests.targets | Adds SkipTrimmingTestsRun gate to allow publish-only trimming coverage. |
| eng/testing/BrowserVersions.props | Bumps pinned V8 versions to 15.1.103. |
| eng/pipelines/runtime.yml | Temporarily disables the WasmTestOnV8 scenario in a wasm CoreCLR smoke legs block. |
| eng/pipelines/runtime-llvm.yml | Expands PR path filters to include assembly-load-context.*. |
| eng/pipelines/runtime-linker-tests.yml | Passes SkipTrimmingTestsRun=true to avoid executing trimmed apps on V8 temporarily. |
| eng/pipelines/performance/runtime-wasm-perf.yml | Disables PR trigger for wasm perf pipeline while V8 execution is blocked. |
| eng/pipelines/common/templates/wasm-runtime-tests.yml | Sets sendToHelix: false to build but skip Helix execution for wasm runtime tests. |
| eng/pipelines/common/templates/runtimes/build-runtime-tests-and-send-to-helix.yml | Adds sendToHelix parameter and conditional logic to skip Helix send/execution. |
| eng/pipelines/common/templates/pipeline-with-resources.yml | Updates the pinned webassembly prereqs container digest(s). |
| eng/native/configureplatform.cmake | Switches CoreCLR browser build to WASM_LEGACY_EXCEPTIONS=0 and links EH-specific libc++/unwind libs. |
Member
Author
|
/azp run runtime-wasm |
|
Azure Pipelines successfully started running 1 pipeline(s). |
akoeplinger
reviewed
Jun 25, 2026
akoeplinger
reviewed
Jun 25, 2026
| if(CMAKE_BUILD_TYPE STREQUAL "Release") | ||
| add_custom_command(TARGET dotnet.native | ||
| POST_BUILD COMMAND ${EMSDK_PATH}/bin/wasm-opt --enable-exception-handling --enable-multivalue --enable-simd --enable-bulk-memory --enable-nontrapping-float-to-int ${CONFIGURATION_WASM_OPT_FLAGS} --strip-dwarf ${NATIVE_BIN_DIR}/dotnet.native.wasm -o ${NATIVE_BIN_DIR}/dotnet.native.wasm | ||
| POST_BUILD COMMAND ${EMSDK_PATH}/bin/wasm-opt --enable-exception-handling --enable-reference-types --enable-multivalue --enable-simd --enable-bulk-memory --enable-nontrapping-float-to-int ${CONFIGURATION_WASM_OPT_FLAGS} --strip-dwarf ${NATIVE_BIN_DIR}/dotnet.native.wasm -o ${NATIVE_BIN_DIR}/dotnet.native.wasm |
Member
There was a problem hiding this comment.
what's the connection between --enable-reference-types and exception handling?
Member
Author
There was a problem hiding this comment.
WebAssembly's exception handling final proposal uses an exnref value (a reference to an exception) to carry exception state
akoeplinger
approved these changes
Jun 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Disables V8 legs until we have image with 15.1.103
Fixes #119961
Summary
This change upgrades the WebAssembly toolchain (emsdk / Emscripten + wasm-opt) and switches the
browser runtime from the legacy WASM exception-handling encoding to the standardized
exnref-based exception-handling proposal (
try_table/throw_ref).Concretely, every place that previously passed
WASM_LEGACY_EXCEPTIONS=1now passesWASM_LEGACY_EXCEPTIONS=0, the jiterpreter codegen emitstry_tableinstead of the legacytry/catchopcodes, and feature detection / JS-engine flags are updated to require the final EHproposal (
--experimental-wasm-exnref).Because the V8 baked into our CI containers (and the jsvu-installed V8 used by perf) does not yet
support
--experimental-wasm-exnref, the V8 test legs are temporarily disabled and tracked by#129849. Build/publish coverage is preserved;
only the V8 execution step is skipped.
Changes
Toolchain flags: legacy EH → standardized EH
eng/native/configureplatform.cmake— CoreCLR browser build:WASM_LEGACY_EXCEPTIONS=0for bothcompile and link, and switch to the EH-specific runtime libraries
(
-lc++-wasmexcept,-lc++abi-wasmexcept,-lunwind-wasmexcept).src/mono/mono/mini/CMakeLists.txt—mono-wasm-eh-wasmcompile/link flags setWASM_LEGACY_EXCEPTIONS=0.src/mono/browser/browser.proj— Mono runtime build flags setWASM_LEGACY_EXCEPTIONS=0.src/mono/browser/build/BrowserWasmApp.targets,src/mono/browser/build/BrowserWasmApp.CoreCLR.targets,src/mono/wasm/build/WasmApp.Common.targets— app build flags updated;wasm-optnow runs with--enable-reference-types(required for exnref) alongside--enable-exception-handling.src/mono/browser/runtime/CMakeLists.txt— Releasewasm-optpost-build step adds--enable-reference-types.Jiterpreter codegen: emit
try_table/ exnrefsrc/mono/browser/runtime/jiterpreter-opcodes.ts— replace the legacytry_/catch_/catch_all/throw_/rethrow_opcodes withthrow_ref(0x0a) andtry_table(0x1f).src/mono/browser/runtime/jiterpreter-support.ts— addtryTable(...)andgetTagIndex(...)helpers (tags live in a separate index space from types), and rename the
enableWasmEhoption toenableWasmFinalEh(the underlyingjiterpreter-wasm-eh-enabledflag name is unchanged).src/mono/browser/runtime/jiterpreter-jit-call.ts— wrap the jit-call body in a(block (block (try_table (catch __cpp_exception ...) ...)))structure instead of the legacytry/catchblock.Feature detection and startup
src/mono/browser/runtime/loader/globals.ts,src/mono/browser/runtime/types/internal.ts,src/mono/browser/runtime/startup.ts— switch from theexceptionsto theexceptionsFinaldetector of the
wasm-feature-detectpackage; renamefeatureWasmEh→featureWasmFinalEh.src/mono/browser/runtime/startup.ts— minor worker-startup reordering (callsuccessCallbackbeforepreRunWorker).JS-engine arguments for tests / samples
Add
--experimental-wasm-exnrefwherever V8 / Node is launched:eng/testing/WasmRunnerTemplate.cmd,eng/testing/WasmRunnerTemplate.shsrc/tests/Common/CLRTest.Execute.Bash.targets,src/tests/Common/CLRTest.Execute.Batch.targetssrc/mono/browser/build/BrowserWasmApp.targets(generated V8 run script)src/mono/sample/wasm/wasm.mk,src/mono/sample/wasm/console-node/Wasm.Console.Node.Sample.csproj,src/mono/sample/wasm/console-v8/Wasm.Console.V8.Sample.csprojCI images and versions
eng/pipelines/common/templates/pipeline-with-resources.yml— bump theazurelinux-3.0-net11.0-webassemblyprereqs image (new emsdk) forbrowser_wasmandwasi_wasm.eng/testing/BrowserVersions.props— bump V8 to15.1.103on Linux/macOS/Windows.Temporarily disable V8 test legs (tracked by #129849)
The CI/perf V8 doesn't support
--experimental-wasm-exnrefyet, so V8 execution is skipped whilekeeping build/publish coverage:
eng/pipelines/common/templates/runtimes/build-runtime-tests-and-send-to-helix.yml— add asendToHelixparameter (defaulttrue) so callers can build but not send to Helix.eng/pipelines/common/templates/wasm-runtime-tests.yml— passsendToHelix: false.eng/pipelines/runtime.yml— comment out theWasmTestOnV8scenario (Firefox still runs).eng/pipelines/performance/runtime-wasm-perf.yml— disable the PR trigger (pr: none).eng/pipelines/runtime-linker-tests.yml+eng/testing/linker/trimmingTests.targets— addSkipTrimmingTestsRun=trueto publish trimmed browser apps without executing them on V8.