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(&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!(func 72 .call(&mut store, &[Val::FuncRef(Some(f))], &mut [Val::I32(0)]) 73 .is_err()); 74 } 75 76 Ok(()) 77 } 78 79 #[test] 80 #[cfg_attr(miri, ignore)] 81 fn receive_null_funcref_from_wasm() -> anyhow::Result<()> { 82 let (mut store, module) = ref_types_module( 83 false, 84 r#" 85 (module 86 (func (export "get-null") (result funcref) 87 ref.null func 88 ) 89 ) 90 "#, 91 )?; 92 93 let instance = Instance::new(&mut store, &module, &[])?; 94 let get_null = instance.get_func(&mut store, "get-null").unwrap(); 95 96 let mut results = [Val::I32(0)]; 97 get_null.call(&mut store, &[], &mut results)?; 98 let result_func = results[0].unwrap_funcref(); 99 assert!(result_func.is_none()); 100 101 Ok(()) 102 } 103 104 #[test] 105 fn wrong_store() -> anyhow::Result<()> { 106 let dropped = Arc::new(AtomicBool::new(false)); 107 { 108 let mut store1 = Store::<()>::default(); 109 let mut store2 = Store::<()>::default(); 110 111 let set = SetOnDrop(dropped.clone()); 112 let f1 = Func::wrap(&mut store1, move || { 113 let _ = &set; 114 }); 115 let f2 = Func::wrap(&mut store2, move || Some(f1)); 116 assert!(f2.call(&mut store2, &[], &mut []).is_err()); 117 } 118 assert!(dropped.load(SeqCst)); 119 120 return Ok(()); 121 122 struct SetOnDrop(Arc<AtomicBool>); 123 124 impl Drop for SetOnDrop { 125 fn drop(&mut self) { 126 self.0.store(true, SeqCst); 127 } 128 } 129 } 130 131 #[test] 132 #[cfg_attr(miri, ignore)] 133 fn func_new_returns_wrong_store() -> anyhow::Result<()> { 134 let dropped = Arc::new(AtomicBool::new(false)); 135 { 136 let mut store1 = Store::<()>::default(); 137 let mut store2 = Store::<()>::default(); 138 139 let set = SetOnDrop(dropped.clone()); 140 let f1 = Func::wrap(&mut store1, move || { 141 let _ = &set; 142 }); 143 let func_ty = FuncType::new(store2.engine(), None, Some(ValType::FUNCREF)); 144 let f2 = Func::new(&mut store2, func_ty, move |_, _, results| { 145 results[0] = f1.into(); 146 Ok(()) 147 }); 148 assert!(f2.call(&mut store2, &[], &mut [Val::I32(0)]).is_err()); 149 } 150 assert!(dropped.load(SeqCst)); 151 152 return Ok(()); 153 154 struct SetOnDrop(Arc<AtomicBool>); 155 156 impl Drop for SetOnDrop { 157 fn drop(&mut self) { 158 self.0.store(true, SeqCst); 159 } 160 } 161 } 162