1 use crate::{
2 WasmtimeStoreContextMut, handle_result, wasm_trap_t, wasmtime_error_t, wasmtime_val_t,
3 };
4 use std::mem::MaybeUninit;
5 use wasmtime::{AsContextMut, ExnRef, ExnRefPre, ExnType, RootScope, Tag};
6
7 /// An opaque type representing a WebAssembly exception object.
8 pub struct wasmtime_exn_t {
9 exn: wasmtime::OwnedRooted<ExnRef>,
10 }
11
12 wasmtime_c_api_macros::declare_own!(wasmtime_exn_t);
13
14 #[unsafe(no_mangle)]
wasmtime_exn_new( mut store: WasmtimeStoreContextMut<'_>, tag: &Tag, fields: *const wasmtime_val_t, nfields: usize, exn_ret: &mut *mut wasmtime_exn_t, ) -> Option<Box<wasmtime_error_t>>15 pub unsafe extern "C" fn wasmtime_exn_new(
16 mut store: WasmtimeStoreContextMut<'_>,
17 tag: &Tag,
18 fields: *const wasmtime_val_t,
19 nfields: usize,
20 exn_ret: &mut *mut wasmtime_exn_t,
21 ) -> Option<Box<wasmtime_error_t>> {
22 let mut scope = RootScope::new(&mut store);
23
24 let result = (|| {
25 let tag_ty = tag.ty(&scope);
26 let exn_type = ExnType::from_tag_type(&tag_ty)?;
27 let allocator = ExnRefPre::new(&mut scope, exn_type);
28 let raw_fields = crate::slice_from_raw_parts(fields, nfields);
29 let field_vals: Vec<wasmtime::Val> =
30 raw_fields.iter().map(|f| f.to_val(&mut scope)).collect();
31 ExnRef::new(&mut scope, &allocator, tag, &field_vals)
32 })();
33
34 handle_result(result, |rooted| {
35 let owned = rooted.to_owned_rooted(&mut scope).unwrap();
36 *exn_ret = Box::into_raw(Box::new(wasmtime_exn_t { exn: owned }));
37 })
38 }
39
40 #[unsafe(no_mangle)]
wasmtime_exn_tag( mut store: WasmtimeStoreContextMut<'_>, exn: &wasmtime_exn_t, tag_ret: &mut Tag, ) -> Option<Box<wasmtime_error_t>>41 pub extern "C" fn wasmtime_exn_tag(
42 mut store: WasmtimeStoreContextMut<'_>,
43 exn: &wasmtime_exn_t,
44 tag_ret: &mut Tag,
45 ) -> Option<Box<wasmtime_error_t>> {
46 let mut scope = RootScope::new(&mut store);
47 let rooted = exn.exn.to_rooted(&mut scope);
48 handle_result(rooted.tag(&mut scope), |tag| {
49 *tag_ret = tag;
50 })
51 }
52
53 #[unsafe(no_mangle)]
wasmtime_exn_field_count( mut store: WasmtimeStoreContextMut<'_>, exn: &wasmtime_exn_t, ) -> usize54 pub extern "C" fn wasmtime_exn_field_count(
55 mut store: WasmtimeStoreContextMut<'_>,
56 exn: &wasmtime_exn_t,
57 ) -> usize {
58 let mut scope = RootScope::new(&mut store);
59 let rooted = exn.exn.to_rooted(&mut scope);
60 let ty = rooted.ty(&scope).unwrap();
61 ty.fields().len()
62 }
63
64 #[unsafe(no_mangle)]
wasmtime_exn_field( mut store: WasmtimeStoreContextMut<'_>, exn: &wasmtime_exn_t, index: usize, val_ret: &mut MaybeUninit<wasmtime_val_t>, ) -> Option<Box<wasmtime_error_t>>65 pub unsafe extern "C" fn wasmtime_exn_field(
66 mut store: WasmtimeStoreContextMut<'_>,
67 exn: &wasmtime_exn_t,
68 index: usize,
69 val_ret: &mut MaybeUninit<wasmtime_val_t>,
70 ) -> Option<Box<wasmtime_error_t>> {
71 let mut scope = RootScope::new(&mut store);
72 let rooted = exn.exn.to_rooted(&mut scope);
73 handle_result(rooted.field(&mut scope, index), |val| {
74 crate::initialize(val_ret, wasmtime_val_t::from_val(&mut scope, val));
75 })
76 }
77
78 #[unsafe(no_mangle)]
wasmtime_context_set_exception( mut store: WasmtimeStoreContextMut<'_>, exn: Box<wasmtime_exn_t>, ) -> Box<wasm_trap_t>79 pub unsafe extern "C" fn wasmtime_context_set_exception(
80 mut store: WasmtimeStoreContextMut<'_>,
81 exn: Box<wasmtime_exn_t>,
82 ) -> Box<wasm_trap_t> {
83 let mut scope = RootScope::new(&mut store);
84 let rooted = exn.exn.to_rooted(&mut scope);
85 let thrown = scope.as_context_mut().throw::<()>(rooted).unwrap_err();
86 Box::new(wasm_trap_t::new(wasmtime::Error::new(thrown)))
87 }
88
89 #[unsafe(no_mangle)]
wasmtime_context_take_exception( mut store: WasmtimeStoreContextMut<'_>, exn_ret: &mut *mut wasmtime_exn_t, ) -> bool90 pub extern "C" fn wasmtime_context_take_exception(
91 mut store: WasmtimeStoreContextMut<'_>,
92 exn_ret: &mut *mut wasmtime_exn_t,
93 ) -> bool {
94 match store.take_pending_exception() {
95 Some(rooted) => {
96 let owned = rooted.to_owned_rooted(&mut store).unwrap();
97 *exn_ret = Box::into_raw(Box::new(wasmtime_exn_t { exn: owned }));
98 true
99 }
100 None => false,
101 }
102 }
103
104 #[unsafe(no_mangle)]
wasmtime_context_has_exception(store: WasmtimeStoreContextMut<'_>) -> bool105 pub extern "C" fn wasmtime_context_has_exception(store: WasmtimeStoreContextMut<'_>) -> bool {
106 store.has_pending_exception()
107 }
108