wailsapp / wails

Create beautiful applications using Go
https://wails.io
MIT License
25.16k stars 1.21k forks source link

Calling event listener remover function on EventsOnce after it has fired causes TypeError #3850

Open dreamscached opened 1 week ago

dreamscached commented 1 week ago

Wails 2.9.1

Title basically explains the issue, which occurs here: https://github.com/wailsapp/wails/blob/5cd0caccc4e238e276611e7ed7fc91eac4765c46/v2/internal/frontend/runtime/desktop/events.js#L203-L212

This happens whenever a one-time event handler (registered with EventsOnce) is removed by remover function (namely, from frontend code) after it has already fired (and therefore its listener is now removed.)

Consider the following example:

// Code in JS frontend

const eventRemover = EventsOnce("myEvent", () => console.log("Event fired.");
window.removeEvent = () => eventRemover();
window.emitEvent = () => EventsEmit("emitMyEvent");
// Code in Go backend

func (a *App) onStartup() {
    runtime.EventsOn(a.Context, "emitMyEvent", func(optionalData ...interface{}) {
        runtime.EventsEmit(a.Context, "myEvent")
    })
}

Now, when myEvent fires and removes itself, its remover function will now cause a TypeError: demo

This does not happen when the remover is called before event is fired: demo

This can be fixed pretty easily, by making a remover no-op if the listener can't be found:

 function listenerOff(listener) {
   const eventName = listener.eventName;
+  const listeners = eventListeners[eventName];
+  if (listeners === undefined) return;

   eventListeners[eventName] = eventListeners[eventName].filter((l) => l !== listener);
   if (eventListeners[eventName].length === 0) {
       removeListener(eventName);
   }
 }
leaanthony commented 3 days ago

Good catch. Feel free to open a PR 👍