From 56f1a303056ec54c998d26334664c5d97f23cfb8 Mon Sep 17 00:00:00 2001 From: "dennis@kobert.dev" Date: Thu, 25 Jul 2024 12:47:15 +0200 Subject: [PATCH] Use a mutex for storing the frontend state instead of a RefCell --- frontend/wasm/Cargo.toml | 1 - frontend/wasm/src/editor_api.rs | 24 ++++++++++++------------ frontend/wasm/src/lib.rs | 16 ++++++++-------- 3 files changed, 20 insertions(+), 21 deletions(-) diff --git a/frontend/wasm/Cargo.toml b/frontend/wasm/Cargo.toml index b4a5f851c8..9b4ea8f944 100644 --- a/frontend/wasm/Cargo.toml +++ b/frontend/wasm/Cargo.toml @@ -57,7 +57,6 @@ debug = true [package.metadata.wasm-pack.profile.dev] wasm-opt = false -panic = "unwind" [package.metadata.wasm-pack.profile.dev.wasm-bindgen] debug-js-glue = true diff --git a/frontend/wasm/src/editor_api.rs b/frontend/wasm/src/editor_api.rs index f97e59a213..33a96d8491 100644 --- a/frontend/wasm/src/editor_api.rs +++ b/frontend/wasm/src/editor_api.rs @@ -71,10 +71,10 @@ impl EditorHandle { pub fn new(frontend_message_handler_callback: js_sys::Function) -> Self { let editor = Editor::new(); let editor_handle = EditorHandle { frontend_message_handler_callback }; - if EDITOR.with(|editor_cell| editor_cell.set(RefCell::new(editor))).is_err() { + 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"); } - if EDITOR_HANDLE.with(|handle_cell| handle_cell.set(RefCell::new(editor_handle.clone()))).is_err() { + 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 @@ -888,29 +888,29 @@ fn set_timeout(f: &Closure, delay: Duration) { } /// Provides access to the `Editor` by calling the given closure with it as an argument. -fn editor(callback: impl FnOnce(&mut editor::application::Editor) -> T) -> T { +fn editor(callback: impl FnOnce(&mut editor::application::Editor) -> T) -> T { EDITOR.with(|editor| { - let Some(Ok(mut editor)) = editor.get().map(RefCell::try_borrow_mut) else { - // TODO: Investigate if this should just panic instead, and if not doing so right now may be the cause of silent crashes that don't inform the user that the app has panicked - log::error!("Failed to borrow the editor"); - return T::default(); + let mut guard = editor.lock(); + let Ok(Some(ref mut editor)) = guard.as_deref_mut() else { + panic!("Failed to borrow the editor"); }; - callback(&mut editor) + callback(editor) }) } /// Provides access to the `Editor` and its `EditorHandle` by calling the given closure with them as arguments. pub(crate) fn editor_and_handle(mut callback: impl FnMut(&mut Editor, &mut EditorHandle)) { - editor(|editor| { - EDITOR_HANDLE.with(|editor_handle| { - let Some(Ok(mut handle)) = editor_handle.get().map(RefCell::try_borrow_mut) else { + EDITOR_HANDLE.with(|editor_handle| { + editor(|editor| { + let mut guard = editor_handle.lock(); + let Ok(Some(ref mut editor_handle)) = guard.as_deref_mut() else { log::error!("Failed to borrow editor handle"); return; }; // Call the closure with the editor and its handle - callback(editor, &mut handle); + callback(editor, editor_handle); }) }); } diff --git a/frontend/wasm/src/lib.rs b/frontend/wasm/src/lib.rs index 9c84ed428c..ee9dc0cd19 100644 --- a/frontend/wasm/src/lib.rs +++ b/frontend/wasm/src/lib.rs @@ -9,18 +9,19 @@ pub mod helpers; use editor::messages::prelude::*; -use std::cell::{OnceCell, RefCell}; use std::panic; use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::Mutex; use wasm_bindgen::prelude::*; // Set up the persistent editor backend state pub static EDITOR_HAS_CRASHED: AtomicBool = AtomicBool::new(false); pub static NODE_GRAPH_ERROR_DISPLAYED: AtomicBool = AtomicBool::new(false); pub static LOGGER: WasmLog = WasmLog; + thread_local! { - pub static EDITOR: OnceCell> = const { OnceCell::new() }; - pub static EDITOR_HANDLE: OnceCell> = const { OnceCell::new() }; + pub static EDITOR: Mutex> = const { Mutex::new(None) }; + pub static EDITOR_HANDLE: Mutex> = const { Mutex::new(None) }; } /// Initialize the backend @@ -73,11 +74,10 @@ pub fn panic_hook(info: &panic::PanicInfo) { error!("{info}"); EDITOR_HANDLE.with(|editor_handle| { - editor_handle.get().map(|handle| { - handle - .borrow_mut() - .send_frontend_message_to_js_rust_proxy(FrontendMessage::DisplayDialogPanic { panic_info: info.to_string() }) - }) + let mut guard = editor_handle.lock(); + if let Ok(Some(ref mut handle)) = guard.as_deref_mut() { + handle.send_frontend_message_to_js_rust_proxy(FrontendMessage::DisplayDialogPanic { panic_info: info.to_string() }); + } }); }