diff --git a/.changes/enhance-event-emit.md b/.changes/enhance-event-emit.md new file mode 100644 index 000000000..492e208b7 --- /dev/null +++ b/.changes/enhance-event-emit.md @@ -0,0 +1,5 @@ +--- +"tauri": patch:enhance +--- + +Improve and optimize event emit calls. diff --git a/.changes/fix-js-unlisten-all-race.md b/.changes/fix-js-unlisten-all-race.md deleted file mode 100644 index bf3be508a..000000000 --- a/.changes/fix-js-unlisten-all-race.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": patch:bug ---- - -Fix old JS listeners being dropped on page load after it was possible to create new listeners. diff --git a/core/tauri/src/event/listener.rs b/core/tauri/src/event/listener.rs index 4dc23444a..26e10d312 100644 --- a/core/tauri/src/event/listener.rs +++ b/core/tauri/src/event/listener.rs @@ -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 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::>(); + webview.emit_js(emit_args, &ids)?; } Ok(()) diff --git a/core/tauri/src/event/mod.rs b/core/tauri/src/event/mod.rs index 54e5144a1..3e2fd207c 100644 --- a/core/tauri/src/event/mod.rs +++ b/core/tauri/src/event/mod.rs @@ -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 { 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) }} }} diff --git a/core/tauri/src/webview/mod.rs b/core/tauri/src/webview/mod.rs index 093e21765..28deaac00 100644 --- a/core/tauri/src/webview/mod.rs +++ b/core/tauri/src/webview/mod.rs @@ -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(()) }