From 4d360f67a4ae2314fbc8b83b01b701ec8e9cea5b Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Fri, 21 Apr 2023 09:22:34 +0200 Subject: [PATCH] eframe web: rememeber to unsubscribe from events on destroy --- crates/eframe/src/web/backend.rs | 49 ++++++++++++++++---------------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/crates/eframe/src/web/backend.rs b/crates/eframe/src/web/backend.rs index 83bdaec2097..48eac5de8b8 100644 --- a/crates/eframe/src/web/backend.rs +++ b/crates/eframe/src/web/backend.rs @@ -517,17 +517,19 @@ impl AppRunnerRef { if self.panic_handler.lock().has_panicked() { // Unsubscribe from all events so that we don't get any more callbacks // that will try to access the poisoned runner. - let events_to_unsubscribe: Vec<_> = - std::mem::take(&mut *self.events_to_unsubscribe.borrow_mut()); - if !events_to_unsubscribe.is_empty() { - log::debug!( - "Unsubscribing from {} events due to panic", - events_to_unsubscribe.len() - ); - for x in events_to_unsubscribe { - if let Err(err) = x.unsubscribe() { - log::error!("Failed to unsubscribe from event: {err:?}"); - } + self.unsubscribe_from_all_events(); + } + } + + fn unsubscribe_from_all_events(&self) { + let events_to_unsubscribe: Vec<_> = + std::mem::take(&mut *self.events_to_unsubscribe.borrow_mut()); + + if !events_to_unsubscribe.is_empty() { + log::debug!("Unsubscribing from {} events", events_to_unsubscribe.len()); + for x in events_to_unsubscribe { + if let Err(err) = x.unsubscribe() { + log::error!("Failed to unsubscribe from event: {err:?}"); } } } @@ -546,6 +548,7 @@ impl AppRunnerRef { } pub fn destroy(&self) { + self.unsubscribe_from_all_events(); if let Some(mut runner) = self.try_lock() { runner.destroy(); } @@ -574,21 +577,17 @@ impl AppRunnerRef { event_name: &'static str, mut closure: impl FnMut(E, &mut AppRunner) + 'static, ) -> Result<(), JsValue> { - // Create a JS closure based on the FnMut provided - let closure = Closure::wrap({ - // Clone atomics - let runner_ref = self.clone(); + let runner_ref = self.clone(); - Box::new(move |event: web_sys::Event| { - // Only call the wrapped closure if the egui code has not panicked - if let Some(mut runner_lock) = runner_ref.try_lock() { - // Cast the event to the expected event type - let event = event.unchecked_into::(); - - closure(event, &mut runner_lock); - } - }) as Box - }); + // Create a JS closure based on the FnMut provided + let closure = Closure::wrap(Box::new(move |event: web_sys::Event| { + // Only call the wrapped closure if the egui code has not panicked + if let Some(mut runner_lock) = runner_ref.try_lock() { + // Cast the event to the expected event type + let event = event.unchecked_into::(); + closure(event, &mut runner_lock); + } + }) as Box); // Add the event listener to the target target.add_event_listener_with_callback(event_name, closure.as_ref().unchecked_ref())?;