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