From 2a1f3c4cee9f3545121d6517d59793fbbfae2bd8 Mon Sep 17 00:00:00 2001 From: Tim Yung Date: Thu, 15 Jan 2026 11:09:42 -0800 Subject: [PATCH 1/2] RN: Minor Cleanup in `EventEmitter` Summary: Removes an obsolete `$FlowFixMe` and removes an unused type argument. Differential Revision: D90785969 --- packages/react-native/Libraries/vendor/emitter/EventEmitter.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/react-native/Libraries/vendor/emitter/EventEmitter.js b/packages/react-native/Libraries/vendor/emitter/EventEmitter.js index 05d668dee422..66bc3b61aa60 100644 --- a/packages/react-native/Libraries/vendor/emitter/EventEmitter.js +++ b/packages/react-native/Libraries/vendor/emitter/EventEmitter.js @@ -126,7 +126,6 @@ export default class EventEmitter< // 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)) { - // $FlowFixMe[incompatible-type] registration.listener.apply(registration.context, args); } } @@ -159,7 +158,6 @@ export default class EventEmitter< function allocate< TEventToArgsMap: Readonly>>, TEvent: $Keys, - TEventArgs: TEventToArgsMap[TEvent], >( registry: Registry, eventType: TEvent, From dcaf50bd138043cb5278c3d4731a3101ea7a8fc2 Mon Sep 17 00:00:00 2001 From: Tim Yung Date: Thu, 15 Jan 2026 11:09:42 -0800 Subject: [PATCH 2/2] RN: Export `EventEmitter` in Public API (#55190) Summary: Makes `EventEmitter` (and the related `IEventEmitter` interface type) available as part of React Native's Public API. This allows product logic using React Native to also leverage the same abstraction. Currently, code outside of React Native that wants to use `EventEmitter` must resort to deep imports (which is discouraged). Changelog: [General][Added] - Added `EventEmitter` to `react-native` exports. Differential Revision: D90786781 --- packages/react-native/ReactNativeApi.d.ts | 39 ++++++++++++++++++----- packages/react-native/index.js | 3 ++ packages/react-native/index.js.flow | 7 +++- 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/packages/react-native/ReactNativeApi.d.ts b/packages/react-native/ReactNativeApi.d.ts index be0534addca3..650c698682a9 100644 --- a/packages/react-native/ReactNativeApi.d.ts +++ b/packages/react-native/ReactNativeApi.d.ts @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<9504863966549f8efbbe4e13d7f74eaf>> + * @generated SignedSource<<532b4c9c3a1d7ea9cbfce8c8e8ff3d87>> * * This file was generated by scripts/js-api/build-types/index.js. */ @@ -1865,7 +1865,7 @@ declare namespace CodegenTypes { UnsafeMixed, DefaultTypes, WithDefault, - EventEmitter, + EventEmitter_2 as EventEmitter, } } declare type ColorListenerCallback = (value: ColorValue) => unknown @@ -2229,7 +2229,28 @@ declare type EventConfig = { platformConfig?: PlatformConfig useNativeDriver: boolean } -declare type EventEmitter = ( +declare class EventEmitter< + TEventToArgsMap extends Readonly< + Record> + > = Readonly>>, +> implements IEventEmitter +{ + addListener( + eventType: TEvent, + listener: (...args: TEventToArgsMap[TEvent]) => unknown, + context: unknown, + ): EventSubscription + constructor() + emit( + eventType: TEvent, + ...args: TEventToArgsMap[TEvent] + ): void + listenerCount(eventType: TEvent): number + removeAllListeners( + eventType?: null | TEvent | undefined, + ): void +} +declare type EventEmitter_2 = ( handler: ($$PARAM_0$$: T) => Promise | void, ) => EventSubscription declare type EventName = (() => string) | string @@ -5988,7 +6009,7 @@ export { Button, // ef82aed4 ButtonProps, // 3c081e75 Clipboard, // 41addb89 - CodegenTypes, // 030a94b8 + CodegenTypes, // adbc477c ColorSchemeName, // 31a4350e ColorValue, // 98989a8f ComponentProvider, // b5c60ddd @@ -5996,7 +6017,7 @@ export { CursorValue, // 26522595 DevMenu, // 21b8b7a9 DevSettings, // e55b91dc - DeviceEventEmitter, // 650e6394 + DeviceEventEmitter, // bdbdd014 DeviceInfo, // 521bfb71 DeviceInfoConstants, // 279e7858 DimensionValue, // b163a381 @@ -6016,6 +6037,7 @@ export { EmitterSubscription, // de50c359 EnterKeyHintTypeOptions, // 8314de78 ErrorUtils, // 38fb909e + EventEmitter, // 2a2ea995 EventSubscription, // b8d084aa ExtendedExceptionData, // 5a6ccf5a FilterFunction, // bf24c0e3 @@ -6029,6 +6051,7 @@ export { HostComponent, // 5e13ff5a HostInstance, // 489cbe7f I18nManager, // f9870e00 + IEventEmitter, // fbef6131 IOSKeyboardEvent, // e67bfe3a IgnorePattern, // ec6f6ece Image, // 957b3726 @@ -6074,7 +6097,7 @@ export { LayoutChangeEvent, // c674f902 LayoutConformanceProps, // 055f03b8 LayoutRectangle, // 6601b294 - Linking, // b5645d2b + Linking, // 9a6a174d ListRenderItem, // b5353fd8 ListRenderItemInfo, // e8595b03 ListViewToken, // 833d3481 @@ -6090,11 +6113,11 @@ export { ModalPropsIOS, // 4fbcedf6 ModeChangeEvent, // 16790307 MouseEvent, // 53ede3db - NativeAppEventEmitter, // e1340a0a + NativeAppEventEmitter, // 08d4c47d NativeColorValue, // d2094c29 NativeComponentRegistry, // 7fd99ba6 NativeDialogManagerAndroid, // 5be8497e - NativeEventEmitter, // d72906cc + NativeEventEmitter, // 27f97c1a NativeEventSubscription, // de3942e7 NativeMethods, // 03dc51c5 NativeMethodsMixin, // 4b061b7e diff --git a/packages/react-native/index.js b/packages/react-native/index.js index 2c47d5f2b5b7..719b64fb5be4 100644 --- a/packages/react-native/index.js +++ b/packages/react-native/index.js @@ -42,6 +42,9 @@ module.exports = { return require('./Libraries/Components/DrawerAndroid/DrawerLayoutAndroid') .default; }, + get EventEmitter() { + return require('./Libraries/vendor/emitter/EventEmitter').default; + }, get FlatList() { return require('./Libraries/Lists/FlatList').default; }, diff --git a/packages/react-native/index.js.flow b/packages/react-native/index.js.flow index ec723fa6b180..63d8dffd5847 100644 --- a/packages/react-native/index.js.flow +++ b/packages/react-native/index.js.flow @@ -320,7 +320,6 @@ export * as NativeComponentRegistry from './Libraries/NativeComponent/NativeComp export {default as NativeDialogManagerAndroid} from './Libraries/NativeModules/specs/NativeDialogManagerAndroid'; export type { - EventSubscription, EmitterSubscription, NativeEventSubscription, } from './Libraries/EventEmitter/NativeEventEmitter'; @@ -463,6 +462,12 @@ export type { PublicTextInstance, } from './Libraries/ReactPrivate/ReactNativePrivateInterface'; +export type { + EventSubscription, + IEventEmitter, +} from './Libraries/vendor/emitter/EventEmitter'; +export {default as EventEmitter} from './Libraries/vendor/emitter/EventEmitter'; + export { default as unstable_VirtualView, VirtualViewMode,