Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(event): clear residual js listeners (#8916 ) #8930

Merged
6 changes: 6 additions & 0 deletions .changes/fix-clear-residual-listeners.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"tauri": patch:bug
---

Adds the `unlisten_all_js` method to struct `Webview` and calls it in on_page_load_handler when the corresponding webview window is refreshed.
This will only clean up all `js_listeners` for the window that was refreshed, and will not affect other windows.
12 changes: 12 additions & 0 deletions core/tauri/src/event/listener.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,18 @@ impl Listeners {
}
}

pub(crate) fn unlisten_all_js(&self, source_webview_label: &str) {
let inner_listeners = self.inner.as_ref();
let mut js_listeners = inner_listeners.js_event_listeners.lock().unwrap();
js_listeners
.iter_mut()
.for_each(|(webview_label, listener)| {
if webview_label == source_webview_label {
listener.clear()
}
})
}
canxin121 marked this conversation as resolved.
Show resolved Hide resolved

pub(crate) fn has_js_listener<F: Fn(&EventTarget) -> bool>(
&self,
event: &str,
Expand Down
18 changes: 18 additions & 0 deletions core/tauri/src/event/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,24 @@ pub fn unlisten_js_script(
)
}

pub fn unlisten_all_js_script(listeners_object_name: &str) -> String {
amrbashir marked this conversation as resolved.
Show resolved Hide resolved
format!(
r#"
(function () {{
var listenersObjectName = '{}';
if (window[listenersObjectName]) {{
for (var prop in window[listenersObjectName]) {{
if (window[listenersObjectName].hasOwnProperty(prop)) {{
window[listenersObjectName][prop] = undefined;
}}
}}
}}
}})();
"#,
listeners_object_name
)
}

pub fn event_initialization_script(function: &str, listeners: &str) -> String {
format!(
"
Expand Down
41 changes: 31 additions & 10 deletions core/tauri/src/webview/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -568,17 +568,27 @@ 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 {
match w.unlisten_all_js() {
Ok(_) => {
// println!("Clear all residual js listeners when page load.")
}
Err(e) => {
println!("Failed to clear residual js listeners when page load: {e}")
}
};
amrbashir marked this conversation as resolved.
Show resolved Hide resolved
}
}));
}
if let Some(handler) = self.on_page_load_handler.as_ref() {
handler(w, PageLoadPayload { url: &url, event });
}
}
}));

manager.manager().webview.prepare_webview(
manager,
Expand Down Expand Up @@ -1317,6 +1327,17 @@ fn main() {
Ok(())
}

/// Unregister all JS event listeners.
pub(crate) fn unlisten_all_js(&self) -> crate::Result<()> {
let listeners: &crate::event::Listeners = self.manager().listeners();
listeners.unlisten_all_js(self.label());
self.eval(&crate::event::unlisten_all_js_script(
amrbashir marked this conversation as resolved.
Show resolved Hide resolved
listeners.listeners_object_name(),
))?;

Ok(())
}

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(),
Expand Down