eframe web: rememeber to unsubscribe from events on destroy

This commit is contained in:
Emil Ernerfeldt 2023-04-21 09:22:34 +02:00
parent ac50fa0d94
commit 4d360f67a4
1 changed files with 24 additions and 25 deletions

View File

@ -517,13 +517,16 @@ impl AppRunnerRef {
if self.panic_handler.lock().has_panicked() { if self.panic_handler.lock().has_panicked() {
// Unsubscribe from all events so that we don't get any more callbacks // Unsubscribe from all events so that we don't get any more callbacks
// that will try to access the poisoned runner. // that will try to access the poisoned runner.
self.unsubscribe_from_all_events();
}
}
fn unsubscribe_from_all_events(&self) {
let events_to_unsubscribe: Vec<_> = let events_to_unsubscribe: Vec<_> =
std::mem::take(&mut *self.events_to_unsubscribe.borrow_mut()); std::mem::take(&mut *self.events_to_unsubscribe.borrow_mut());
if !events_to_unsubscribe.is_empty() { if !events_to_unsubscribe.is_empty() {
log::debug!( log::debug!("Unsubscribing from {} events", events_to_unsubscribe.len());
"Unsubscribing from {} events due to panic",
events_to_unsubscribe.len()
);
for x in events_to_unsubscribe { for x in events_to_unsubscribe {
if let Err(err) = x.unsubscribe() { if let Err(err) = x.unsubscribe() {
log::error!("Failed to unsubscribe from event: {err:?}"); log::error!("Failed to unsubscribe from event: {err:?}");
@ -531,7 +534,6 @@ impl AppRunnerRef {
} }
} }
} }
}
/// Returns true if there has been a panic. /// Returns true if there has been a panic.
pub fn has_panicked(&self) -> bool { pub fn has_panicked(&self) -> bool {
@ -546,6 +548,7 @@ impl AppRunnerRef {
} }
pub fn destroy(&self) { pub fn destroy(&self) {
self.unsubscribe_from_all_events();
if let Some(mut runner) = self.try_lock() { if let Some(mut runner) = self.try_lock() {
runner.destroy(); runner.destroy();
} }
@ -574,21 +577,17 @@ impl AppRunnerRef {
event_name: &'static str, event_name: &'static str,
mut closure: impl FnMut(E, &mut AppRunner) + 'static, mut closure: impl FnMut(E, &mut AppRunner) + 'static,
) -> Result<(), JsValue> { ) -> 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| { // 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 // Only call the wrapped closure if the egui code has not panicked
if let Some(mut runner_lock) = runner_ref.try_lock() { if let Some(mut runner_lock) = runner_ref.try_lock() {
// Cast the event to the expected event type // Cast the event to the expected event type
let event = event.unchecked_into::<E>(); let event = event.unchecked_into::<E>();
closure(event, &mut runner_lock); closure(event, &mut runner_lock);
} }
}) as Box<dyn FnMut(web_sys::Event)> }) as Box<dyn FnMut(web_sys::Event)>);
});
// Add the event listener to the target // Add the event listener to the target
target.add_event_listener_with_callback(event_name, closure.as_ref().unchecked_ref())?; target.add_event_listener_with_callback(event_name, closure.as_ref().unchecked_ref())?;