From 8b768f144a3cad25d84a4e70b880e5aa1d5ff872 Mon Sep 17 00:00:00 2001 From: Tim Yung Date: Tue, 19 Sep 2023 08:04:17 -0700 Subject: [PATCH] RN: Switch EventEmitter to `Array.from(...)` (#39525) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/39525 Switches `EventEmitter#emit` to use `Array.from` instead of the spread operator. This should be functionally identical (with marginally less overhead of the runtime having to determine the type of `registrations`), but there seems to be [some unexpected Babel configurations in the community](https://github.com/facebook/react-native/issues/35577#issuecomment-1723218934) that causes this line of code to do the wrong things. Although we should independently root cause the Babel plugin configuration problems, this change might provide immediate relief and is also not any worse (e.g. in terms of code readability). This also adds a descriptive comment explaining the intention of the call to `Array.from`. Changelog: [Fixed][General] - Fix a potential bug in `EventEmitter` when used with certain Babel configurations that incorrectly polyfill the spread operator for iterables. Reviewed By: javache Differential Revision: D49389813 fbshipit-source-id: 7caf63734fc047496afe2f1ed6d918c22747258a --- .../react-native/Libraries/vendor/emitter/EventEmitter.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/react-native/Libraries/vendor/emitter/EventEmitter.js b/packages/react-native/Libraries/vendor/emitter/EventEmitter.js index e638309de87fc8..177cbbdf300935 100644 --- a/packages/react-native/Libraries/vendor/emitter/EventEmitter.js +++ b/packages/react-native/Libraries/vendor/emitter/EventEmitter.js @@ -109,7 +109,9 @@ export default class EventEmitter const registrations: ?Set> = this.#registry[eventType]; if (registrations != null) { - for (const registration of [...registrations]) { + // Copy `registrations` to take a snapshot when we invoke `emit`, in case + // registrations are added or removed when listeners are invoked. + for (const registration of Array.from(registrations)) { registration.listener.apply(registration.context, args); } }