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