Skip to content

Commit 32b7b4d

Browse files
rubennortefacebook-github-bot
authored andcommitted
[skip ci] Add regression test for EventTarget (facebook#48431)
Summary: Changelog: [internal] Adds a regression test to make sure we implement the correct spec-compliant behavior for a possible bug in ~~the Web spec~~ __Chrome__: whatwg/dom#1346 Edit: the bug is in the Chrome implementation, not in the spec. Differential Revision: D67758702
1 parent 4b6ce6e commit 32b7b4d

File tree

2 files changed

+67
-6
lines changed

2 files changed

+67
-6
lines changed

packages/react-native/src/private/webapis/dom/events/EventTarget.js

+19-6
Original file line numberDiff line numberDiff line change
@@ -127,16 +127,17 @@ export default class EventTarget {
127127
}
128128
}
129129

130-
listenerList.push({
130+
const listener: EventListenerRegistration = {
131131
callback,
132132
passive,
133133
once,
134134
removed: false,
135-
});
135+
};
136+
listenerList.push(listener);
136137

137138
if (signal != null) {
138139
signal.addEventListener('abort', () => {
139-
this.removeEventListener(processedType, callback, capture);
140+
this.#removeEventListenerRegistration(listener, listenerList);
140141
});
141142
}
142143
}
@@ -180,9 +181,6 @@ export default class EventTarget {
180181
return;
181182
}
182183
}
183-
184-
// NOTE: there is no step to remove the event listener from the signal, if
185-
// set, as per the spec. See https://github.com/whatwg/dom/issues/1346.
186184
}
187185

188186
dispatchEvent(event: Event): boolean {
@@ -344,6 +342,21 @@ export default class EventTarget {
344342
}
345343
}
346344

345+
#removeEventListenerRegistration(
346+
registration: EventListenerRegistration,
347+
listenerList: Array<EventListenerRegistration>,
348+
): void {
349+
for (let i = 0; i < listenerList.length; i++) {
350+
const listener = listenerList[i];
351+
352+
if (listener === registration) {
353+
listener.removed = true;
354+
listenerList.splice(i, 1);
355+
return;
356+
}
357+
}
358+
}
359+
347360
/**
348361
* This a "protected" method to be overridden by a subclass to allow event
349362
* propagation.

packages/react-native/src/private/webapis/dom/events/__tests__/EventTarget-itest.js

+48
Original file line numberDiff line numberDiff line change
@@ -926,5 +926,53 @@ describe('EventTarget', () => {
926926
expect(listenerThatWillBeRemoved).not.toHaveBeenCalled();
927927
});
928928
});
929+
930+
describe('re-attaching a previous listener with a pending signal', () => {
931+
// This is a regression test for https://github.com/whatwg/dom/issues/1346
932+
it('should NOT remove the new subscription when the signal for the old subscription is aborted', () => {
933+
const [node] = createEventTargetHierarchyWithDepth(1);
934+
935+
// Listener setup
936+
937+
resetListenerCallOrder();
938+
939+
const listener = createListener();
940+
941+
const abortController = new AbortController();
942+
943+
node.addEventListener('custom', listener, {
944+
signal: abortController.signal,
945+
});
946+
947+
// Dispatch
948+
949+
const event = new Event('custom');
950+
951+
node.dispatchEvent(event);
952+
953+
expect(listener).toHaveBeenCalledTimes(1);
954+
955+
node.removeEventListener('custom', listener);
956+
957+
node.dispatchEvent(event);
958+
959+
expect(listener).toHaveBeenCalledTimes(1);
960+
961+
// Added without a signal
962+
node.addEventListener('custom', listener);
963+
964+
node.dispatchEvent(event);
965+
966+
// Listener is called
967+
expect(listener).toHaveBeenCalledTimes(2);
968+
969+
abortController.abort();
970+
971+
node.dispatchEvent(event);
972+
973+
// Listener is called
974+
expect(listener).toHaveBeenCalledTimes(3);
975+
});
976+
});
929977
});
930978
});

0 commit comments

Comments
 (0)