mod private
{
use std::panic;
pub fn hook( info : &panic::PanicHookInfo< '_ >, config : &Config )
{
hook_impl( info, config );
}
pub fn setup( config : Config )
{
use std::sync::Once;
static INIT_HOOK : Once = Once::new();
INIT_HOOK.call_once( ||
{
panic::set_hook( Box::new( move | info | hook( info, &config ) ) );
});
}
#[ derive( Debug ) ]
pub struct Config
{
pub with_location : bool,
pub with_stack_trace : bool,
}
impl Default for Config
{
fn default() -> Self
{
Self
{
with_location : true,
with_stack_trace : true,
}
}
}
#[ cfg( target_arch = "wasm32" ) ]
#[ allow( wasm_c_abi ) ]
mod imp
{
use super::Config;
use wasm_bindgen::prelude::*;
#[ wasm_bindgen ]
extern
{
type Error;
#[wasm_bindgen( js_namespace = console )]
fn error( msg : String );
#[wasm_bindgen( constructor )]
fn new() -> Error;
#[wasm_bindgen( structural, method, getter )]
fn stack( error : &Error ) -> String;
}
pub fn hook_impl( info : &panic::PanicHookInfo< '_ >, config : &Config )
{
use std::fmt::Write;
let mut message = "=== Error\n\n".to_string();
message.push_str( &info.to_string() );
if config.with_location
{
let location = info.location();
if let Some( location ) = location
{
let _ = write!( message, "\n\n = Location:\n\n {}:{}", location.file(), location.line() );
}
}
if config.with_stack_trace
{
message.push_str( "\n\n = Stack Trace:\n\n" );
let error_instance = Error::new();
let stack_trace = error_instance.stack();
message.push_str( &stack_trace );
message.push_str( "\n\n" );
}
error( message );
}
}
#[ cfg( not( target_arch = "wasm32" ) ) ]
mod imp
{
use super::Config;
use std::io::{ self, Write };
pub fn hook_impl( info : &std::panic::PanicHookInfo< '_ >, _config : &Config )
{
let _ = writeln!( io::stderr(), "{info}" );
}
}
pub use imp::*;
}
crate::mod_interface!
{
own use
{
Config,
hook,
setup,
};
}