| 147 | |
| 148 | #[test] |
| 149 | fn test_trap_through_host() -> Result<()> { |
| 150 | let wat = r#" |
| 151 | (module $hello_mod |
| 152 | (import "" "" (func $host_func_a)) |
| 153 | (import "" "" (func $host_func_b)) |
| 154 | (func $a (export "a") |
| 155 | call $host_func_a |
| 156 | ) |
| 157 | (func $b (export "b") |
| 158 | call $host_func_b |
| 159 | ) |
| 160 | (func $c (export "c") |
| 161 | unreachable |
| 162 | ) |
| 163 | ) |
| 164 | "#; |
| 165 | |
| 166 | let engine = Engine::default(); |
| 167 | let module = Module::new(&engine, wat)?; |
| 168 | let mut store = Store::<()>::new(&engine, ()); |
| 169 | |
| 170 | let host_func_a = Func::new( |
| 171 | &mut store, |
| 172 | FuncType::new(&engine, vec![], vec![]), |
| 173 | |mut caller, _args, _results| { |
| 174 | caller |
| 175 | .get_export("b") |
| 176 | .unwrap() |
| 177 | .into_func() |
| 178 | .unwrap() |
| 179 | .call(caller, &[], &mut [])?; |
| 180 | Ok(()) |
| 181 | }, |
| 182 | ); |
| 183 | let host_func_b = Func::new( |
| 184 | &mut store, |
| 185 | FuncType::new(&engine, vec![], vec![]), |
| 186 | |mut caller, _args, _results| { |
| 187 | caller |
| 188 | .get_export("c") |
| 189 | .unwrap() |
| 190 | .into_func() |
| 191 | .unwrap() |
| 192 | .call(caller, &[], &mut [])?; |
| 193 | Ok(()) |
| 194 | }, |
| 195 | ); |
| 196 | |
| 197 | let instance = Instance::new( |
| 198 | &mut store, |
| 199 | &module, |
| 200 | &[host_func_a.into(), host_func_b.into()], |
| 201 | )?; |
| 202 | let a = instance.get_typed_func::<(), ()>(&mut store, "a")?; |
| 203 | let err = a.call(&mut store, ()).unwrap_err(); |
| 204 | let trace = err.downcast_ref::<WasmBacktrace>().unwrap().frames(); |
| 205 | assert_eq!(trace.len(), 3); |
| 206 | assert_eq!(trace[0].func_name(), Some("c")); |