#[cfg(feature = "console_error_panic_hook")]
use std::panic;
#[cfg(feature = "console_error_panic_hook")]
#[cfg_attr(not(target_arch = "wasm32"), allow(dead_code))]
const PANIC_STASH_KEY: &str = "__ifclite_wasm_panic";
#[cfg(all(feature = "console_error_panic_hook", target_arch = "wasm32"))]
fn stash_panic_location(info: &panic::PanicHookInfo<'_>) {
let Some(location) = info.location() else {
return;
};
stash_location_parts(location.file(), location.line(), location.column());
}
#[cfg(all(feature = "console_error_panic_hook", target_arch = "wasm32"))]
#[doc(hidden)]
pub fn stash_location_parts(file: &str, line: u32, column: u32) {
let text = format!("{}:{}:{}", sanitize_panic_path(file), line, column);
let stash = js_sys::Object::new();
let ok = js_sys::Reflect::set(
&stash,
&wasm_bindgen::JsValue::from_str("location"),
&wasm_bindgen::JsValue::from_str(&text),
)
.is_ok()
&& js_sys::Reflect::set(
&stash,
&wasm_bindgen::JsValue::from_str("at"),
&wasm_bindgen::JsValue::from_f64(js_sys::Date::now()),
)
.is_ok();
if ok {
let _ = js_sys::Reflect::set(
&js_sys::global(),
&wasm_bindgen::JsValue::from_str(PANIC_STASH_KEY),
&stash.into(),
);
}
}
#[cfg_attr(
any(not(feature = "console_error_panic_hook"), not(target_arch = "wasm32")),
allow(dead_code)
)]
fn sanitize_panic_path(file: &str) -> String {
let unified = file.replace('\\', "/");
if let Some(idx) = unified.find("/registry/src/") {
let rest = &unified[idx + "/registry/src/".len()..];
if let Some(slash) = rest.find('/') {
return rest[slash + 1..].to_string();
}
}
if let Some(idx) = unified.rfind("/rust/") {
return unified[idx + 1..].to_string();
}
let is_absolute = unified.starts_with('/') || unified.as_bytes().get(1) == Some(&b':');
if !is_absolute {
return unified;
}
let segments: Vec<&str> = unified.split('/').filter(|s| !s.is_empty()).collect();
let after_home = match segments.iter().position(|s| *s == "Users" || *s == "home") {
Some(idx) => &segments[(idx + 2).min(segments.len())..],
None => &segments[..],
};
let keep = after_home.len().saturating_sub(4);
after_home[keep..].join("/")
}
pub fn set_panic_hook() {
#[cfg(feature = "console_error_panic_hook")]
{
use std::sync::Once;
static SET_HOOK: Once = Once::new();
SET_HOOK.call_once(|| {
panic::set_hook(Box::new(|info| {
#[cfg(target_arch = "wasm32")]
stash_panic_location(info);
console_error_panic_hook::hook(info);
}));
});
}
}
#[cfg(test)]
#[path = "utils_tests.rs"]
mod tests;