Skip to content

Commit 79b8a35

Browse files
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 #8930 , and reported in #8930 (comment) * 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>
1 parent d349558 commit 79b8a35

5 files changed

Lines changed: 27 additions & 48 deletions

File tree

.changes/enhance-event-emit.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"tauri": patch:enhance
3+
---
4+
5+
Improve and optimize event emit calls.

.changes/fix-js-unlisten-all-race.md

Lines changed: 0 additions & 5 deletions
This file was deleted.

core/tauri/src/event/listener.rs

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -252,12 +252,6 @@ impl Listeners {
252252
}
253253
}
254254

255-
pub(crate) fn unlisten_all_js(&self, webview_label: &str) {
256-
let js_listeners = self.inner.as_ref();
257-
let mut js_listeners = js_listeners.js_event_listeners.lock().unwrap();
258-
js_listeners.remove(webview_label);
259-
}
260-
261255
pub(crate) fn has_js_listener<F: Fn(&EventTarget) -> bool>(
262256
&self,
263257
event: &str,
@@ -287,11 +281,12 @@ impl Listeners {
287281
let js_listeners = self.inner.js_event_listeners.lock().unwrap();
288282
webviews.try_for_each(|webview| {
289283
if let Some(handlers) = js_listeners.get(webview.label()).and_then(|s| s.get(event)) {
290-
let handlers = handlers.iter();
291-
let handlers = handlers.filter(|handler| match_any_or_filter(&handler.target, &filter));
292-
for JsHandler { target, .. } in handlers {
293-
webview.emit_js(emit_args, target)?;
294-
}
284+
let ids = handlers
285+
.iter()
286+
.filter(|handler| match_any_or_filter(&handler.target, &filter))
287+
.map(|handler| handler.id)
288+
.collect::<Vec<_>>();
289+
webview.emit_js(emit_args, &ids)?;
295290
}
296291

297292
Ok(())

core/tauri/src/event/mod.rs

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -174,21 +174,19 @@ pub fn listen_js_script(
174174
handler: &str,
175175
) -> String {
176176
format!(
177-
"
178-
(function () {{
177+
"(function () {{
179178
if (window['{listeners}'] === void 0) {{
180179
Object.defineProperty(window, '{listeners}', {{ value: Object.create(null) }});
181180
}}
182181
if (window['{listeners}']['{event}'] === void 0) {{
183-
Object.defineProperty(window['{listeners}'], '{event}', {{ value: [] }});
182+
Object.defineProperty(window['{listeners}'], '{event}', {{ value: Object.create(null) }});
184183
}}
185184
const eventListeners = window['{listeners}']['{event}']
186185
const listener = {{
187-
id: {event_id},
188186
target: {target},
189187
handler: {handler}
190188
}};
191-
eventListeners.push(listener);
189+
Object.defineProperty(eventListeners, '{event_id}', {{ value: listener, configurable: true }});
192190
}})()
193191
",
194192
listeners = listeners_object_name,
@@ -199,14 +197,14 @@ pub fn listen_js_script(
199197
pub fn emit_js_script(
200198
event_emit_function_name: &str,
201199
emit_args: &EmitArgs,
202-
serialized_target: &str,
200+
serialized_ids: &str,
203201
) -> crate::Result<String> {
204202
Ok(format!(
205-
"(function () {{ const fn = window['{}']; fn && fn({{event: {}, payload: {}}}, {target}) }})()",
203+
"(function () {{ const fn = window['{}']; fn && fn({{event: {}, payload: {}}}, {ids}) }})()",
206204
event_emit_function_name,
207205
emit_args.event,
208206
emit_args.payload,
209-
target = serialized_target,
207+
ids = serialized_ids,
210208
))
211209
}
212210

@@ -216,14 +214,10 @@ pub fn unlisten_js_script(
216214
event_id: EventId,
217215
) -> String {
218216
format!(
219-
"
220-
(function () {{
217+
"(function () {{
221218
const listeners = (window['{listeners_object_name}'] || {{}})['{event_name}']
222219
if (listeners) {{
223-
const index = window['{listeners_object_name}']['{event_name}'].findIndex(e => e.id === {event_id})
224-
if (index > -1) {{
225-
window['{listeners_object_name}']['{event_name}'].splice(index, 1)
226-
}}
220+
delete window['{listeners_object_name}']['{event_name}'][{event_id}];
227221
}}
228222
}})()
229223
",
@@ -232,14 +226,13 @@ pub fn unlisten_js_script(
232226

233227
pub fn event_initialization_script(function: &str, listeners: &str) -> String {
234228
format!(
235-
"
236-
Object.defineProperty(window, '{function}', {{
237-
value: function (eventData, target) {{
229+
"Object.defineProperty(window, '{function}', {{
230+
value: function (eventData, ids) {{
238231
const listeners = (window['{listeners}'] && window['{listeners}'][eventData.event]) || []
239-
for (let i = listeners.length - 1; i >= 0; i--) {{
240-
const listener = listeners[i]
241-
if (listener.target.kind === 'Any' || (listener.target.kind === target.kind && listener.target.label === target.label)) {{
242-
eventData.id = listener.id
232+
for (const id of ids) {{
233+
const listener = listeners[id]
234+
if (listener) {{
235+
eventData.id = id
243236
listener.handler(eventData)
244237
}}
245238
}}

core/tauri/src/webview/mod.rs

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -571,9 +571,6 @@ tauri::Builder::default()
571571
.on_page_load_handler
572572
.replace(Box::new(move |url, event| {
573573
if let Some(w) = manager_.get_webview(&label_) {
574-
if let PageLoadEvent::Started = event {
575-
w.unlisten_all_js();
576-
}
577574
if let Some(handler) = self.on_page_load_handler.as_ref() {
578575
handler(w, PageLoadPayload { url: &url, event });
579576
}
@@ -1302,17 +1299,11 @@ fn main() {
13021299
Ok(())
13031300
}
13041301

1305-
/// Unregister all JS event listeners.
1306-
pub(crate) fn unlisten_all_js(&self) {
1307-
let listeners = self.manager().listeners();
1308-
listeners.unlisten_all_js(self.label());
1309-
}
1310-
1311-
pub(crate) fn emit_js(&self, emit_args: &EmitArgs, target: &EventTarget) -> crate::Result<()> {
1302+
pub(crate) fn emit_js(&self, emit_args: &EmitArgs, ids: &[u32]) -> crate::Result<()> {
13121303
self.eval(&crate::event::emit_js_script(
13131304
self.manager().listeners().function_name(),
13141305
emit_args,
1315-
&serde_json::to_string(target)?,
1306+
&serde_json::to_string(ids)?,
13161307
)?)?;
13171308
Ok(())
13181309
}

0 commit comments

Comments
 (0)