Skip to content

Commit 51829c4

Browse files
jonas-schievinkVeykril
authored andcommitted
Allow returning traps from linked closures
1 parent 1743a74 commit 51829c4

File tree

3 files changed

+48
-9
lines changed

3 files changed

+48
-9
lines changed

examples/wasm_link_closure.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ fn main() {
1616

1717
let mut module = rt.load_module(module).expect("Unable to load module");
1818
module
19-
.link_closure("time", "millis", |_, ()| MILLIS)
19+
.link_closure("time", "millis", |_, ()| Ok(MILLIS))
2020
.expect("Unable to link closure");
2121
let func = module
2222
.find_function::<(), u64>("seconds")
2323
.expect("Unable to find function");
24-
println!("{}ms in seconds is {:?}s.", MILLIS, func.call());
24+
println!("{}ms in seconds is {:?}s.", MILLIS, func.call().unwrap());
2525
assert_eq!(func.call(), Ok(MILLIS / 1000));
2626
}

examples/wasm_link_closure_trap.rs

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
use wasm3::error::Error;
2+
use wasm3::error::Trap;
3+
use wasm3::Environment;
4+
use wasm3::Module;
5+
6+
fn main() {
7+
let env = Environment::new().expect("Unable to create environment");
8+
let rt = env
9+
.create_runtime(1024 * 60)
10+
.expect("Unable to create runtime");
11+
let module = Module::parse(
12+
&env,
13+
&include_bytes!("wasm/wasm_millis_to_seconds/wasm_millis_to_seconds.wasm")[..],
14+
)
15+
.expect("Unable to parse module");
16+
17+
let mut module = rt.load_module(module).expect("Unable to load module");
18+
module
19+
.link_closure("time", "millis", |_, ()| Err::<u64, _>(Trap::Abort))
20+
.expect("Unable to link closure");
21+
let func = module
22+
.find_function::<(), u64>("seconds")
23+
.expect("Unable to find function");
24+
25+
let err = func.call().unwrap_err();
26+
match err {
27+
Error::Wasm3(e) if e.is_trap(Trap::Abort) => {
28+
println!("got expected error: {}", e);
29+
}
30+
_ => {
31+
panic!("unexpected error: {}", err)
32+
}
33+
}
34+
}

src/module.rs

+12-7
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use core::ptr::{self, NonNull};
55
use core::slice;
66

77
use crate::environment::Environment;
8-
use crate::error::{Error, Result};
8+
use crate::error::{Error, Result, Trap};
99
use crate::function::{CallContext, Function, NNM3Function, RawCall};
1010
use crate::runtime::Runtime;
1111
use crate::utils::{cstr_to_str, eq_cstr_str};
@@ -123,7 +123,7 @@ impl<'rt> Module<'rt> {
123123
where
124124
Args: crate::WasmArgs,
125125
Ret: crate::WasmType,
126-
F: for<'cc> FnMut(CallContext<'cc>, Args) -> Ret + 'static,
126+
F: for<'cc> FnMut(CallContext<'cc>, Args) -> core::result::Result<Ret, Trap> + 'static,
127127
{
128128
let func = self.find_import_function(module_name, function_name)?;
129129
Function::<'_, Args, Ret>::validate_sig(func)?;
@@ -234,7 +234,7 @@ impl<'rt> Module<'rt> {
234234
where
235235
Args: crate::WasmArgs,
236236
Ret: crate::WasmType,
237-
F: for<'cc> FnMut(CallContext<'cc>, Args) -> Ret + 'static,
237+
F: for<'cc> FnMut(CallContext<'cc>, Args) -> core::result::Result<Ret, Trap> + 'static,
238238
{
239239
unsafe extern "C" fn _impl<Args, Ret, F>(
240240
runtime: ffi::IM3Runtime,
@@ -245,7 +245,7 @@ impl<'rt> Module<'rt> {
245245
where
246246
Args: crate::WasmArgs,
247247
Ret: crate::WasmType,
248-
F: for<'cc> FnMut(CallContext<'cc>, Args) -> Ret + 'static,
248+
F: for<'cc> FnMut(CallContext<'cc>, Args) -> core::result::Result<Ret, Trap> + 'static,
249249
{
250250
// use https://doc.rust-lang.org/std/primitive.pointer.html#method.offset_from once stable
251251
let stack_base = (*runtime).stack as ffi::m3stack_t;
@@ -258,9 +258,14 @@ impl<'rt> Module<'rt> {
258258

259259
let args = Args::pop_from_stack(stack);
260260
let context = CallContext::from_rt(NonNull::new_unchecked(runtime));
261-
let ret = (&mut *closure.cast::<F>())(context, args);
262-
ret.push_on_stack(stack.cast());
263-
ffi::m3Err_none as _
261+
let res = (&mut *closure.cast::<F>())(context, args);
262+
match res {
263+
Ok(ret) => {
264+
ret.push_on_stack(stack.cast());
265+
ffi::m3Err_none as _
266+
}
267+
Err(err) => err.as_ptr() as _,
268+
}
264269
}
265270

266271
let page = wasm3_priv::AcquireCodePageWithCapacity(self.rt.as_ptr(), 3);

0 commit comments

Comments
 (0)