1 use super::ref_types_module;
2 use std::sync::Arc;
3 use std::sync::atomic::{AtomicBool, Ordering::SeqCst};
4 use wasmtime::*;
5
6 #[test]
7 #[cfg_attr(miri, ignore)]
pass_funcref_in_and_out_of_wasm() -> wasmtime::Result<()>8 fn pass_funcref_in_and_out_of_wasm() -> wasmtime::Result<()> {
9 let (mut store, module) = ref_types_module(
10 false,
11 r#"
12 (module
13 (func (export "func") (param funcref) (result funcref)
14 local.get 0
15 )
16 )
17 "#,
18 )?;
19
20 let instance = Instance::new(&mut store, &module, &[])?;
21 let func = instance.get_func(&mut store, "func").unwrap();
22
23 // Pass in a non-null funcref.
24 {
25 let mut results = [Val::I32(0)];
26 func.call(&mut store, &[Val::FuncRef(Some(func))], &mut results)?;
27
28 // Can't compare `Func` for equality, so this is the best we can do here.
29 let result_func = results[0].unwrap_funcref().unwrap();
30 assert!(FuncType::eq(&func.ty(&store), &result_func.ty(&store)));
31 }
32
33 // Pass in a null funcref.
34 {
35 let mut results = [Val::I32(0)];
36 func.call(&mut store, &[Val::FuncRef(None)], &mut results)?;
37 let result_func = results[0].unwrap_funcref();
38 assert!(result_func.is_none());
39 }
40
41 // Pass in a `funcref` from another instance.
42 {
43 let other_instance = Instance::new(&mut store, &module, &[])?;
44 let other_instance_func = other_instance.get_func(&mut store, "func").unwrap();
45
46 let mut results = [Val::I32(0)];
47 func.call(
48 &mut store,
49 &[Val::FuncRef(Some(other_instance_func))],
50 &mut results,
51 )?;
52 assert_eq!(results.len(), 1);
53
54 // Can't compare `Func` for equality, so this is the best we can do here.
55 let result_func = results[0].unwrap_funcref().unwrap();
56 assert!(FuncType::eq(
57 &other_instance_func.ty(&store),
58 &result_func.ty(&store),
59 ));
60 }
61
62 // Passing in a `funcref` from another store fails.
63 {
64 let (mut other_store, other_module) =
65 ref_types_module(false, r#"(module (func (export "f")))"#)?;
66 let other_store_instance = Instance::new(&mut other_store, &other_module, &[])?;
67 let f = other_store_instance
68 .get_func(&mut other_store, "f")
69 .unwrap();
70
71 assert!(
72 func.call(&mut store, &[Val::FuncRef(Some(f))], &mut [Val::I32(0)])
73 .is_err()
74 );
75 }
76
77 Ok(())
78 }
79
80 #[test]
81 #[cfg_attr(miri, ignore)]
receive_null_funcref_from_wasm() -> wasmtime::Result<()>82 fn receive_null_funcref_from_wasm() -> wasmtime::Result<()> {
83 let (mut store, module) = ref_types_module(
84 false,
85 r#"
86 (module
87 (func (export "get-null") (result funcref)
88 ref.null func
89 )
90 )
91 "#,
92 )?;
93
94 let instance = Instance::new(&mut store, &module, &[])?;
95 let get_null = instance.get_func(&mut store, "get-null").unwrap();
96
97 let mut results = [Val::I32(0)];
98 get_null.call(&mut store, &[], &mut results)?;
99 let result_func = results[0].unwrap_funcref();
100 assert!(result_func.is_none());
101
102 Ok(())
103 }
104
105 #[test]
wrong_store() -> wasmtime::Result<()>106 fn wrong_store() -> wasmtime::Result<()> {
107 let dropped = Arc::new(AtomicBool::new(false));
108 {
109 let mut store1 = Store::<()>::default();
110 let mut store2 = Store::<()>::default();
111
112 let set = SetOnDrop(dropped.clone());
113 let f1 = Func::wrap(&mut store1, move || {
114 let _ = &set;
115 });
116 let f2 = Func::wrap(&mut store2, move || Some(f1));
117 assert!(f2.call(&mut store2, &[], &mut []).is_err());
118 }
119 assert!(dropped.load(SeqCst));
120
121 return Ok(());
122
123 struct SetOnDrop(Arc<AtomicBool>);
124
125 impl Drop for SetOnDrop {
126 fn drop(&mut self) {
127 self.0.store(true, SeqCst);
128 }
129 }
130 }
131
132 #[test]
133 #[cfg_attr(miri, ignore)]
func_new_returns_wrong_store() -> wasmtime::Result<()>134 fn func_new_returns_wrong_store() -> wasmtime::Result<()> {
135 let dropped = Arc::new(AtomicBool::new(false));
136 {
137 let mut store1 = Store::<()>::default();
138 let mut store2 = Store::<()>::default();
139
140 let set = SetOnDrop(dropped.clone());
141 let f1 = Func::wrap(&mut store1, move || {
142 let _ = &set;
143 });
144 let func_ty = FuncType::new(store2.engine(), None, Some(ValType::FUNCREF));
145 let f2 = Func::new(&mut store2, func_ty, move |_, _, results| {
146 results[0] = f1.into();
147 Ok(())
148 });
149 assert!(f2.call(&mut store2, &[], &mut [Val::I32(0)]).is_err());
150 }
151 assert!(dropped.load(SeqCst));
152
153 return Ok(());
154
155 struct SetOnDrop(Arc<AtomicBool>);
156
157 impl Drop for SetOnDrop {
158 fn drop(&mut self) {
159 self.0.store(true, SeqCst);
160 }
161 }
162 }
163