branch: main
panic_abort.rs
1766 bytesRaw
use std::panic;
#[cfg(target_arch = "wasm32")]
use wasm_bindgen::prelude::*;
#[cfg(target_arch = "wasm32")]
use std::cell::Cell;
#[cfg(target_arch = "wasm32")]
thread_local! {
static PANIC_CALLBACK: Cell<Option<js_sys::Function>> = Cell::new(None);
}
#[cfg(target_arch = "wasm32")]
#[wasm_bindgen(js_name = "setPanicHook")]
pub fn set_panic_hook(callback: js_sys::Function) {
PANIC_CALLBACK.with(|f| f.set(Some(callback)));
set_once();
}
#[cfg(not(target_arch = "wasm32"))]
pub fn set_panic_hook(_callback: ()) {
// No-op on non-wasm targets
}
#[allow(deprecated)]
#[cfg(target_arch = "wasm32")]
fn hook_impl(info: &panic::PanicInfo) {
let message = info.to_string();
PANIC_CALLBACK.with(|f| {
if let Some(callback) = f.take() {
use js_sys::JsString;
if let Err(e) = callback.call1(&JsValue::UNDEFINED, &JsString::from(message)) {
web_sys::console::error_2(&"Failed to call panic callback:".into(), &e);
}
}
});
}
#[allow(deprecated)]
#[cfg(not(target_arch = "wasm32"))]
fn hook_impl(_info: &panic::PanicInfo) {
// On non-wasm targets, we don't have contexts to abort
// This is a no-op, but maintains the same interface
}
/// Set the WASM reinitialization panic hook the first time this is called.
/// Subsequent invocations do nothing.
#[allow(dead_code)]
#[inline]
fn set_once() {
use std::sync::Once;
static SET_HOOK: Once = Once::new();
SET_HOOK.call_once(|| {
let default_hook = panic::take_hook();
panic::set_hook(Box::new(move |panic_info| {
// First call the existing hook (console_error_panic_hook if set)
default_hook(panic_info);
hook_impl(panic_info);
}));
});
}