| 425 | // (used when capturing backtraces) before we resume panics. |
| 426 | #[test] |
| 427 | fn rust_catch_panic_import() -> Result<()> { |
| 428 | let mut store = Store::<()>::default(); |
| 429 | |
| 430 | let binary = wat::parse_str( |
| 431 | r#" |
| 432 | (module $a |
| 433 | (import "" "panic" (func $panic)) |
| 434 | (import "" "catch panic" (func $catch_panic)) |
| 435 | (func (export "panic") call $panic) |
| 436 | (func (export "run") |
| 437 | call $catch_panic |
| 438 | call $catch_panic |
| 439 | unreachable |
| 440 | ) |
| 441 | ) |
| 442 | "#, |
| 443 | )?; |
| 444 | |
| 445 | let module = Module::new(store.engine(), &binary)?; |
| 446 | let num_panics = std::sync::Arc::new(std::sync::atomic::AtomicU32::new(0)); |
| 447 | let sig = FuncType::new(store.engine(), None, None); |
| 448 | let panic = Func::new(&mut store, sig, { |
| 449 | let num_panics = num_panics.clone(); |
| 450 | move |_, _, _| { |
| 451 | num_panics.fetch_add(1, std::sync::atomic::Ordering::SeqCst); |
| 452 | panic!("this is a panic"); |
| 453 | } |
| 454 | }); |
| 455 | let catch_panic = Func::wrap(&mut store, |mut caller: Caller<'_, _>| { |
| 456 | panic::catch_unwind(AssertUnwindSafe(|| { |
| 457 | drop( |
| 458 | caller |
| 459 | .get_export("panic") |
| 460 | .unwrap() |
| 461 | .into_func() |
| 462 | .unwrap() |
| 463 | .call(&mut caller, &[], &mut []), |
| 464 | ); |
| 465 | })) |
| 466 | .unwrap_err(); |
| 467 | }); |
| 468 | |
| 469 | let instance = Instance::new(&mut store, &module, &[panic.into(), catch_panic.into()])?; |
| 470 | let run = instance.get_typed_func::<(), ()>(&mut store, "run")?; |
| 471 | let trap = run.call(&mut store, ()).unwrap_err(); |
| 472 | let trace = trap.downcast_ref::<WasmBacktrace>().unwrap().frames(); |
| 473 | assert_eq!(trace.len(), 1); |
| 474 | assert_eq!(trace[0].func_index(), 3); |
| 475 | assert_eq!(num_panics.load(std::sync::atomic::Ordering::SeqCst), 2); |
| 476 | Ok(()) |
| 477 | } |
| 478 | |
| 479 | #[test] |
| 480 | fn rust_panic_start_function() -> Result<()> { |