alexcrichton added the wasm-proposal:exceptions label to Issue #13614.
alexcrichton added the wasm-proposal:component-model label to Issue #13614.
alexcrichton opened issue #13614:
This test:
(component (component $A (core module $a (type $t (func)) (tag $t (type $t)) (func (export "throw") throw $t) ) (core instance $a (instantiate $a)) (func (export "throw") (canon lift (core func $a "throw"))) ) (component $B (import "a" (instance $a (export "throw" (func)))) (core func $throw (canon lower (func $a "throw"))) (core module $b (import "" "throw" (func $throw)) (func (export "run") block $a try_table (catch_all $a) call $throw end end ) ) (core instance $b (instantiate $b (with "" (instance (export "throw" (func $throw)) )) )) (func (export "run") (canon lift (core func $b "run"))) ) (instance $a (instantiate $A)) (instance $b (instantiate $B (with "a" (instance $a)))) (export "run" (func $b "run")) ) (assert_trap (invoke "run") "something about an uncaught wasm exception")currently fails:
$ cargo run wast foo.wast Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.11s Running `target/debug/wasmtime wast foo.wast` Error: failed to run script file 'foo.wast' Caused by: 0: failed directive on foo.wast:39 1: expected trap, got Component([])While this isn't strictly defined by the component model spec per-se, I'm almost certain that the desired behavior here is that uncaught exceptions within a component don't get propagated anywhere else and turn into unconditional traps.
I talked a bit about this with @fitzgen today and one solution is to insert
catch_allinstructions in component-to-component adapters. The downside of this is that it might pessimize the sync-to-sync adapter even further insfoar as I'm not sure what the inlining story would be in that case. Another possible solution might be to adjust the tag tables of modules to change the encoding of catch-all exceptions in such a manner that only exceptions/tags from the current component instance are caught. As I write this down this is difficult to articulate which means it might not be viable...cc @cfallin as this is exception-related
cc @lukewagner as this is component-model-spec related and I'd want to confirm with you that it's expected thatcatch_allis NOT expected to work across component boundaries. In other words, uncaught exceptions should indeed be unrecoverable traps
alexcrichton commented on issue #13614:
oop looks like Chris/Nick talked as well and I raced #13613 being created
cfallin commented on issue #13614:
Ah, yes, sorry about the race -- my PR fixes an issue from the future...
I don't think that
try_callshould pessimize inlining: the inliner explicitly handles it as well, fortunately.
alexcrichton closed issue #13614:
This test:
(component (component $A (core module $a (type $t (func)) (tag $t (type $t)) (func (export "throw") throw $t) ) (core instance $a (instantiate $a)) (func (export "throw") (canon lift (core func $a "throw"))) ) (component $B (import "a" (instance $a (export "throw" (func)))) (core func $throw (canon lower (func $a "throw"))) (core module $b (import "" "throw" (func $throw)) (func (export "run") block $a try_table (catch_all $a) call $throw end end ) ) (core instance $b (instantiate $b (with "" (instance (export "throw" (func $throw)) )) )) (func (export "run") (canon lift (core func $b "run"))) ) (instance $a (instantiate $A)) (instance $b (instantiate $B (with "a" (instance $a)))) (export "run" (func $b "run")) ) (assert_trap (invoke "run") "something about an uncaught wasm exception")currently fails:
$ cargo run wast foo.wast Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.11s Running `target/debug/wasmtime wast foo.wast` Error: failed to run script file 'foo.wast' Caused by: 0: failed directive on foo.wast:39 1: expected trap, got Component([])While this isn't strictly defined by the component model spec per-se, I'm almost certain that the desired behavior here is that uncaught exceptions within a component don't get propagated anywhere else and turn into unconditional traps.
I talked a bit about this with @fitzgen today and one solution is to insert
catch_allinstructions in component-to-component adapters. The downside of this is that it might pessimize the sync-to-sync adapter even further insfoar as I'm not sure what the inlining story would be in that case. Another possible solution might be to adjust the tag tables of modules to change the encoding of catch-all exceptions in such a manner that only exceptions/tags from the current component instance are caught. As I write this down this is difficult to articulate which means it might not be viable...cc @cfallin as this is exception-related
cc @lukewagner as this is component-model-spec related and I'd want to confirm with you that it's expected thatcatch_allis NOT expected to work across component boundaries. In other words, uncaught exceptions should indeed be unrecoverable traps
Last updated: Jul 29 2026 at 05:03 UTC