Exception Handling
24.1 Wasm Exception Handling (exnref, Wasm 3.0)
Instructions: throw, throw_ref, try_table with catch, catch_ref, catch_all, catch_all_ref. The legacy try/catch/delegate/rethrow (phase-out) is still supported in browsers for older binaries.
JS interop: WebAssembly.Tag, WebAssembly.Exception (exception.is(tag), exception.getArg(tag, 0)). JS exceptions propagate through Wasm frames.
(module
(tag $MyError (param i32)) ;; exception tag with an i32 payload
(export "MyError" (tag $MyError))
(func $might_fail (param $x i32) (result i32)
(if (i32.lt_s (local.get $x) (i32.const 0))
(then (throw $MyError (local.get $x))))
(i32.mul (local.get $x) (i32.const 2)))
(func (export "safe") (param $x i32) (result i32)
(block $handler (result i32)
(try_table (result i32) (catch $MyError $handler) ;; on MyError, branch to $handler with the payload
(call $might_fail (local.get $x)))
(return))
;; the payload (i32) is on the stack here
(drop)
(i32.const -1)))24.2 Language Usage
C++: -fwasm-exceptions (zero-cost, native) vs the older Emscripten JS-based exceptions (-fexceptions, slower and larger).
Rust: panics are usually panic=abort in Wasm. Unwinding support with native exceptions is emerging (-Cpanic=unwind with nightly features).
Kotlin/Dart/OCaml WasmGC backends use native exceptions.