mirror of
https://github.com/tauri-apps/tauri.git
synced 2026-04-01 10:01:07 +02:00
enhance(core/event): filter js listeners on rust side only then emit filtered ids to be triggered (#9151)
* fix(core/event): filter js listeners on rust side only then emit filtered ids to be triggerd fix regression introduced in https://github.com/tauri-apps/tauri/pull/8930 , and reported in https://github.com/tauri-apps/tauri/pull/8930#issuecomment-1986279046 * Update .changes/core-js-unlisten-all-regression.md Co-authored-by: Lucas Fernandes Nogueira <lucas@tauri.app> * Discard changes to .changes/core-js-unlisten-all-regression.md * object.defineproperty * add change file [skip ci] --------- Co-authored-by: Lucas Fernandes Nogueira <lucas@tauri.app>
This commit is contained in:
5
.changes/enhance-event-emit.md
Normal file
5
.changes/enhance-event-emit.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"tauri": patch:enhance
|
||||
---
|
||||
|
||||
Improve and optimize event emit calls.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"tauri": patch:bug
|
||||
---
|
||||
|
||||
Fix old JS listeners being dropped on page load after it was possible to create new listeners.
|
||||
@@ -252,12 +252,6 @@ impl Listeners {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn unlisten_all_js(&self, webview_label: &str) {
|
||||
let js_listeners = self.inner.as_ref();
|
||||
let mut js_listeners = js_listeners.js_event_listeners.lock().unwrap();
|
||||
js_listeners.remove(webview_label);
|
||||
}
|
||||
|
||||
pub(crate) fn has_js_listener<F: Fn(&EventTarget) -> bool>(
|
||||
&self,
|
||||
event: &str,
|
||||
@@ -287,11 +281,12 @@ impl Listeners {
|
||||
let js_listeners = self.inner.js_event_listeners.lock().unwrap();
|
||||
webviews.try_for_each(|webview| {
|
||||
if let Some(handlers) = js_listeners.get(webview.label()).and_then(|s| s.get(event)) {
|
||||
let handlers = handlers.iter();
|
||||
let handlers = handlers.filter(|handler| match_any_or_filter(&handler.target, &filter));
|
||||
for JsHandler { target, .. } in handlers {
|
||||
webview.emit_js(emit_args, target)?;
|
||||
}
|
||||
let ids = handlers
|
||||
.iter()
|
||||
.filter(|handler| match_any_or_filter(&handler.target, &filter))
|
||||
.map(|handler| handler.id)
|
||||
.collect::<Vec<_>>();
|
||||
webview.emit_js(emit_args, &ids)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -174,21 +174,19 @@ pub fn listen_js_script(
|
||||
handler: &str,
|
||||
) -> String {
|
||||
format!(
|
||||
"
|
||||
(function () {{
|
||||
"(function () {{
|
||||
if (window['{listeners}'] === void 0) {{
|
||||
Object.defineProperty(window, '{listeners}', {{ value: Object.create(null) }});
|
||||
}}
|
||||
if (window['{listeners}']['{event}'] === void 0) {{
|
||||
Object.defineProperty(window['{listeners}'], '{event}', {{ value: [] }});
|
||||
Object.defineProperty(window['{listeners}'], '{event}', {{ value: Object.create(null) }});
|
||||
}}
|
||||
const eventListeners = window['{listeners}']['{event}']
|
||||
const listener = {{
|
||||
id: {event_id},
|
||||
target: {target},
|
||||
handler: {handler}
|
||||
}};
|
||||
eventListeners.push(listener);
|
||||
Object.defineProperty(eventListeners, '{event_id}', {{ value: listener, configurable: true }});
|
||||
}})()
|
||||
",
|
||||
listeners = listeners_object_name,
|
||||
@@ -199,14 +197,14 @@ pub fn listen_js_script(
|
||||
pub fn emit_js_script(
|
||||
event_emit_function_name: &str,
|
||||
emit_args: &EmitArgs,
|
||||
serialized_target: &str,
|
||||
serialized_ids: &str,
|
||||
) -> crate::Result<String> {
|
||||
Ok(format!(
|
||||
"(function () {{ const fn = window['{}']; fn && fn({{event: {}, payload: {}}}, {target}) }})()",
|
||||
"(function () {{ const fn = window['{}']; fn && fn({{event: {}, payload: {}}}, {ids}) }})()",
|
||||
event_emit_function_name,
|
||||
emit_args.event,
|
||||
emit_args.payload,
|
||||
target = serialized_target,
|
||||
ids = serialized_ids,
|
||||
))
|
||||
}
|
||||
|
||||
@@ -216,14 +214,10 @@ pub fn unlisten_js_script(
|
||||
event_id: EventId,
|
||||
) -> String {
|
||||
format!(
|
||||
"
|
||||
(function () {{
|
||||
"(function () {{
|
||||
const listeners = (window['{listeners_object_name}'] || {{}})['{event_name}']
|
||||
if (listeners) {{
|
||||
const index = window['{listeners_object_name}']['{event_name}'].findIndex(e => e.id === {event_id})
|
||||
if (index > -1) {{
|
||||
window['{listeners_object_name}']['{event_name}'].splice(index, 1)
|
||||
}}
|
||||
delete window['{listeners_object_name}']['{event_name}'][{event_id}];
|
||||
}}
|
||||
}})()
|
||||
",
|
||||
@@ -232,14 +226,13 @@ pub fn unlisten_js_script(
|
||||
|
||||
pub fn event_initialization_script(function: &str, listeners: &str) -> String {
|
||||
format!(
|
||||
"
|
||||
Object.defineProperty(window, '{function}', {{
|
||||
value: function (eventData, target) {{
|
||||
"Object.defineProperty(window, '{function}', {{
|
||||
value: function (eventData, ids) {{
|
||||
const listeners = (window['{listeners}'] && window['{listeners}'][eventData.event]) || []
|
||||
for (let i = listeners.length - 1; i >= 0; i--) {{
|
||||
const listener = listeners[i]
|
||||
if (listener.target.kind === 'Any' || (listener.target.kind === target.kind && listener.target.label === target.label)) {{
|
||||
eventData.id = listener.id
|
||||
for (const id of ids) {{
|
||||
const listener = listeners[id]
|
||||
if (listener) {{
|
||||
eventData.id = id
|
||||
listener.handler(eventData)
|
||||
}}
|
||||
}}
|
||||
|
||||
@@ -571,9 +571,6 @@ tauri::Builder::default()
|
||||
.on_page_load_handler
|
||||
.replace(Box::new(move |url, event| {
|
||||
if let Some(w) = manager_.get_webview(&label_) {
|
||||
if let PageLoadEvent::Started = event {
|
||||
w.unlisten_all_js();
|
||||
}
|
||||
if let Some(handler) = self.on_page_load_handler.as_ref() {
|
||||
handler(w, PageLoadPayload { url: &url, event });
|
||||
}
|
||||
@@ -1302,17 +1299,11 @@ 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<()> {
|
||||
pub(crate) fn emit_js(&self, emit_args: &EmitArgs, ids: &[u32]) -> crate::Result<()> {
|
||||
self.eval(&crate::event::emit_js_script(
|
||||
self.manager().listeners().function_name(),
|
||||
emit_args,
|
||||
&serde_json::to_string(target)?,
|
||||
&serde_json::to_string(ids)?,
|
||||
)?)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user