xref: /wasmtime-44.0.1/tests/all/funcref.rs (revision 94740588)
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