mirror of
https://github.com/denoland/deno.git
synced 2024-12-21 23:04:45 -05:00
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.
This commit is contained in:
parent
34dac6c6ef
commit
adf41edda1
2 changed files with 17 additions and 2 deletions
|
@ -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();
|
||||
|
|
|
@ -737,13 +737,14 @@ function innerInvokeEventListeners(
|
|||
}
|
||||
|
||||
let handlers = targetListeners[type];
|
||||
const handlersLength = handlers.length;
|
||||
|
||||
// Copy event listeners before iterating since the list can be modified during the iteration.
|
||||
if (handlers.length > 1) {
|
||||
if (handlersLength > 1) {
|
||||
handlers = ArrayPrototypeSlice(targetListeners[type]);
|
||||
}
|
||||
|
||||
for (let i = 0; i < handlers.length; i++) {
|
||||
for (let i = 0; i < handlersLength; i++) {
|
||||
const listener = handlers[i];
|
||||
|
||||
let capture, once, passive;
|
||||
|
|
Loading…
Reference in a new issue