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)] 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)] 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] 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)] 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