diff --git a/.changes/fix-clear-residual-listeners.md b/.changes/fix-clear-residual-listeners.md new file mode 100644 index 000000000..d08ed8452 --- /dev/null +++ b/.changes/fix-clear-residual-listeners.md @@ -0,0 +1,5 @@ +--- +"tauri": patch:bug +--- + +Clear JS event listeneres on page load, which fixes zombie listeners when the page reloads. diff --git a/core/tauri/src/event/listener.rs b/core/tauri/src/event/listener.rs index 1ae128fd5..22bae8767 100644 --- a/core/tauri/src/event/listener.rs +++ b/core/tauri/src/event/listener.rs @@ -271,6 +271,12 @@ impl Listeners { } } + pub(crate) fn unlisten_all_js(&self, webview_label: &str) { + let inner_listeners = self.inner.as_ref(); + let mut js_listeners = inner_listeners.js_event_listeners.lock().unwrap(); + js_listeners.remove(webview_label); + } + pub(crate) fn has_js_listener bool>( &self, event: &str, diff --git a/core/tauri/src/webview/mod.rs b/core/tauri/src/webview/mod.rs index 532c0da03..6a4c95cf0 100644 --- a/core/tauri/src/webview/mod.rs +++ b/core/tauri/src/webview/mod.rs @@ -568,17 +568,20 @@ tauri::Builder::default() })); } - if let Some(on_page_load_handler) = self.on_page_load_handler.take() { - let label = pending.label.clone(); - let manager = manager.manager_owned(); - pending - .on_page_load_handler - .replace(Box::new(move |url, event| { - if let Some(w) = manager.get_webview(&label) { - on_page_load_handler(w, PageLoadPayload { url: &url, event }); + let label_ = pending.label.clone(); + let manager_ = manager.manager_owned(); + pending + .on_page_load_handler + .replace(Box::new(move |url, event| { + if let Some(w) = manager_.get_webview(&label_) { + if let PageLoadEvent::Finished = event { + w.unlisten_all_js(); } - })); - } + if let Some(handler) = self.on_page_load_handler.as_ref() { + handler(w, PageLoadPayload { url: &url, event }); + } + } + })); manager.manager().webview.prepare_webview( manager, @@ -1317,6 +1320,12 @@ fn main() { Ok(()) } + /// Unregister all JS event listeners. + pub(crate) fn unlisten_all_js(&self) { + let listeners = self.manager().listeners(); + listeners.unlisten_all_js(self.label()); + } + pub(crate) fn emit_js(&self, emit_args: &EmitArgs, target: &EventTarget) -> crate::Result<()> { self.eval(&crate::event::emit_js_script( self.manager().listeners().function_name(),