1use std::panic;
2
3#[cfg(target_arch = "wasm32")]
4use wasm_bindgen::prelude::*;
5
6#[cfg(target_arch = "wasm32")]
7use std::cell::Cell;
8
9#[cfg(target_arch = "wasm32")]
10thread_local! {
11 static PANIC_CALLBACK: Cell<Option<js_sys::Function>> = Cell::new(None);
12}
13
14#[cfg(target_arch = "wasm32")]
15#[wasm_bindgen(js_name = "setPanicHook")]
16pub fn set_panic_hook(callback: js_sys::Function) {
17 PANIC_CALLBACK.with(|f| f.set(Some(callback)));
18 set_once();
19}
20
21#[cfg(not(target_arch = "wasm32"))]
22pub fn set_panic_hook(_callback: ()) {
23 }
25
26#[allow(deprecated)]
27#[cfg(target_arch = "wasm32")]
28fn hook_impl(info: &panic::PanicInfo) {
29 let message = info.to_string();
30
31 PANIC_CALLBACK.with(|f| {
32 if let Some(callback) = f.take() {
33 use js_sys::JsString;
34
35 if let Err(e) = callback.call1(&JsValue::UNDEFINED, &JsString::from(message)) {
36 web_sys::console::error_2(&"Failed to call panic callback:".into(), &e);
37 }
38 }
39 });
40}
41
42#[allow(deprecated)]
43#[cfg(not(target_arch = "wasm32"))]
44fn hook_impl(_info: &panic::PanicInfo) {
45 }
48
49#[allow(dead_code)]
52#[inline]
53fn set_once() {
54 use std::sync::Once;
55 static SET_HOOK: Once = Once::new();
56 SET_HOOK.call_once(|| {
57 let default_hook = panic::take_hook();
58 panic::set_hook(Box::new(move |panic_info| {
59 default_hook(panic_info);
61 hook_impl(panic_info);
62 }));
63 });
64}