browser_panic_hook/
lib.rs1mod mode;
2mod utils;
3
4pub use mode::*;
5pub use utils::{escape_text, Unescaped};
6
7use std::panic;
8use std::sync::Once;
9
10fn handle<M>(mode: &M, info: &panic::PanicInfo)
11where
12 M: PresentationMode,
13{
14 let msg = format!("Application panicked: {info}");
16 web_sys::console::error_1(&msg.into());
17
18 let details = PanicDetails::from(info);
19 if let Err(err) = mode.present(details) {
20 web_sys::console::error_2(&"Panic hook failed".into(), &err.as_ref().into());
22 }
23}
24
25pub trait IntoPanicHook {
27 fn into_panic_hook(self) -> Box<dyn Fn(&panic::PanicInfo) + 'static + Sync + Send>;
28}
29
30impl<T> IntoPanicHook for T
31where
32 T: PresentationMode + 'static + Send + Sync,
33{
34 fn into_panic_hook(self) -> Box<dyn Fn(&panic::PanicInfo) + 'static + Sync + Send> {
35 Box::new(move |info| handle(&self, info))
36 }
37}
38
39static SET_HOOK: Once = Once::new();
40
41pub fn set_once<F, M>(f: F)
43where
44 F: FnOnce() -> M,
45 M: PresentationMode + 'static + Send + Sync,
46{
47 SET_HOOK.call_once(move || panic::set_hook(f().into_panic_hook()))
48}
49
50#[inline]
52pub fn set_once_default() {
53 set_once(|| Basic)
54}