From c4a866218e3b3b26b48542f196d67e9d4ba00c21 Mon Sep 17 00:00:00 2001 From: er-s-an <92594860+er-s-an@users.noreply.github.com> Date: Sun, 11 Oct 2026 17:10:45 +0800 Subject: [PATCH] Fix event listener snapshots before singular handlers --- src/events.test.ts | 36 ++++++++++++++++++++++++++++++++++++ src/events.ts | 3 ++- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/events.test.ts b/src/events.test.ts index 60e7c355f..1d335aac5 100644 --- a/src/events.test.ts +++ b/src/events.test.ts @@ -57,6 +57,42 @@ describe("EventDispatcher", () => { expect(calls).toEqual(["first", "second", "first"]); }); + it("defers listeners added by the singular handler until the next dispatch", () => { + const dispatcher = new EventDispatcher(); + const calls: string[] = []; + const listener = () => calls.push("listener"); + + dispatcher.setHandler("change", () => { + calls.push("handler"); + dispatcher.addEventListener("change", listener); + dispatcher.setHandler("change", undefined); + }); + + dispatcher.dispatch("change", { value: 1 }); + expect(calls).toEqual(["handler"]); + + dispatcher.dispatch("change", { value: 2 }); + expect(calls).toEqual(["handler", "listener"]); + }); + + it("keeps listeners removed by the singular handler in the current dispatch", () => { + const dispatcher = new EventDispatcher(); + const calls: string[] = []; + const listener = () => calls.push("listener"); + + dispatcher.addEventListener("change", listener); + dispatcher.setHandler("change", () => { + calls.push("handler"); + dispatcher.removeEventListener("change", listener); + }); + + dispatcher.dispatch("change", { value: 1 }); + expect(calls).toEqual(["handler", "listener"]); + + dispatcher.dispatch("change", { value: 2 }); + expect(calls).toEqual(["handler", "listener", "handler"]); + }); + it("warns only when one singular handler replaces another", () => { const dispatcher = new EventDispatcher(); const warn = spyOn(console, "warn").mockImplementation(() => {}); diff --git a/src/events.ts b/src/events.ts index aa2e8623a..fe089d8cc 100644 --- a/src/events.ts +++ b/src/events.ts @@ -72,8 +72,9 @@ export class EventDispatcher> { | EventSlot | undefined; if (!slot) return; + const listeners = [...slot.listeners]; slot.onHandler?.(params); - for (const l of [...slot.listeners]) l(params); + for (const l of listeners) l(params); } private _ensureEventSlot(