[frontend] Event listener leaks: 2,225 addEventListener vs 242 removeEventListener #791

Open
opened 2026-06-03 00:40:12 +02:00 by sleepy · 0 comments
Owner

Finding

Frontend JS has 2,225 addEventListener calls but only 242 removeEventListener calls — a 9:1 ratio indicating systematic listener leaks. Worst offenders:

File addEventListener removeEventListener
document.js 211 21
chat.js 30 0
notes.js 144 8
settings.js 157 3
emailLibrary.js 111 13
slashCommands.js 57 54

Impact

  • chat.js has zero cleanup — every listener added is permanent
  • notes.js leaks 136 listeners (144 added, 8 removed)
  • settings.js leaks 154 listeners
  • Over time, switching sessions, opening/closing modals, and navigating features accumulates orphaned listeners
  • This causes memory leaks and potential duplicate-handler bugs (e.g., handlers firing multiple times after re-initialization)

Recommendation

  1. Use AbortController pattern: pass a single signal to all addEventListener calls, then controller.abort() to clean up all at once
  2. Track listeners per module and clean up on teardown
  3. Add cleanup/destroy methods to each module that removes its listeners
## Finding Frontend JS has **2,225 addEventListener** calls but only **242 removeEventListener** calls — a 9:1 ratio indicating systematic listener leaks. Worst offenders: | File | addEventListener | removeEventListener | |------|-----------------|-------------------| | document.js | 211 | 21 | | chat.js | 30 | **0** | | notes.js | 144 | 8 | | settings.js | 157 | 3 | | emailLibrary.js | 111 | 13 | | slashCommands.js | 57 | 54 | ## Impact - **chat.js** has zero cleanup — every listener added is permanent - **notes.js** leaks 136 listeners (144 added, 8 removed) - **settings.js** leaks 154 listeners - Over time, switching sessions, opening/closing modals, and navigating features accumulates orphaned listeners - This causes memory leaks and potential duplicate-handler bugs (e.g., handlers firing multiple times after re-initialization) ## Recommendation 1. Use AbortController pattern: pass a single `signal` to all addEventListener calls, then `controller.abort()` to clean up all at once 2. Track listeners per module and clean up on teardown 3. Add cleanup/destroy methods to each module that removes its listeners
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
sleepy/odysseus#791
No description provided.