From f3e9e3ddc84940221a70c197efcb8aab12a75c3f Mon Sep 17 00:00:00 2001 From: David Walker Date: Sat, 22 Nov 2025 18:13:44 -0800 Subject: [PATCH] BUGFIX: Avoid re-entrency issues with EventEmitter (#2397) Subscribing or unsubscribing from within an event handler (possibly transitively) could cause issues or even infinite loops. This was initially fixed in #2257, which exhibited such problems. Currently no code is known to have this issue, but it could easily come up again in the future. --- src/utils/EventEmitter.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/utils/EventEmitter.ts b/src/utils/EventEmitter.ts index 96c3407a2..c6ac89ad5 100644 --- a/src/utils/EventEmitter.ts +++ b/src/utils/EventEmitter.ts @@ -11,7 +11,11 @@ export class EventEmitter { } emit(...args: [...T]): void { - for (const sub of this.subscribers) { + // It is necessary to make a copy of the subscribers list, because since + // the subscribers call arbitrary code, it can eventually call back in and + // subscribe or unsubscribe new listeners. We must only dispatch to the + // ones that were active at the time the event came in. + for (const sub of [...this.subscribers]) { sub(...args); } }