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

useEventListener can be confused to not clean up events. #2825

Closed
7 tasks done
WORMSS opened this issue Feb 28, 2023 · 6 comments
Closed
7 tasks done

useEventListener can be confused to not clean up events. #2825

WORMSS opened this issue Feb 28, 2023 · 6 comments

Comments

@WORMSS
Copy link
Contributor

WORMSS commented Feb 28, 2023

Describe the bug

I will start off, that someone would have to go out of their way to cause this bug, but I just thought best to show it exists..

  1. With a computed Target, when the target value is changed, it removes listeners from the old element, creates a new set of listeners on the new element
  2. capture: true binds to a different set of internal in the element.
  • Eg: you cannot do el.addEventListener("click", handle, { capture: true }) and then el.removeEventListener("click", handle, { capture: false}) to remove the event listener.
  1. if you change the options to true object while the handler is attached to 1 target
  2. Then switch the ref to target 2, it will attempt to remove the handler from target 1 with the incorrect capture option.

This is ALSO true if you change the options object, and then remove the element off the screen. shared.tryOnScopeDispose(stop) could fail to remove the listener.. but You would have to start self referencing in the callback to attempt to stop that type of GC cleanup.

I believe a simple fix of

-  const stopWatch = vueDemi.watch(() => unrefElement(target), (el) => {
-   cleanup();
-   if (!el)
-     return;
-   el.addEventListener(event, listener, options);
-   cleanup = () => {
-     el.removeEventListener(event, listener, options);
-     cleanup = shared.noop;
-   };
-  }, { immediate: true, flush: "post" });
+  const stopWatch = vueDemi.watch(() => unrefElement(target), (el) => {
+    cleanup();
+    if (!el)
+      return;
+    const { capture } = options;
+    el.addEventListener(event, listener, { ...options, capture });
+    cleanup = () => {
+      el.removeEventListener(event, listener, { ...options, capture });
+      cleanup = shared.noop;
+    };
+  }, { immediate: true, flush: "post" });

Reproduction

https://sfc.vuejs.org/#eNrFVcFu2zAM/RXOGJAES220xyxJW7S9FeuwdYcBPtSxmVitLQmSHLcw/O+jLNuN0ybrYcAuiSU+PpJPFFV5l1L62wK9mTfXsWLSgEZTyGXIWS6FMlCBwvUUYpHLwmAypWUUG7bFKRScTFDDWokcRsQy2vEqNN5skZtbpg1yVD3ugoBkDGKhcPQ15LHg2oCJ1AbNKSxsuPFkb//swP7Pkpk4bY1GFbgPIFOX+Xg8gcXSJT12v7skEzjvk5h1YSeTId39IT5nnpz7jFOt9/hsXjMR0jD6aLJ00o0rCIJ+n2nIowRJMcY3PQa+//pxc/sb1kJBwrTMohdrZhxMimAwpx1DhxCBJs0zBLF6xNhAKYosAV2s10xj421SirAqNn7IAeJImkIhVUhqTUNe2zz3z6otZwqhF2csfgq9KYxxa5qCK0sjCkMi+NsoKxC+LODhc3VN6fhclONJDVfWCz5X5OM7rldh6jDkDxS0nnYK9CI71vY4RyPaD/m64KSH4CB4w3rnfEh8l4hb+m1d5Ptpb8uGektz32TVsew2QlsUEb3ddVzzwF0VuiS06I6CVgBzkTX/9JWxpZMh9FwwOA09OgdjBDGQ9SDu7BDubqVRUWsInr3YnC0nxNQxBnUr3gHmqzTiGwQX4INp/Nt0B/BhzhDxpOnqptmAUk0yGhhpRG2LyKkbcrHFxM2P3fSOF9t2yt+q+K/SrIRJh7SX366Pa6Xfkaqk3YJHKxoDRhzQy3K1znSt3d2gLamERGVeGg4uaNIRQEc5WnCZkvyMhgp9R1JmDBO/r2QetM0+dyXaW7sIvXaIht6yq2oeOMBBMKXWgc+G4FQNnC6asslvcIvJe3CIM6iqdl7X9bvB93n6VumI2g3L1I6TfaYuM6lwSaDmcCzGru2I6MeCN/Xco3iSR9J/1ILTY9tMnbA1UFwK5Joj9Oh5tOvQS42RehYEeh3bJ/pR+0JtAvryVcENy9FHnZ+slCipl4iYpvQOx0mCORsSlWXpF1w+bXx6wyxRg6HjXAWMJ/js5wOS7qHWKU2a5BjVEHmUzL76H6GyuHeJyB40d0edKCS7QnVMrj3oG8ksLY302qv/ADe/H8Y=

System Info

System:
    OS: Windows 10 10.0.19044
    CPU: (8) x64 Intel(R) Xeon(R) CPU E5-1620 v3 @ 3.50GHz
    Memory: 2.21 GB / 15.92 GB
  Binaries:
    Node: 19.6.0 - ~\nodejs\node.EXE
    npm: 8.19.1 - C:\Development\alloy-web2\node_modules\.bin\npm.CMD
  Browsers:
    Chrome: 110.0.5481.105
    Edge: Spartan (44.19041.1266.0), Chromium (110.0.1587.57)        
    Internet Explorer: 11.0.19041.1566
  npmPackages:
    @vueuse/core: ^9.3.1 => 9.3.1
    @vueuse/gesture: ^2.0.0-beta.1 => 2.0.0-beta.1
    vue: ^3.2.41 => 3.2.45

Used Package Manager

npm

Validations

@WORMSS
Copy link
Contributor Author

WORMSS commented Feb 28, 2023

Actually, ignore my "simple" fix, I just realised it doesn't work with when options is empty or a string..

but it should be similar, but with type checking

@stale
Copy link

stale bot commented Apr 29, 2023

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Apr 29, 2023
@WORMSS
Copy link
Contributor Author

WORMSS commented Apr 29, 2023

Not Stale

@stale stale bot removed the stale label Apr 29, 2023
@WORMSS
Copy link
Contributor Author

WORMSS commented Jun 26, 2023

Has any maintainer even seen this issue yet? Care to comment?

@stale
Copy link

stale bot commented Aug 26, 2023

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@WORMSS
Copy link
Contributor Author

WORMSS commented Aug 26, 2023

Thank you @antfu

@stale stale bot removed the stale label Aug 26, 2023
@antfu antfu closed this as completed in 3ef59cb Aug 28, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant