Fix missing crash dialog for panics thrown inside requestAnimationFrame loop (#3788)
* add crash dialog in RAF path * removed panic!() * removed redundant string allocationa dn duplication between function * fixed allocation * removed bloated code
This commit is contained in:
parent
0531769c41
commit
9d83998463
|
|
@ -5,7 +5,7 @@
|
||||||
// on the dispatcher messaging system and more complex Rust data types.
|
// on the dispatcher messaging system and more complex Rust data types.
|
||||||
//
|
//
|
||||||
use crate::helpers::translate_key;
|
use crate::helpers::translate_key;
|
||||||
use crate::{EDITOR_HANDLE, EDITOR_HAS_CRASHED, Error, MESSAGE_BUFFER};
|
use crate::{EDITOR_HANDLE, EDITOR_HAS_CRASHED, Error, MESSAGE_BUFFER, PANIC_DIALOG_MESSAGE_CALLBACK};
|
||||||
use editor::consts::FILE_EXTENSION;
|
use editor::consts::FILE_EXTENSION;
|
||||||
use editor::messages::clipboard::utility_types::ClipboardContentRaw;
|
use editor::messages::clipboard::utility_types::ClipboardContentRaw;
|
||||||
use editor::messages::input_mapper::utility_types::input_keyboard::ModifierKeys;
|
use editor::messages::input_mapper::utility_types::input_keyboard::ModifierKeys;
|
||||||
|
|
@ -78,6 +78,16 @@ impl EditorHandle {
|
||||||
pub fn send_frontend_message_to_js_rust_proxy(&self, message: FrontendMessage) {
|
pub fn send_frontend_message_to_js_rust_proxy(&self, message: FrontendMessage) {
|
||||||
self.send_frontend_message_to_js(message);
|
self.send_frontend_message_to_js(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn initialize_handle(frontend_message_handler_callback: js_sys::Function) -> EditorHandle {
|
||||||
|
let panic_callback = frontend_message_handler_callback.clone();
|
||||||
|
let editor_handle = EditorHandle { frontend_message_handler_callback };
|
||||||
|
if EDITOR_HANDLE.with(|handle| handle.lock().ok().map(|mut guard| *guard = Some(editor_handle.clone()))).is_none() {
|
||||||
|
log::error!("Attempted to initialize the editor handle more than once");
|
||||||
|
}
|
||||||
|
PANIC_DIALOG_MESSAGE_CALLBACK.with_borrow_mut(|callback| *callback = Some(panic_callback));
|
||||||
|
editor_handle
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
|
|
@ -97,23 +107,16 @@ impl EditorHandle {
|
||||||
uuid_random_seed,
|
uuid_random_seed,
|
||||||
);
|
);
|
||||||
|
|
||||||
let editor_handle = EditorHandle { frontend_message_handler_callback };
|
|
||||||
if EDITOR.with(|handle| handle.lock().ok().map(|mut guard| *guard = Some(editor))).is_none() {
|
if EDITOR.with(|handle| handle.lock().ok().map(|mut guard| *guard = Some(editor))).is_none() {
|
||||||
log::error!("Attempted to initialize the editor more than once");
|
log::error!("Attempted to initialize the editor more than once");
|
||||||
}
|
}
|
||||||
if EDITOR_HANDLE.with(|handle| handle.lock().ok().map(|mut guard| *guard = Some(editor_handle.clone()))).is_none() {
|
|
||||||
log::error!("Attempted to initialize the editor handle more than once");
|
Self::initialize_handle(frontend_message_handler_callback)
|
||||||
}
|
|
||||||
editor_handle
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "native")]
|
#[cfg(feature = "native")]
|
||||||
pub fn create(_platform: String, _uuid_random_seed: u64, frontend_message_handler_callback: js_sys::Function) -> EditorHandle {
|
pub fn create(_platform: String, _uuid_random_seed: u64, frontend_message_handler_callback: js_sys::Function) -> EditorHandle {
|
||||||
let editor_handle = EditorHandle { frontend_message_handler_callback };
|
Self::initialize_handle(frontend_message_handler_callback)
|
||||||
if EDITOR_HANDLE.with(|handle| handle.lock().ok().map(|mut guard| *guard = Some(editor_handle.clone()))).is_none() {
|
|
||||||
log::error!("Attempted to initialize the editor handle more than once");
|
|
||||||
}
|
|
||||||
editor_handle
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sends a message to the dispatcher in the Editor Backend
|
// Sends a message to the dispatcher in the Editor Backend
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ thread_local! {
|
||||||
pub static EDITOR: Mutex<Option<editor::application::Editor>> = const { Mutex::new(None) };
|
pub static EDITOR: Mutex<Option<editor::application::Editor>> = const { Mutex::new(None) };
|
||||||
pub static MESSAGE_BUFFER: std::cell::RefCell<Vec<Message>> = const { std::cell::RefCell::new(Vec::new()) };
|
pub static MESSAGE_BUFFER: std::cell::RefCell<Vec<Message>> = const { std::cell::RefCell::new(Vec::new()) };
|
||||||
pub static EDITOR_HANDLE: Mutex<Option<editor_api::EditorHandle>> = const { Mutex::new(None) };
|
pub static EDITOR_HANDLE: Mutex<Option<editor_api::EditorHandle>> = const { Mutex::new(None) };
|
||||||
|
pub static PANIC_DIALOG_MESSAGE_CALLBACK: std::cell::RefCell<Option<js_sys::Function>> = const { std::cell::RefCell::new(None) };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initialize the backend
|
/// Initialize the backend
|
||||||
|
|
@ -72,12 +73,65 @@ pub fn panic_hook(info: &panic::PanicHookInfo) {
|
||||||
|
|
||||||
log::error!("{info}");
|
log::error!("{info}");
|
||||||
|
|
||||||
EDITOR_HANDLE.with(|editor_handle| {
|
// Prefer using the raw JS callback to avoid mutex lock contention inside the panic hook.
|
||||||
let mut guard = editor_handle.lock();
|
if let Err(info) = send_panic_dialog_via_callback(info) {
|
||||||
if let Ok(Some(handle)) = guard.as_deref_mut() {
|
send_panic_dialog_deferred(info);
|
||||||
handle.send_frontend_message_to_js_rust_proxy(FrontendMessage::DisplayDialogPanic { panic_info: info.to_string() });
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn send_panic_dialog_via_callback(panic_info: String) -> Result<(), String> {
|
||||||
|
let message = FrontendMessage::DisplayDialogPanic { panic_info };
|
||||||
|
let message_type = message.to_discriminant().local_name();
|
||||||
|
let Ok(message_data) = serde_wasm_bindgen::to_value(&message) else {
|
||||||
|
log::error!("Failed to serialize crash dialog panic message");
|
||||||
|
let FrontendMessage::DisplayDialogPanic { panic_info } = message else {
|
||||||
|
unreachable!("Message variant changed unexpectedly")
|
||||||
|
};
|
||||||
|
return Err(panic_info);
|
||||||
|
};
|
||||||
|
|
||||||
|
PANIC_DIALOG_MESSAGE_CALLBACK.with(|callback| {
|
||||||
|
let callback_ref = callback.borrow();
|
||||||
|
let Some(callback) = callback_ref.as_ref() else {
|
||||||
|
let FrontendMessage::DisplayDialogPanic { panic_info } = message else {
|
||||||
|
unreachable!("Message variant changed unexpectedly")
|
||||||
|
};
|
||||||
|
return Err(panic_info);
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Err(error) = callback.call2(&JsValue::null(), &JsValue::from(message_type), &message_data) {
|
||||||
|
log::error!("Failed to send crash dialog panic message to JS: {:?}", error);
|
||||||
|
let FrontendMessage::DisplayDialogPanic { panic_info } = message else {
|
||||||
|
unreachable!("Message variant changed unexpectedly")
|
||||||
|
};
|
||||||
|
return Err(panic_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "native"))]
|
||||||
|
fn send_panic_dialog_deferred(panic_info: String) {
|
||||||
|
let callback = Closure::once_into_js(move || {
|
||||||
|
if send_panic_dialog_via_callback(panic_info).is_err() {
|
||||||
|
log::error!("Failed to send crash dialog after panic because the editor handle is unavailable");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let Some(window) = web_sys::window() else {
|
||||||
|
log::error!("Failed to schedule crash dialog after panic because no window exists");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
if window.set_timeout_with_callback_and_timeout_and_arguments_0(callback.unchecked_ref(), 0).is_err() {
|
||||||
|
log::error!("Failed to schedule crash dialog after panic with setTimeout");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "native")]
|
||||||
|
fn send_panic_dialog_deferred(_panic_info: String) {
|
||||||
|
// Native builds do not use `setTimeout`, so just log the failure in the caller's context.
|
||||||
}
|
}
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue