From adf41edda12a26a84cb8b4252404aae2a9e7ae03 Mon Sep 17 00:00:00 2001 From: Koen <41021050+vrugtehagel@users.noreply.github.com> Date: Mon, 5 Jun 2023 02:03:44 +0200 Subject: fix(ext/web): Copy EventTarget list before dispatch (#19360) Related issue: https://github.com/denoland/deno/issues/19358. This is a regression that seems to have been introduced in https://github.com/denoland/deno/pull/18905. It looks to have been a performance optimization. The issue is probably easiest described with some code: ```ts const target = new EventTarget(); const event = new Event("foo"); target.addEventListener("foo", () => { console.log('base'); target.addEventListener("foo", () => { console.log('nested'); }); }); target.dispatchEvent(event); ``` Essentially, the second event listener is being attached while the `foo` event is still being dispatched. It should then not fire that second event listener, but Deno currently does. --- cli/tests/unit/event_target_test.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'cli') diff --git a/cli/tests/unit/event_target_test.ts b/cli/tests/unit/event_target_test.ts index 49bd354aa..c7acab364 100644 --- a/cli/tests/unit/event_target_test.ts +++ b/cli/tests/unit/event_target_test.ts @@ -245,6 +245,20 @@ Deno.test(function eventTargetDispatchShouldSetTargetInListener() { assertEquals(called, true); }); +Deno.test(function eventTargetDispatchShouldFireCurrentListenersOnly() { + const target = new EventTarget(); + const event = new Event("foo"); + let callCount = 0; + target.addEventListener("foo", () => { + ++callCount; + target.addEventListener("foo", () => { + ++callCount; + }); + }); + target.dispatchEvent(event); + assertEquals(callCount, 1); +}); + Deno.test(function eventTargetAddEventListenerGlobalAbort() { return new Promise((resolve) => { const c = new AbortController(); -- cgit v1.2.3