Add a WasmBacktrace::new() constructor (#5341)
* Add a `WasmBacktrace::new()` constructor This commit adds a method of manually capturing a backtrace of WebAssembly frames within a `Store`. The new constructor can be called with any `AsContext` values, primarily `&Store` and `&Caller`, during host functions to inspect the calling state. For now this does not respect the `Config::wasm_backtrace` option and instead unconditionally captures the backtrace. It's hoped that this can continue to adapt to needs of embedders by making it more configurable int he future if necessary. Closes #5339 * Split `new` into `capture` and `force_capture`
This commit is contained in:
@@ -1099,3 +1099,64 @@ async fn sync_then_async_trap() -> Result<()> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn standalone_backtrace() -> Result<()> {
|
||||
let engine = Engine::default();
|
||||
let mut store = Store::new(&engine, ());
|
||||
let trace = WasmBacktrace::capture(&store);
|
||||
assert!(trace.frames().is_empty());
|
||||
let module = Module::new(
|
||||
&engine,
|
||||
r#"
|
||||
(module
|
||||
(import "" "" (func $host))
|
||||
(func $foo (export "f") call $bar)
|
||||
(func $bar call $host)
|
||||
)
|
||||
"#,
|
||||
)?;
|
||||
let func = Func::wrap(&mut store, |cx: Caller<'_, ()>| {
|
||||
let trace = WasmBacktrace::capture(&cx);
|
||||
assert_eq!(trace.frames().len(), 2);
|
||||
let frame1 = &trace.frames()[0];
|
||||
let frame2 = &trace.frames()[1];
|
||||
assert_eq!(frame1.func_index(), 2);
|
||||
assert_eq!(frame1.func_name(), Some("bar"));
|
||||
assert_eq!(frame2.func_index(), 1);
|
||||
assert_eq!(frame2.func_name(), Some("foo"));
|
||||
});
|
||||
let instance = Instance::new(&mut store, &module, &[func.into()])?;
|
||||
let f = instance.get_typed_func::<(), ()>(&mut store, "f")?;
|
||||
f.call(&mut store, ())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(deprecated)]
|
||||
fn standalone_backtrace_disabled() -> Result<()> {
|
||||
let mut config = Config::new();
|
||||
config.wasm_backtrace(false);
|
||||
let engine = Engine::new(&config)?;
|
||||
let mut store = Store::new(&engine, ());
|
||||
let module = Module::new(
|
||||
&engine,
|
||||
r#"
|
||||
(module
|
||||
(import "" "" (func $host))
|
||||
(func $foo (export "f") call $bar)
|
||||
(func $bar call $host)
|
||||
)
|
||||
"#,
|
||||
)?;
|
||||
let func = Func::wrap(&mut store, |cx: Caller<'_, ()>| {
|
||||
let trace = WasmBacktrace::capture(&cx);
|
||||
assert_eq!(trace.frames().len(), 0);
|
||||
let trace = WasmBacktrace::force_capture(&cx);
|
||||
assert_eq!(trace.frames().len(), 2);
|
||||
});
|
||||
let instance = Instance::new(&mut store, &module, &[func.into()])?;
|
||||
let f = instance.get_typed_func::<(), ()>(&mut store, "f")?;
|
||||
f.call(&mut store, ())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user