react-native 0.84.0-nightly-20251118-d314e5f4e → 0.84.0-nightly-20251119-79b09ce9c

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/Libraries/Components/View/ViewPropTypes.js +10 -0
  2. package/Libraries/Core/ReactNativeVersion.js +1 -1
  3. package/Libraries/NativeComponent/BaseViewConfig.android.js +12 -0
  4. package/Libraries/Types/CoreEventTypes.js +31 -0
  5. package/React/Base/RCTVersion.m +1 -1
  6. package/React/CxxModule/RCTCxxUtils.mm +1 -1
  7. package/React/FBReactNativeSpec/react/renderer/components/FBReactNativeSpec/Props.h +14 -0
  8. package/ReactAndroid/api/ReactAndroid.api +2 -14
  9. package/ReactAndroid/gradle.properties +1 -1
  10. package/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +0 -7
  11. package/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerBuilder.kt +0 -10
  12. package/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java +58 -2
  13. package/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstance.kt +0 -18
  14. package/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java +0 -54
  15. package/ReactAndroid/src/main/java/com/facebook/react/modules/debug/FpsDebugFrameCallback.kt +3 -27
  16. package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.kt +1 -1
  17. package/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessCatalystInstance.kt +0 -9
  18. package/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactSurfaceView.kt +52 -0
  19. package/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java +10 -0
  20. package/ReactAndroid/src/main/java/com/facebook/react/uimanager/JSKeyDispatcher.kt +65 -0
  21. package/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementation.java +0 -8
  22. package/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java +0 -8
  23. package/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIViewOperationQueue.java +0 -16
  24. package/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/KeyDownEvent.kt +23 -0
  25. package/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/KeyEvent.kt +156 -0
  26. package/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/KeyUpEvent.kt +24 -0
  27. package/ReactAndroid/src/main/jni/react/tracing/PerformanceTracerCxxInterop.cpp +1 -1
  28. package/ReactCommon/cxxreact/ReactNativeVersion.h +1 -1
  29. package/ReactCommon/jsi/jsi/test/testlib.cpp +2 -2
  30. package/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.cpp +1 -1
  31. package/ReactCommon/react/runtime/ReactInstance.cpp +1 -1
  32. package/index.js.flow +3 -0
  33. package/package.json +9 -9
  34. package/sdks/hermes-engine/version.properties +1 -1
  35. package/types_generated/Libraries/Components/View/ViewPropTypes.d.ts +9 -3
  36. package/types_generated/Libraries/Types/CoreEventTypes.d.ts +29 -1
  37. package/types_generated/index.d.ts +2 -2
  38. package/ReactAndroid/src/main/java/com/facebook/react/bridge/NotThreadSafeBridgeIdleDebugListener.kt +0 -36
  39. package/ReactAndroid/src/main/java/com/facebook/react/modules/debug/DidJSUpdateUiDuringFrameDetector.kt +0 -157
  40. package/ReactAndroid/src/main/java/com/facebook/react/uimanager/debug/NotThreadSafeViewHierarchyUpdateDebugListener.kt +0 -30
@@ -16,6 +16,8 @@ import type {
16
16
  BlurEvent,
17
17
  FocusEvent,
18
18
  GestureResponderEvent,
19
+ KeyDownEvent,
20
+ KeyUpEvent,
19
21
  LayoutChangeEvent,
20
22
  LayoutRectangle,
21
23
  MouseEvent,
@@ -115,6 +117,13 @@ type FocusEventProps = $ReadOnly<{
115
117
  onFocusCapture?: ?(event: FocusEvent) => void,
116
118
  }>;
117
119
 
120
+ type KeyEventProps = $ReadOnly<{
121
+ onKeyDown?: ?(event: KeyDownEvent) => void,
122
+ onKeyDownCapture?: ?(event: KeyDownEvent) => void,
123
+ onKeyUp?: ?(event: KeyUpEvent) => void,
124
+ onKeyUpCapture?: ?(event: KeyUpEvent) => void,
125
+ }>;
126
+
118
127
  type TouchEventProps = $ReadOnly<{
119
128
  onTouchCancel?: ?(e: GestureResponderEvent) => void,
120
129
  onTouchCancelCapture?: ?(e: GestureResponderEvent) => void,
@@ -505,6 +514,7 @@ export type ViewProps = $ReadOnly<{
505
514
  ...MouseEventProps,
506
515
  ...PointerEventProps,
507
516
  ...FocusEventProps,
517
+ ...KeyEventProps,
508
518
  ...TouchEventProps,
509
519
  ...ViewPropsAndroid,
510
520
  ...ViewPropsIOS,
@@ -29,7 +29,7 @@ export default class ReactNativeVersion {
29
29
  static major: number = 0;
30
30
  static minor: number = 84;
31
31
  static patch: number = 0;
32
- static prerelease: string | null = 'nightly-20251118-d314e5f4e';
32
+ static prerelease: string | null = 'nightly-20251119-79b09ce9c';
33
33
 
34
34
  static getVersionString(): string {
35
35
  return `${this.major}.${this.minor}.${this.patch}${this.prerelease != null ? `-${this.prerelease}` : ''}`;
@@ -122,6 +122,18 @@ const bubblingEventTypes = {
122
122
  bubbled: 'onFocus',
123
123
  },
124
124
  },
125
+ topKeyDown: {
126
+ phasedRegistrationNames: {
127
+ captured: 'onKeyDownCapture',
128
+ bubbled: 'onKeyDown',
129
+ },
130
+ },
131
+ topKeyUp: {
132
+ phasedRegistrationNames: {
133
+ captured: 'onKeyUpCapture',
134
+ bubbled: 'onKeyUp',
135
+ },
136
+ },
125
137
  };
126
138
 
127
139
  const directEventTypes = {
@@ -322,3 +322,34 @@ export type MouseEvent = NativeSyntheticEvent<
322
322
  timestamp: number,
323
323
  }>,
324
324
  >;
325
+
326
+ export type KeyEvent = $ReadOnly<{
327
+ /**
328
+ * The actual key that was pressed. For example, F would be "f" or "F" depending on the shift key.
329
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
330
+ */
331
+ key: string,
332
+ /**
333
+ * The key code of the key that was pressed. For example, F would be "KeyF"
334
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code
335
+ */
336
+ code: string,
337
+ altKey: boolean,
338
+ ctrlKey: boolean,
339
+ metaKey: boolean,
340
+ shiftKey: boolean,
341
+ /**
342
+ * A boolean value that is true if the given key is being held down such that it is automatically repeating.
343
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/repeat
344
+ */
345
+ repeat?: boolean,
346
+ /**
347
+ * Returns a boolean value indicating if the event is fired within a composition session
348
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent/isComposing
349
+ */
350
+ isComposing?: boolean,
351
+ }>;
352
+
353
+ export type KeyUpEvent = NativeSyntheticEvent<KeyEvent>;
354
+
355
+ export type KeyDownEvent = NativeSyntheticEvent<KeyEvent>;
@@ -24,7 +24,7 @@ NSDictionary* RCTGetReactNativeVersion(void)
24
24
  RCTVersionMajor: @(0),
25
25
  RCTVersionMinor: @(84),
26
26
  RCTVersionPatch: @(0),
27
- RCTVersionPrerelease: @"nightly-20251118-d314e5f4e",
27
+ RCTVersionPrerelease: @"nightly-20251119-79b09ce9c",
28
28
  };
29
29
  });
30
30
  return __rnVersion;
@@ -68,7 +68,7 @@ NSError *tryAndReturnError(const std::function<void()> &func)
68
68
  return nil;
69
69
  } @catch (NSException *exception) {
70
70
  return RCTErrorWithNSException(exception);
71
- } @catch (id exception) {
71
+ } @catch (id) {
72
72
  // This will catch any other ObjC exception, but no C++ exceptions
73
73
  return RCTErrorWithMessage(@"non-std ObjC Exception");
74
74
  }
@@ -75,6 +75,8 @@ static inline std::string toString(const ActivityIndicatorViewSize &value) {
75
75
  switch (value) {
76
76
  case ActivityIndicatorViewSize::Small: return "small";
77
77
  case ActivityIndicatorViewSize::Large: return "large";
78
+ default:
79
+ abort();
78
80
  }
79
81
  }
80
82
 
@@ -120,6 +122,8 @@ static inline std::string toString(const AndroidDrawerLayoutKeyboardDismissMode
120
122
  switch (value) {
121
123
  case AndroidDrawerLayoutKeyboardDismissMode::None: return "none";
122
124
  case AndroidDrawerLayoutKeyboardDismissMode::OnDrag: return "on-drag";
125
+ default:
126
+ abort();
123
127
  }
124
128
  }
125
129
 
@@ -141,6 +145,8 @@ static inline std::string toString(const AndroidDrawerLayoutDrawerPosition &valu
141
145
  switch (value) {
142
146
  case AndroidDrawerLayoutDrawerPosition::Left: return "left";
143
147
  case AndroidDrawerLayoutDrawerPosition::Right: return "right";
148
+ default:
149
+ abort();
144
150
  }
145
151
  }
146
152
 
@@ -164,6 +170,8 @@ static inline std::string toString(const AndroidDrawerLayoutDrawerLockMode &valu
164
170
  case AndroidDrawerLayoutDrawerLockMode::Unlocked: return "unlocked";
165
171
  case AndroidDrawerLayoutDrawerLockMode::LockedClosed: return "locked-closed";
166
172
  case AndroidDrawerLayoutDrawerLockMode::LockedOpen: return "locked-open";
173
+ default:
174
+ abort();
167
175
  }
168
176
  }
169
177
 
@@ -231,6 +239,8 @@ static inline std::string toString(const AndroidSwipeRefreshLayoutSize &value) {
231
239
  switch (value) {
232
240
  case AndroidSwipeRefreshLayoutSize::Default: return "default";
233
241
  case AndroidSwipeRefreshLayoutSize::Large: return "large";
242
+ default:
243
+ abort();
234
244
  }
235
245
  }
236
246
 
@@ -398,6 +408,8 @@ static inline std::string toString(const ModalHostViewAnimationType &value) {
398
408
  case ModalHostViewAnimationType::None: return "none";
399
409
  case ModalHostViewAnimationType::Slide: return "slide";
400
410
  case ModalHostViewAnimationType::Fade: return "fade";
411
+ default:
412
+ abort();
401
413
  }
402
414
  }
403
415
 
@@ -423,6 +435,8 @@ static inline std::string toString(const ModalHostViewPresentationStyle &value)
423
435
  case ModalHostViewPresentationStyle::PageSheet: return "pageSheet";
424
436
  case ModalHostViewPresentationStyle::FormSheet: return "formSheet";
425
437
  case ModalHostViewPresentationStyle::OverFullScreen: return "overFullScreen";
438
+ default:
439
+ abort();
426
440
  }
427
441
  }
428
442
 
@@ -296,7 +296,6 @@ public final class com/facebook/react/ReactInstanceManagerBuilder {
296
296
  public final fun addPackages (Ljava/util/List;)Lcom/facebook/react/ReactInstanceManagerBuilder;
297
297
  public final fun build ()Lcom/facebook/react/ReactInstanceManager;
298
298
  public final fun setApplication (Landroid/app/Application;)Lcom/facebook/react/ReactInstanceManagerBuilder;
299
- public final fun setBridgeIdleDebugListener (Lcom/facebook/react/bridge/NotThreadSafeBridgeIdleDebugListener;)Lcom/facebook/react/ReactInstanceManagerBuilder;
300
299
  public final fun setBundleAssetName (Ljava/lang/String;)Lcom/facebook/react/ReactInstanceManagerBuilder;
301
300
  public final fun setChoreographerProvider (Lcom/facebook/react/internal/ChoreographerProvider;)Lcom/facebook/react/ReactInstanceManagerBuilder;
302
301
  public final fun setCurrentActivity (Landroid/app/Activity;)Lcom/facebook/react/ReactInstanceManagerBuilder;
@@ -381,6 +380,7 @@ public class com/facebook/react/ReactRootView : android/widget/FrameLayout, com/
381
380
  public fun <init> (Landroid/content/Context;Landroid/util/AttributeSet;)V
382
381
  public fun <init> (Landroid/content/Context;Landroid/util/AttributeSet;I)V
383
382
  protected fun dispatchDraw (Landroid/graphics/Canvas;)V
383
+ protected fun dispatchJSKeyEvent (Landroid/view/KeyEvent;)V
384
384
  protected fun dispatchJSPointerEvent (Landroid/view/MotionEvent;Z)V
385
385
  protected fun dispatchJSTouchEvent (Landroid/view/MotionEvent;)V
386
386
  public fun dispatchKeyEvent (Landroid/view/KeyEvent;)Z
@@ -583,7 +583,6 @@ public abstract interface class com/facebook/react/bridge/Callback {
583
583
  }
584
584
 
585
585
  public abstract interface class com/facebook/react/bridge/CatalystInstance : com/facebook/react/bridge/JSBundleLoaderDelegate, com/facebook/react/bridge/JSInstance, com/facebook/react/bridge/MemoryPressureListener {
586
- public abstract fun addBridgeIdleDebugListener (Lcom/facebook/react/bridge/NotThreadSafeBridgeIdleDebugListener;)V
587
586
  public abstract fun callFunction (Ljava/lang/String;Ljava/lang/String;Lcom/facebook/react/bridge/NativeArray;)V
588
587
  public abstract fun destroy ()V
589
588
  public abstract fun extendNativeModules (Lcom/facebook/react/bridge/NativeModuleRegistry;)V
@@ -605,7 +604,6 @@ public abstract interface class com/facebook/react/bridge/CatalystInstance : com
605
604
  public abstract fun invokeCallback (ILcom/facebook/react/bridge/NativeArrayInterface;)V
606
605
  public abstract fun isDestroyed ()Z
607
606
  public abstract fun registerSegment (ILjava/lang/String;)V
608
- public abstract fun removeBridgeIdleDebugListener (Lcom/facebook/react/bridge/NotThreadSafeBridgeIdleDebugListener;)V
609
607
  public abstract fun runJSBundle ()V
610
608
  public abstract fun setFabricUIManager (Lcom/facebook/react/bridge/UIManager;)V
611
609
  public abstract fun setGlobalVariable (Ljava/lang/String;Ljava/lang/String;)V
@@ -613,7 +611,6 @@ public abstract interface class com/facebook/react/bridge/CatalystInstance : com
613
611
  }
614
612
 
615
613
  public class com/facebook/react/bridge/CatalystInstanceImpl : com/facebook/react/bridge/CatalystInstance {
616
- public fun addBridgeIdleDebugListener (Lcom/facebook/react/bridge/NotThreadSafeBridgeIdleDebugListener;)V
617
614
  public fun callFunction (Lcom/facebook/react/bridge/CatalystInstanceImpl$PendingJSCall;)V
618
615
  public fun callFunction (Ljava/lang/String;Ljava/lang/String;Lcom/facebook/react/bridge/NativeArray;)V
619
616
  public fun destroy ()V
@@ -641,7 +638,6 @@ public class com/facebook/react/bridge/CatalystInstanceImpl : com/facebook/react
641
638
  public fun loadScriptFromFile (Ljava/lang/String;Ljava/lang/String;Z)V
642
639
  public fun loadSplitBundleFromFile (Ljava/lang/String;Ljava/lang/String;)V
643
640
  public fun registerSegment (ILjava/lang/String;)V
644
- public fun removeBridgeIdleDebugListener (Lcom/facebook/react/bridge/NotThreadSafeBridgeIdleDebugListener;)V
645
641
  public fun runJSBundle ()V
646
642
  public fun setFabricUIManager (Lcom/facebook/react/bridge/UIManager;)V
647
643
  public fun setGlobalVariable (Ljava/lang/String;Ljava/lang/String;)V
@@ -970,12 +966,6 @@ public final class com/facebook/react/bridge/NoSuchKeyException : java/lang/Runt
970
966
  public fun <init> (Ljava/lang/String;)V
971
967
  }
972
968
 
973
- public abstract interface class com/facebook/react/bridge/NotThreadSafeBridgeIdleDebugListener {
974
- public abstract fun onBridgeDestroyed ()V
975
- public abstract fun onTransitionToBridgeBusy ()V
976
- public abstract fun onTransitionToBridgeIdle ()V
977
- }
978
-
979
969
  public abstract interface class com/facebook/react/bridge/PerformanceCounter {
980
970
  public abstract fun getPerformanceCounters ()Ljava/util/Map;
981
971
  public abstract fun profileNextBatch ()V
@@ -3132,6 +3122,7 @@ public final class com/facebook/react/runtime/ReactSurfaceView : com/facebook/re
3132
3122
  public fun isViewAttachedToReactInstance ()Z
3133
3123
  public fun onChildEndedNativeGesture (Landroid/view/View;Landroid/view/MotionEvent;)V
3134
3124
  public fun onChildStartedNativeGesture (Landroid/view/View;Landroid/view/MotionEvent;)V
3125
+ public fun requestChildFocus (Landroid/view/View;Landroid/view/View;)V
3135
3126
  public fun requestDisallowInterceptTouchEvent (Z)V
3136
3127
  public fun setIsFabric (Z)V
3137
3128
  }
@@ -4328,7 +4319,6 @@ public class com/facebook/react/uimanager/UIImplementation {
4328
4319
  public fun setJSResponder (IZ)V
4329
4320
  public fun setLayoutAnimationEnabledExperimental (Z)V
4330
4321
  public fun setLayoutUpdateListener (Lcom/facebook/react/uimanager/UIImplementation$LayoutUpdateListener;)V
4331
- public fun setViewHierarchyUpdateDebugListener (Lcom/facebook/react/uimanager/debug/NotThreadSafeViewHierarchyUpdateDebugListener;)V
4332
4322
  public fun setViewLocalData (ILjava/lang/Object;)V
4333
4323
  public fun synchronouslyUpdateViewOnUIThread (ILcom/facebook/react/uimanager/ReactStylesDiffMap;)V
4334
4324
  public fun updateInsetsPadding (IIIII)V
@@ -4412,7 +4402,6 @@ public class com/facebook/react/uimanager/UIManagerModule : com/facebook/react/b
4412
4402
  public fun setChildren (ILcom/facebook/react/bridge/ReadableArray;)V
4413
4403
  public fun setJSResponder (IZ)V
4414
4404
  public fun setLayoutAnimationEnabledExperimental (Z)V
4415
- public fun setViewHierarchyUpdateDebugListener (Lcom/facebook/react/uimanager/debug/NotThreadSafeViewHierarchyUpdateDebugListener;)V
4416
4405
  public fun setViewLocalData (ILjava/lang/Object;)V
4417
4406
  public fun startSurface (Landroid/view/View;Ljava/lang/String;Lcom/facebook/react/bridge/WritableMap;II)I
4418
4407
  public fun stopSurface (I)V
@@ -4460,7 +4449,6 @@ public class com/facebook/react/uimanager/UIViewOperationQueue {
4460
4449
  public fun isEmpty ()Z
4461
4450
  public fun prependUIBlock (Lcom/facebook/react/uimanager/UIBlock;)V
4462
4451
  public fun profileNextBatch ()V
4463
- public fun setViewHierarchyUpdateDebugListener (Lcom/facebook/react/uimanager/debug/NotThreadSafeViewHierarchyUpdateDebugListener;)V
4464
4452
  }
4465
4453
 
4466
4454
  public abstract interface class com/facebook/react/uimanager/UIViewOperationQueue$UIOperation {
@@ -1,4 +1,4 @@
1
- VERSION_NAME=0.84.0-nightly-20251118-d314e5f4e
1
+ VERSION_NAME=0.84.0-nightly-20251119-79b09ce9c
2
2
  react.internal.publishingGroup=com.facebook.react
3
3
  react.internal.hermesPublishingGroup=com.facebook.hermes
4
4
 
@@ -57,7 +57,6 @@ import com.facebook.react.bridge.JSExceptionHandler;
57
57
  import com.facebook.react.bridge.JavaScriptExecutor;
58
58
  import com.facebook.react.bridge.JavaScriptExecutorFactory;
59
59
  import com.facebook.react.bridge.NativeModuleRegistry;
60
- import com.facebook.react.bridge.NotThreadSafeBridgeIdleDebugListener;
61
60
  import com.facebook.react.bridge.ReactApplicationContext;
62
61
  import com.facebook.react.bridge.ReactContext;
63
62
  import com.facebook.react.bridge.ReactCxxErrorHandler;
@@ -183,7 +182,6 @@ public class ReactInstanceManager {
183
182
  private final boolean mUseDeveloperSupport;
184
183
  private final boolean mRequireActivity;
185
184
  private final boolean mKeepActivity;
186
- private final @Nullable NotThreadSafeBridgeIdleDebugListener mBridgeIdleDebugListener;
187
185
  private final Object mReactContextLock = new Object();
188
186
  private @Nullable volatile ReactContext mCurrentReactContext;
189
187
  private final Context mApplicationContext;
@@ -246,7 +244,6 @@ public class ReactInstanceManager {
246
244
  DevSupportManagerFactory devSupportManagerFactory,
247
245
  boolean requireActivity,
248
246
  boolean keepActivity,
249
- @Nullable NotThreadSafeBridgeIdleDebugListener bridgeIdleDebugListener,
250
247
  LifecycleState initialLifecycleState,
251
248
  JSExceptionHandler jSExceptionHandler,
252
249
  @Nullable RedBoxHandler redBoxHandler,
@@ -292,7 +289,6 @@ public class ReactInstanceManager {
292
289
  devLoadingViewManager,
293
290
  pausedInDebuggerOverlayManager);
294
291
  Systrace.endSection(TRACE_TAG_REACT);
295
- mBridgeIdleDebugListener = bridgeIdleDebugListener;
296
292
  mLifecycleState = initialLifecycleState;
297
293
  mMemoryPressureRouter = new MemoryPressureRouter(applicationContext);
298
294
  mJSExceptionHandler = jSExceptionHandler;
@@ -1517,9 +1513,6 @@ public class ReactInstanceManager {
1517
1513
  catalystInstance.setFabricUIManager(uiManager);
1518
1514
  }
1519
1515
  }
1520
- if (mBridgeIdleDebugListener != null) {
1521
- catalystInstance.addBridgeIdleDebugListener(mBridgeIdleDebugListener);
1522
- }
1523
1516
  if (BuildConfig.ENABLE_PERFETTO || Systrace.isTracing(TRACE_TAG_REACT)) {
1524
1517
  catalystInstance.setGlobalVariable("__RCTProfileIsProfiling", "true");
1525
1518
  }
@@ -19,7 +19,6 @@ import com.facebook.react.ReactInstanceManager.initializeSoLoaderIfNecessary
19
19
  import com.facebook.react.bridge.JSBundleLoader
20
20
  import com.facebook.react.bridge.JSExceptionHandler
21
21
  import com.facebook.react.bridge.JavaScriptExecutorFactory
22
- import com.facebook.react.bridge.NotThreadSafeBridgeIdleDebugListener
23
22
  import com.facebook.react.bridge.UIManagerProvider
24
23
  import com.facebook.react.common.LifecycleState
25
24
  import com.facebook.react.common.SurfaceDelegateFactory
@@ -49,7 +48,6 @@ public class ReactInstanceManagerBuilder {
49
48
  private var jsBundleAssetUrl: String? = null
50
49
  private var jsBundleLoader: JSBundleLoader? = null
51
50
  private var jsMainModulePath: String? = null
52
- private var bridgeIdleDebugListener: NotThreadSafeBridgeIdleDebugListener? = null
53
51
  private var application: Application? = null
54
52
  private var useDeveloperSupport = false
55
53
  private var devSupportManagerFactory: DevSupportManagerFactory? = null
@@ -145,13 +143,6 @@ public class ReactInstanceManagerBuilder {
145
143
  return this
146
144
  }
147
145
 
148
- public fun setBridgeIdleDebugListener(
149
- bridgeIdleDebugListener: NotThreadSafeBridgeIdleDebugListener
150
- ): ReactInstanceManagerBuilder {
151
- this.bridgeIdleDebugListener = bridgeIdleDebugListener
152
- return this
153
- }
154
-
155
146
  /** Required. This must be your `Application` instance. */
156
147
  public fun setApplication(application: Application): ReactInstanceManagerBuilder {
157
148
  this.application = application
@@ -359,7 +350,6 @@ public class ReactInstanceManagerBuilder {
359
350
  devSupportManagerFactory ?: DefaultDevSupportManagerFactory(),
360
351
  requireActivity,
361
352
  keepActivity,
362
- bridgeIdleDebugListener,
363
353
  checkNotNull(initialLifecycleState) { "Initial lifecycle state was not set" },
364
354
  jsExceptionHandler,
365
355
  redBoxHandler,
@@ -57,6 +57,7 @@ import com.facebook.react.modules.appregistry.AppRegistry;
57
57
  import com.facebook.react.modules.deviceinfo.DeviceInfoModule;
58
58
  import com.facebook.react.uimanager.DisplayMetricsHolder;
59
59
  import com.facebook.react.uimanager.IllegalViewOperationException;
60
+ import com.facebook.react.uimanager.JSKeyDispatcher;
60
61
  import com.facebook.react.uimanager.JSPointerDispatcher;
61
62
  import com.facebook.react.uimanager.JSTouchDispatcher;
62
63
  import com.facebook.react.uimanager.PixelUtil;
@@ -105,6 +106,7 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
105
106
  private boolean mShouldLogContentAppeared;
106
107
  private @Nullable JSTouchDispatcher mJSTouchDispatcher;
107
108
  private @Nullable JSPointerDispatcher mJSPointerDispatcher;
109
+ private @Nullable JSKeyDispatcher mJSKeyDispatcher;
108
110
  private final ReactAndroidHWInputDeviceHelper mAndroidHWInputDeviceHelper =
109
111
  new ReactAndroidHWInputDeviceHelper();
110
112
  private boolean mWasMeasured = false;
@@ -333,10 +335,17 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
333
335
  FLog.w(TAG, "Unable to handle key event as the catalyst instance has not been attached");
334
336
  return super.dispatchKeyEvent(ev);
335
337
  }
338
+
336
339
  ReactContext context = getCurrentReactContext();
337
- if (context != null) {
338
- mAndroidHWInputDeviceHelper.handleKeyEvent(ev, context);
340
+ if (context == null) {
341
+ return super.dispatchKeyEvent(ev);
339
342
  }
343
+
344
+ mAndroidHWInputDeviceHelper.handleKeyEvent(ev, context);
345
+
346
+ // Dispatch during the capture phase before children handle the event as the focus could shift
347
+ dispatchJSKeyEvent(ev);
348
+
340
349
  return super.dispatchKeyEvent(ev);
341
350
  }
342
351
 
@@ -352,6 +361,17 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
352
361
  ReactContext context = getCurrentReactContext();
353
362
  if (context != null) {
354
363
  mAndroidHWInputDeviceHelper.clearFocus(context);
364
+
365
+ if (mJSKeyDispatcher != null && ReactNativeFeatureFlags.enableKeyEvents()) {
366
+ if (gainFocus) {
367
+ @Nullable View focusedChild = getFocusedChild();
368
+ if (focusedChild != null) {
369
+ mJSKeyDispatcher.setFocusedView(focusedChild.getId());
370
+ }
371
+ } else {
372
+ mJSKeyDispatcher.clearFocus();
373
+ }
374
+ }
355
375
  }
356
376
  super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
357
377
  }
@@ -369,6 +389,10 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
369
389
  ReactContext context = getCurrentReactContext();
370
390
  if (context != null) {
371
391
  mAndroidHWInputDeviceHelper.onFocusChanged(focused, context);
392
+
393
+ if (mJSKeyDispatcher != null && ReactNativeFeatureFlags.enableKeyEvents()) {
394
+ mJSKeyDispatcher.setFocusedView(focused.getId());
395
+ }
372
396
  }
373
397
  super.requestChildFocus(child, focused);
374
398
  }
@@ -410,6 +434,31 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
410
434
  }
411
435
  }
412
436
 
437
+ protected void dispatchJSKeyEvent(KeyEvent ev) {
438
+ if (!ReactNativeFeatureFlags.enableKeyEvents()) {
439
+ // Silently return early if key events are disabled
440
+ return;
441
+ }
442
+ if (!hasActiveReactContext() || !isViewAttachedToReactInstance()) {
443
+ FLog.w(
444
+ TAG, "Unable to dispatch key event to JS as the catalyst instance has not been attached");
445
+ return;
446
+ }
447
+ if (mJSKeyDispatcher == null) {
448
+ FLog.w(TAG, "Unable to dispatch key event to JS before the dispatcher is available");
449
+ return;
450
+ }
451
+ ReactContext context = getCurrentReactContext();
452
+ if (context != null) {
453
+ EventDispatcher eventDispatcher =
454
+ UIManagerHelper.getEventDispatcher(context, getUIManagerType());
455
+ int surfaceId = UIManagerHelper.getSurfaceId(context);
456
+ if (eventDispatcher != null) {
457
+ mJSKeyDispatcher.handleKeyEvent(ev, eventDispatcher, surfaceId);
458
+ }
459
+ }
460
+ }
461
+
413
462
  @Override
414
463
  public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
415
464
  // Override in order to still receive events to onInterceptTouchEvent even when some other
@@ -666,6 +715,10 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
666
715
  mJSPointerDispatcher = new JSPointerDispatcher(this);
667
716
  }
668
717
 
718
+ if (ReactNativeFeatureFlags.enableKeyEvents()) {
719
+ mJSKeyDispatcher = new JSKeyDispatcher();
720
+ }
721
+
669
722
  if (mRootViewEventListener != null) {
670
723
  mRootViewEventListener.onAttachedToReactInstance(this);
671
724
  }
@@ -744,6 +797,9 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
744
797
  if (ReactFeatureFlags.dispatchPointerEvents) {
745
798
  mJSPointerDispatcher = new JSPointerDispatcher(this);
746
799
  }
800
+ if (ReactNativeFeatureFlags.enableKeyEvents()) {
801
+ mJSKeyDispatcher = new JSKeyDispatcher();
802
+ }
747
803
  }
748
804
 
749
805
  @VisibleForTesting
@@ -75,24 +75,6 @@ public interface CatalystInstance : MemoryPressureListener, JSInstance, JSBundle
75
75
  */
76
76
  public fun extendNativeModules(modules: NativeModuleRegistry)
77
77
 
78
- /**
79
- * Adds a idle listener for this Catalyst instance. The listener will receive notifications
80
- * whenever the bridge transitions from idle to busy and vice-versa, where the busy state is
81
- * defined as there being some non-zero number of calls to JS that haven't resolved via a
82
- * onBatchCompleted call. The listener should be purely passive and not affect application logic.
83
- */
84
- public fun addBridgeIdleDebugListener(
85
- @Suppress("DEPRECATION") listener: NotThreadSafeBridgeIdleDebugListener
86
- )
87
-
88
- /**
89
- * Removes a NotThreadSafeBridgeIdleDebugListener previously added with
90
- * [addBridgeIdleDebugListener]
91
- */
92
- public fun removeBridgeIdleDebugListener(
93
- @Suppress("DEPRECATION") listener: NotThreadSafeBridgeIdleDebugListener
94
- )
95
-
96
78
  /** This method registers the file path of an additional JS segment by its ID. */
97
79
  public fun registerSegment(segmentId: Int, path: String)
98
80
 
@@ -39,7 +39,6 @@ import com.facebook.systrace.TraceListener;
39
39
  import java.lang.ref.WeakReference;
40
40
  import java.util.ArrayList;
41
41
  import java.util.Collection;
42
- import java.util.concurrent.CopyOnWriteArrayList;
43
42
  import java.util.concurrent.atomic.AtomicInteger;
44
43
 
45
44
  /**
@@ -88,7 +87,6 @@ public class CatalystInstanceImpl implements CatalystInstance {
88
87
 
89
88
  // Access from any thread
90
89
  private final ReactQueueConfigurationImpl mReactQueueConfiguration;
91
- private final CopyOnWriteArrayList<NotThreadSafeBridgeIdleDebugListener> mBridgeIdleListeners;
92
90
  private final AtomicInteger mPendingJSCalls = new AtomicInteger(0);
93
91
  private final String mJsPendingCallsTitleForTrace =
94
92
  "pending_js_calls_instance" + sNextInstanceIdForTrace.getAndIncrement();
@@ -138,7 +136,6 @@ public class CatalystInstanceImpl implements CatalystInstance {
138
136
  mReactQueueConfiguration =
139
137
  ReactQueueConfigurationImpl.create(
140
138
  reactQueueConfigurationSpec, new NativeExceptionHandler());
141
- mBridgeIdleListeners = new CopyOnWriteArrayList<>();
142
139
  mNativeModuleRegistry = nativeModuleRegistry;
143
140
  mJSModuleRegistry = new JavaScriptModuleRegistry();
144
141
  mJSBundleLoader = jsBundleLoader;
@@ -372,14 +369,6 @@ public class CatalystInstanceImpl implements CatalystInstance {
372
369
  mFabricUIManager.invalidate();
373
370
  }
374
371
  boolean wasIdle = (mPendingJSCalls.getAndSet(0) == 0);
375
- if (!mBridgeIdleListeners.isEmpty()) {
376
- for (NotThreadSafeBridgeIdleDebugListener listener : mBridgeIdleListeners) {
377
- if (!wasIdle) {
378
- listener.onTransitionToBridgeIdle();
379
- }
380
- listener.onBridgeDestroyed();
381
- }
382
- }
383
372
 
384
373
  getReactQueueConfiguration()
385
374
  .getJSQueueThread()
@@ -521,30 +510,6 @@ public class CatalystInstanceImpl implements CatalystInstance {
521
510
  jniHandleMemoryPressure(level);
522
511
  }
523
512
 
524
- /**
525
- * Adds a idle listener for this Catalyst instance. The listener will receive notifications
526
- * whenever the bridge transitions from idle to busy and vice-versa, where the busy state is
527
- * defined as there being some non-zero number of calls to JS that haven't resolved via a
528
- * onBatchComplete call. The listener should be purely passive and not affect application logic.
529
- *
530
- * @noinspection deprecation
531
- */
532
- @Override
533
- public void addBridgeIdleDebugListener(NotThreadSafeBridgeIdleDebugListener listener) {
534
- mBridgeIdleListeners.add(listener);
535
- }
536
-
537
- /**
538
- * Removes a NotThreadSafeBridgeIdleDebugListener previously added with {@link
539
- * #addBridgeIdleDebugListener}
540
- *
541
- * @noinspection deprecation
542
- */
543
- @Override
544
- public void removeBridgeIdleDebugListener(NotThreadSafeBridgeIdleDebugListener listener) {
545
- mBridgeIdleListeners.remove(listener);
546
- }
547
-
548
513
  @Override
549
514
  public native void setGlobalVariable(String propName, String jsonValue);
550
515
 
@@ -561,16 +526,7 @@ public class CatalystInstanceImpl implements CatalystInstance {
561
526
 
562
527
  private void incrementPendingJSCalls() {
563
528
  int oldPendingCalls = mPendingJSCalls.getAndIncrement();
564
- boolean wasIdle = oldPendingCalls == 0;
565
529
  Systrace.traceCounter(TRACE_TAG_REACT, mJsPendingCallsTitleForTrace, oldPendingCalls + 1);
566
- if (wasIdle && !mBridgeIdleListeners.isEmpty()) {
567
- mNativeModulesQueueThread.runOnQueue(
568
- () -> {
569
- for (NotThreadSafeBridgeIdleDebugListener listener : mBridgeIdleListeners) {
570
- listener.onTransitionToBridgeBusy();
571
- }
572
- });
573
- }
574
530
  }
575
531
 
576
532
  @Override
@@ -592,17 +548,7 @@ public class CatalystInstanceImpl implements CatalystInstance {
592
548
  int newPendingCalls = mPendingJSCalls.decrementAndGet();
593
549
  // TODO(9604406): handle case of web workers injecting messages to main thread
594
550
  // Assertions.assertCondition(newPendingCalls >= 0);
595
- boolean isNowIdle = newPendingCalls == 0;
596
551
  Systrace.traceCounter(TRACE_TAG_REACT, mJsPendingCallsTitleForTrace, newPendingCalls);
597
-
598
- if (isNowIdle && !mBridgeIdleListeners.isEmpty()) {
599
- mNativeModulesQueueThread.runOnQueue(
600
- () -> {
601
- for (NotThreadSafeBridgeIdleDebugListener listener : mBridgeIdleListeners) {
602
- listener.onTransitionToBridgeIdle();
603
- }
604
- });
605
- }
606
552
  }
607
553
 
608
554
  private void onNativeException(Exception e) {
@@ -26,8 +26,6 @@ internal class FpsDebugFrameCallback(private val reactContext: ReactContext) :
26
26
  Choreographer.FrameCallback {
27
27
 
28
28
  private var choreographer: Choreographer? = null
29
- private val didJSUpdateUiDuringFrameDetector: DidJSUpdateUiDuringFrameDetector =
30
- DidJSUpdateUiDuringFrameDetector()
31
29
  private var firstFrameTime: Long = -1
32
30
  private var lastFrameTime: Long = -1
33
31
  private var numFrameCallbacks = 0
@@ -40,11 +38,7 @@ internal class FpsDebugFrameCallback(private val reactContext: ReactContext) :
40
38
  if (firstFrameTime == -1L) {
41
39
  firstFrameTime = l
42
40
  }
43
- val lastFrameStartTime = lastFrameTime
44
41
  lastFrameTime = l
45
- if (didJSUpdateUiDuringFrameDetector.getDidJSHitFrameAndCleanup(lastFrameStartTime, l)) {
46
- numFrameCallbacksWithBatchDispatches++
47
- }
48
42
  numFrameCallbacks++
49
43
  val expectedNumFrames = expectedNumFrames
50
44
  val framesDropped = expectedNumFrames - expectedNumFramesPrev - 1
@@ -61,17 +55,9 @@ internal class FpsDebugFrameCallback(private val reactContext: ReactContext) :
61
55
  // removeBridgeIdleDebugListener for Bridgeless
62
56
  @Suppress("DEPRECATION")
63
57
  if (!ReactBuildConfig.UNSTABLE_ENABLE_MINIFY_LEGACY_ARCHITECTURE) {
64
- val uiManagerModule =
65
- reactContext.getNativeModule(com.facebook.react.uimanager.UIManagerModule::class.java)
66
- if (!reactContext.isBridgeless) {
67
- reactContext.catalystInstance.addBridgeIdleDebugListener(didJSUpdateUiDuringFrameDetector)
68
- isRunningOnFabric = false
69
- } else {
70
- // T172641976 Consider either implementing a mechanism similar to addBridgeIdleDebugListener
71
- // for Fabric or point users to use RNDT.
72
- isRunningOnFabric = true
73
- }
74
- uiManagerModule?.setViewHierarchyUpdateDebugListener(didJSUpdateUiDuringFrameDetector)
58
+ // T172641976 Consider either implementing a mechanism similar to addBridgeIdleDebugListener
59
+ // for Fabric or point users to use RNDT.
60
+ isRunningOnFabric = true
75
61
  }
76
62
  this.targetFps = targetFps
77
63
  UiThreadUtil.runOnUiThread {
@@ -82,16 +68,6 @@ internal class FpsDebugFrameCallback(private val reactContext: ReactContext) :
82
68
 
83
69
  fun stop() {
84
70
  @Suppress("DEPRECATION")
85
- if (!ReactBuildConfig.UNSTABLE_ENABLE_MINIFY_LEGACY_ARCHITECTURE) {
86
- val uiManagerModule =
87
- reactContext.getNativeModule(com.facebook.react.uimanager.UIManagerModule::class.java)
88
- if (!reactContext.isBridgeless) {
89
- reactContext.catalystInstance.removeBridgeIdleDebugListener(
90
- didJSUpdateUiDuringFrameDetector
91
- )
92
- }
93
- uiManagerModule?.setViewHierarchyUpdateDebugListener(null)
94
- }
95
71
  UiThreadUtil.runOnUiThread {
96
72
  choreographer = Choreographer.getInstance()
97
73
  choreographer?.removeFrameCallback(this)
@@ -15,6 +15,6 @@ public object ReactNativeVersion {
15
15
  "major" to 0,
16
16
  "minor" to 84,
17
17
  "patch" to 0,
18
- "prerelease" to "nightly-20251118-d314e5f4e"
18
+ "prerelease" to "nightly-20251119-79b09ce9c"
19
19
  )
20
20
  }