Summary:
Fixes https://github.com/facebook/react-native/issues/54123
In RN 0.80, `betterHitTest:withEvent:` in `RCTScrollViewComponentView` was added, which returns `self` (the `RCTScrollViewComponentView` wrapper view) when a touch point falls inside the scroll view's bounds. This causes touches in the contentInset area — where no content is rendered — to be absorbed by the wrapper rather than forwarded to the underlying UIScrollView, making scroll gestures in that region completely non-functional.
The fix returns `_scrollView` instead of `self`, so hit-tested touches are correctly attributed to the `UIScrollView` and scrolling works throughout the full bounds, including the inset area.
## Changelog:
[IOS] [FIXED] - Fix ScrollView touch events ignored in contentInset area on Fabric
Pull Request resolved: https://github.com/facebook/react-native/pull/56747
Test Plan:
Couldn't use the snack-repro from https://github.com/facebook/react-native/issues/54123 since this requires a native change. But using the `ScrollViewSimpleExample` from the RNTester, and removing a lot of the items demonstrates the behaviour change.
The two videos show attempted dragging from the region below the ScrollView content.
### Before: Dragging in the inset area does nothing — scroll view does not respond
https://github.com/user-attachments/assets/55468ca8-78a7-4034-9e34-0191d55f7da1
### After: Dragging in the inset area scrolls the content correctly
https://github.com/user-attachments/assets/d1f10729-9b41-4a55-8738-16faf27031d7
Reviewed By: christophpurrer
Differential Revision: D104644045
Pulled By: javache
fbshipit-source-id: c8b856ff133705f2197ce9938d5ebafae46d0c17
Summary:
Syncs the in-package AppState API documentation with the Android AppState clarification added in facebook/react-native-website#5079.
Android AppState `background` was already documented as including another `Activity`. This clarifies that temporary system activities, such as autofill credential pickers, are included too.
## Changelog:
[GENERAL] [CHANGED] - Clarify Android AppState background API documentation.
Pull Request resolved: https://github.com/facebook/react-native/pull/56779
Test Plan:
Documentation-only change.
Verified with:
- `git diff --check`
- `prettier --check packages/react-native/Libraries/AppState/AppState.js packages/react-native/Libraries/AppState/AppState.d.ts`
Reviewed By: cortinico
Differential Revision: D104810583
Pulled By: huntie
fbshipit-source-id: 17d2ec312c65c91b8086bd382f733f3cceb4da8a
Summary:
The `onMouseLeave` handler in `Pressability` stores the delayed `onHoverOut` timeout in `_hoverInDelayTimeout` instead of `_hoverOutDelayTimeout`. This is a copy-paste error from the `onMouseEnter` handler above it.
The Pointer Events path (`onPointerLeave`, line 593) correctly uses `_hoverOutDelayTimeout`. The Mouse Events path (`onMouseLeave`, line 645) incorrectly uses `_hoverInDelayTimeout`.
This causes:
- `_cancelHoverOutDelayTimeout()` to not cancel the pending `onHoverOut` callback
- `_cancelHoverInDelayTimeout()` to incorrectly cancel `onHoverOut` instead of `onHoverIn`
- A pending `onHoverIn` timeout to be silently overwritten if it exists
Affects non-mobile platforms (web, desktop) when `delayHoverOut > 0`.
## Changelog:
[General] [Fixed] - Fix hover out timeout stored in wrong variable in Pressability
Pull Request resolved: https://github.com/facebook/react-native/pull/56328
Test Plan:
- All 37 existing Pressability tests pass: `yarn jest packages/react-native/Libraries/Pressability/__tests__/Pressability-test.js`
- Prettier and ESLint checks pass.
- Verified by code inspection: the Pointer Events path (line 593) correctly uses `_hoverOutDelayTimeout`, the Mouse Events path (line 645) now matches.
Reviewed By: christophpurrer
Differential Revision: D104657310
Pulled By: javache
fbshipit-source-id: 66b0b353168102a5e8664e0c9b558cb6a1d7503c
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56720
Introduces a generic TextEffect system that lets apps register custom text
span effects without modifying React Native core. This can serve for use cases like `react-native-live-markdown`, or product specific effects.
The implementation is pretty dumb right now. It's just a marker, where we can add some JSON serializable data, to be serialized during Spannable creation on JS side MapBuffer.
**JS API:**
```js
import requireNativeTextEffect from 'react-native/Libraries/Text/requireNativeTextEffect';
const Spoiler = requireNativeTextEffect<{}>('RCTSpoiler');
<Text>Normal <Spoiler>hidden text</Spoiler></Text>
```
**Android registration** (via FabricUIManager):
```kotlin
val fabricUIManager = UIManagerHelper.getUIManager(
context, UIManagerType.FABRIC) as? FabricUIManager
fabricUIManager?.textEffectRegistry?.register("RCTSpoiler") { props ->
MyCustomSpan()
}
```
Changelog: [Internal]
Reviewed By: javache
Differential Revision: D98812222
fbshipit-source-id: 7000a0452b7592cdc2b26e7eaa37ec95736efce4
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56775
babel/plugin-transform-modules-systemjs versions >= 7.12.0 and <= 7.29.3 are affected by CVE-2026-44728 (GHSA-fv7c-fp4j-7gwp), a HIGH severity vulnerability. The react-native repo resolves this package at 7.25.9 via babel/preset-env. This adds a Yarn resolution to force the package to ^7.29.4, the first patched version.
#Changelog: [Internal]
[General] - Bump `babel/plugin-transform-modules-systemjs` to 7.29.4
Reviewed By: robhogan
Differential Revision: D104687110
fbshipit-source-id: ce95afcae024d6ea2a83eae9067d3ab3fd3baa0c
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56752
Delete the old script files that were renamed in prior commits:
- scripts/releases/use-hermes-nightly.js (renamed to use-hermes-prebuilt.js)
- scripts/try-set-nightly-hermes-compiler.js (renamed to try-set-hermes-compiler-prebuilt.js)
These deletions were accidentally omitted from their respective rename commits.
## Changelog:
[Internal] -
Reviewed By: cortinico
Differential Revision: D104650744
fbshipit-source-id: a0f1e3279622f792a0e79d011d942539e5168eaf
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56751
The hermes-utils test used an old-style Hermes git tag
('hermes-2022-04-28-RNv0.69.0-...') as its fixture. Hermes now uses semver
version strings (e.g. '250829098.0.13'). Update the fixture to match the
current format so the test better represents real usage.
## Changelog:
[Internal] -
Reviewed By: cortinico
Differential Revision: D104649627
fbshipit-source-id: 00562fd7d0325acde6f4ccf906e4c34e3c705375
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56757
Update comments that still say 'Hermes V1' as if it is an opt-in feature.
Since Hermes (formerly called Hermes V1) is now the only supported engine:
- hermes-engine.podspec: drop 'when using Hermes V1' from hermesc note
- PathUtils.kt: rewrite the hermesc path comment to drop the 'opted in to Hermes V1' phrasing
- hermes-engine/build.gradle.kts: 'Hermes V1 by default...' -> 'Hermes by default...'
## Changelog:
[Internal] -
Reviewed By: cortinico
Differential Revision: D104649634
fbshipit-source-id: 9b0a05ed013c7ba908c7abe467d5e3c1c3c2f26c
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56756
The use-hermes-nightly boolean input of prebuild-ios-core.yml was misleadingly named.
It controls whether to use the latest prebuilt Hermes from npm's latest-v1 dist-tag
(not a 'nightly' build). Rename:
- prebuild-ios-core.yml input: use-hermes-nightly -> use-hermes-prebuilt
- Update description of the input
- Update comment to move the TODO note inline
- Update callers in nightly.yml and test-all.yml
## Changelog:
[Internal] -
Reviewed By: cortinico
Differential Revision: D104649628
fbshipit-source-id: 71c75b07caebfe5e7d03e80d47cefba883843c9a
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56758
Rename scripts/try-set-nightly-hermes-compiler.js to
scripts/try-set-hermes-compiler-prebuilt.js. The script sets the hermes-compiler
version to the latest prebuilt (latest-v1 on npm), not a nightly build.
Update the preinstall script reference in the root package.json.
## Changelog:
[Internal] -
Reviewed By: cortinico
Differential Revision: D104649635
fbshipit-source-id: 8375d0518ea8c9ca99a59fd65366210eeea91e50
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56753
The functions getLatestHermesNightlyVersion() and updateHermesVersionsToNightly() were
misleadingly named: they actually fetch from the 'latest-v1' npm dist-tag, not a 'nightly'
tag. Rename them to better reflect what they do:
- getLatestHermesNightlyVersion -> getLatestHermesVersion
- updateHermesVersionsToNightly -> updateHermesVersionsToPrebuilt
Update all call sites in publish-npm.js and publish-npm-test.js.
## Changelog:
[Internal] -
Reviewed By: cortinico
Differential Revision: D104649629
fbshipit-source-id: b1d60b9bb48ef51946e99877a73d5760db585a4c
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56759
The legacy Hermes V0 nightly dist-tag ('nightly') has been removed. This commit
cleans up the ios-prebuild Hermes download logic:
- Remove the 'nightly' sentinel string and getNightlyVersionFromNPM()
- Remove DOWNLOAD_PREBUILT_NIGHTLY_TARBALL source type and downloadPrebuiltNightlyTarball()
- Remove getNightlyTarballUrl() (was fetching from Maven Snapshots for V0 nightlies)
- Rename getLatestV1VersionFromNPM -> getLatestHermesVersionFromNPM
- Update prepare-app-utils.js to use 'latest-v1' instead of 'nightly' for HERMES_VERSION
## Changelog:
[Internal] -
Reviewed By: cortinico
Differential Revision: D104649632
fbshipit-source-id: 91f7c67ee59a3ef835d78146e5ad5ecab25a17bf
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56754
Hermes V1 (Static Hermes) is now always enabled. Remove the isHermesV1 variable and inline its effects:
- enableRegenerator is always based on dev mode (was isHermesV1 && dev)
- preserveClasses is always true (was isHermesV1)
Also update the comments to drop the 'V1' framing.
## Changelog:
[Internal] -
Reviewed By: cortinico
Differential Revision: D104649639
fbshipit-source-id: 70d4cbc0ad365df551b744e3cc16e880ce41c90c
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56731
- Remove all dead C++ code behind `!defined(HERMES_V1_ENABLED)` guards in `HermesExecutorFactory.cpp` and `HermesInstance.cpp`
- Delete `Registration.h`, `Registration.cpp`, `ConnectionDemux.h`, `ConnectionDemux.cpp`, and `ConnectionDemuxTests.cpp` (entirely legacy code)
- Remove `HERMES_V1_ENABLED` compile definition from `react-native-flags.cmake`
- Remove `HERMES_V1_ENABLED` cache variable from Android `CMakeLists.txt`
This is Phase 1 of removing legacy Hermes support. Since Hermes V1 is already the default on all platforms and the 0.86 branch has been cut, all legacy Hermes code
is dead and can be safely removed.
## Changelog:
[General][Breaking] - Remove Legacy Hermes from C++ code
## Test plan
- [x] Android: `./gradlew :packages:rn-tester:android:app:assembleDebug` — BUILD SUCCEEDED
- [x] iOS: `xcodebuild` rn-tester on iPhone 16 Pro simulator — BUILD SUCCEEDED
Reviewed By: cortinico
Differential Revision: D104228879
fbshipit-source-id: 0f88ff703a2936637667257bb8e6a63021d84d3c
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56723
Replace hand-written spec files for `NativeSampleTurboModule` with proper codegen integration by removing exclusion rules and configuring the module in `package.json`. This eliminates ~1600 lines of manual boilerplate (Java, C++, Objective-C) across Android, iOS, and macOS platforms, allowing the codegen system to generate these files automatically from the JavaScript spec.
Changelog: [Internal]
Reviewed By: cipolleschi
Differential Revision: D104323543
fbshipit-source-id: 241f256d03a4ff0f914179c5ee2842d29fad5554
Summary:
`PODFILE_DIR` was being set to `Pod::Config.instance.installation_root.to_s`, which bakes the contributor's absolute path (e.g. `/Users/alice/Projects/MyApp/ios`) into `project.pbxproj` — every `pod install` on a different machine churns the diff, and a checked-in pbxproj points at someone else's filesystem.
Set `PODFILE_DIR` per-project via Xcode variable substitution: `$(SRCROOT)` for user projects, `$(SRCROOT)/..` for the Pods project. Resolved value is identical at build time; the persisted string is now machine-independent.
## Changelog:
[IOS] [FIXED] - Persist `PODFILE_DIR` as `$(SRCROOT)`-relative so `project.pbxproj` is portable across machines
Pull Request resolved: https://github.com/facebook/react-native/pull/56732
Test Plan:
1. `pod install`, inspect host-app and Pods `pbxproj`: `PODFILE_DIR` should be `$(SRCROOT)` and `$(SRCROOT)/..`, not an absolute path.
2. Build the app and confirm consumers of `${PODFILE_DIR}` still resolve correctly (`with-environment.sh`, codegen script phases).
Reviewed By: christophpurrer
Differential Revision: D104398698
Pulled By: cipolleschi
fbshipit-source-id: e00f027d5c3570ac1a9c78b54fdbdaf81f98f17f
Summary:
The `invariant` call in `renderApplication` passes `rootTag` as a substitution argument, but the format string has no `%s` placeholder. When the invariant fails, the error message reads:
```
Expect to have a valid rootTag, instead got
```
instead of:
```
Expect to have a valid rootTag, instead got null
```
The value is silently dropped, making the error less useful for debugging.
## Changelog:
[General] [Fixed] - Fix missing format specifier in renderApplication invariant
Pull Request resolved: https://github.com/facebook/react-native/pull/56329
Test Plan:
- Verified with `invariant` directly: without `%s` the third argument is ignored, with `%s` it is substituted into the message.
- Prettier and ESLint checks pass.
Reviewed By: cipolleschi
Differential Revision: D104657367
Pulled By: javache
fbshipit-source-id: 6b0fad2371941207ef064fa7ea63cdf9aa61ae7f
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56718
Update the return type of `getNativeScrollRef` on `ScrollView`, `FlatList`, `SectionList` to be `PublicScrollViewInstance` (previously, a mix of `HostInstance` and `React.ElementRef<>` types which did not include the imperative methods of `ScrollView`).
- This type extends `HostInstance & ScrollViewImperativeMethods`, and is what the `ScrollView` ref chain already returns at runtime.
- The previous types were either too broad (`HostInstance`), wrong (union with `View`), or required `$FlowFixMe` suppressions.
Also removes `ScrollViewNativeComponent` from the public API surface, since it is an internal implementation detail not intended for external use (equivalent props are on the pre-existing `ScrollViewBaseProps` type).
Related to:
- https://github.com/facebook/react-native/pull/52203
- https://github.com/facebook/react-native/pull/54735
Changelog:
[General][Fixed] - **Strict TypeScript API**: Update `getNativeScrollRef` return type across ScrollView, FlatList, and SectionList
Reviewed By: zeyap
Differential Revision: D104223704
fbshipit-source-id: 7f44f91518d7f84d8a628e58095e616589a068a3
Summary:
### The Problem
When trying to measure the location of a View within a FlatList (ie. for scrolling to the view), the current recommended method is to use measureLayout on the nested view to determine its location inside the containing FlatList:
```
const MyComponent = () => {
const flatListRef = useRef<FlatList>(null);
const nestedViewRef = useRef<View>(null);
const scrollToNestedView = () => {
if (!flatListRef.current || !nestedViewRef.current) {
return;
}
nestedViewRef.current.measureLayout(
flatListRef.current.getNativeScrollRef(),
(x, y) => { flatListRef.current.scrollTo({ y, animated: true }); },
);
}
return (
<FlatList ref={flatListRef}>
<View ref={nestedViewRef}>
{ /* content */ }
</View>
</FlatList>
);
}
```
However the types for `FlatList` `getNativeScrollRef` don't allow this.
### The solution
This solution is basically identical to that in https://github.com/facebook/react-native/issues/52203. The return value for `getNativeScrollRef` should be `HostInstance | null`
## Changelog:[GENERAL] [FIXED] - Change FlatList.getNativeScrollRef return type definition to allow accessing the underlying HostInstance.
Pull Request resolved: https://github.com/facebook/react-native/pull/54735
Test Plan: None needed. This is only a type update exposing existing functionality.
Reviewed By: zeyap
Differential Revision: D104393366
Pulled By: huntie
fbshipit-source-id: 700f708d9a39b16af3e0ed90a748051361101627
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56734
Adds a new RNTester example under the Animation Backend section that runs a looping animation per each property handled by BatchedAnimatedPropsMountItem:
- Top-level numeric props: opacity, elevation, zIndex, shadowOpacity, shadowRadius
- Color props: backgroundColor, color (Text), tintColor (Image), and all
borderColor / borderTopColor / borderBottomColor / borderLeftColor /
borderRightColor / borderStartColor / borderEndColor variants
- All 13 border-radius props (borderRadius and per-corner) in px units, plus
borderRadius in percent units
- All transforms: translateX/Y in px and percent, scale/scaleX/scaleY,
rotate/rotateX/rotateY/rotateZ in deg and rad, skewX/skewY, perspective
Each row exercises one distinct command id from the buffer protocol decoded by BatchedAnimatedPropsMountItem, making it easy to visually verify that every supported animated prop survives the C++ to Java buffer round-trip.
Changelog:
[General][Added] - Add All Animated Props example to the rn-tester Animation Backend section
Reviewed By: zeyap
Differential Revision: D102800169
fbshipit-source-id: eb91b66e67939f65cd30deee1f58fe1684c541d3
Summary:
Adds a new performance test example to the Animation Backend section in rn-tester. The example renders a grid of animated views to stress-test the animation backend.
Changelog:
[General][Added] - Add Performance Test example to the rn-tester Animation Backend section
Reviewed By: zeyap
Differential Revision: D104053337
fbshipit-source-id: 92a34fad88b51754e7e3932d2e9389a7f17d06af
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56466
Add a new React Native feature flag, `optimizedAnimatedPropUpdates`, which gates an upcoming optimized code path for applying animated property updates from the C++ animation backend. The flag defaults to disabled and has no behavioural impact on its own.
Changelog:
[General][Added] - Add `optimizedAnimatedPropUpdates` feature flag
Reviewed By: zeyap
Differential Revision: D101157450
fbshipit-source-id: 7050709144f812771c72db4bf2727543f798fec8
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56761
Aligns `dispatchTrustedEvent` and the underlying `[INTERNAL_DISPATCH_METHOD_KEY]` "protected" symbol method on `EventTarget` with the public `EventTarget.dispatchEvent` contract: both now return `boolean` (`!event.defaultPrevented`) instead of `void`, so callers can tell whether the event's default action was canceled.
Existing call sites ignore the return value, so this is a non-breaking widening.
Changelog: [Internal]
Reviewed By: javache
Differential Revision: D104651715
fbshipit-source-id: 0cc837adb705fc3b34ee4363cd5873176dac25cb
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56760
Aligns error handling in the new EventTarget-based event dispatch path with the legacy plugin path, which surfaces handler errors to the host's global error handler (rather than swallowing them as `console.error`).
Previously, when a React event handler threw, `EventTarget.invoke` caught the error and called `console.error(error)` — the error never reached the host's error reporter, so it was effectively silent in production builds that intercept `console.error`.
This diff replaces the `console.error` calls in `EventTarget.invoke` with a small `reportListenerError` helper that schedules the error to be re-thrown in a new task via `setTimeout(0)`. The throw has no catcher above it, so the host's unhandled-error reporter sees it — matching the legacy plugin path's `runEventsInBatch` + `rethrowCaughtError` behavior of propagating the first listener error after the dispatch batch completes. The dispatch loop itself continues normally so subsequent listeners (e.g. parent bubble handlers) still fire.
Updates the corresponding test in `EventTargetDispatching-itest.js` to drop the `console.error` mock setup that was specific to the old behavior. Both code paths now satisfy the same assertion (`expect(dispatch).toThrow('handler error')`) — the legacy path throws synchronously after the React batch; the new path's async re-throw surfaces inside Fantom's internal work-loop pump during `Fantom.dispatchNativeEvent`.
Changelog:
[Internal]
Reviewed By: javache
Differential Revision: D104650049
fbshipit-source-id: 793072f82c9abf11f4fad23b3c1f044f0e5d2936
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56738
Reduces dispatch latency on the new W3C `EventTarget`-based event pipeline
(gated behind `enableNativeEventTargetEventDispatching`) by eliminating
redundant work that compounds per ancestor on every dispatch.
Four surgical changes, all backwards-compatible with the existing public
API surface (`EventTarget` / `Event` / `LegacySyntheticEvent` / `dispatchNativeEvent`
shapes are unchanged; the protected `EVENT_TARGET_GET_DECLARATIVE_LISTENER_KEY`
contract evolves additively):
1. **Fast path in `EventTarget.invoke()`** when only a prop-listener is present and there are no `addEventListener` listeners — call the prop listener inline without allocating an array or running `for..of`. The mixed-listeners slow path moved to a small `invokeListeners()` helper.
2. **Pre-resolve React prop names once per dispatch** in `dispatchNativeEvent`. The view-config we already look up exposes the bubbled / captured prop names directly; stash them on the event via internal symbol slots (`BUBBLED_PROP_NAME_KEY` / `CAPTURED_PROP_NAME_KEY`) so per-ancestor `EVENT_TARGET_GET_DECLARATIVE_LISTENER_KEY` lookups can read them in O(1) instead of doing a `getEventTypePropName(eventType, isCapture)` hash lookup each time. `ReactNativeElement` reads them with a fallback to the mapping table for events not constructed via `dispatchNativeEvent`. The protected method now receives `(event, isCapture)` instead of `(eventType, isCapture)` — `event.type` is `eventType`, and `isCapture` can't be derived from `event.eventPhase` (which is `AT_TARGET` during both passes through the target node per the W3C "event dispatch" algorithm).
3. **Alias `[EVENT_TARGET_GET_THE_PARENT_KEY]` to the `parentNode` getter** on `ReadOnlyNode.prototype` (instead of a trampoline method that just returns `this.parentNode`). Removes one extra function call per ancestor on the dispatch hot path.
4. **Early-return `processResponderEvent`** for non-touch events (`pointerup`, `pointermove`, `layout`, etc.) when no responder is currently set. Trivially safe; saves the touch counting + `ResponderTouchHistoryStore` + `canTriggerTransfer` work that always short-circuits anyway in that case.
Also adds one new scenario to `EventTarget-benchmark-itest.js` (`'dispatchEvent, bubbling (100), prop listener per target only'`) that isolates the per-target prop-listener cost in pure JS — useful for future micro-validation of `invoke()` changes.
### Benchmark results (`EventDispatching-benchmark-itest.js`, opt mode, FLAG ON, median ns/op)
| Scenario | Before | After | Speedup |
|------------------------------------------------|--------|--------|--------|
| dispatch event, flat (1 handler) | 44,226 | 41,653 | 5.8 % |
| dispatch event, nested 10 deep (bubbling) | 112,489 | 100,050 | 11.1 % |
| dispatch event, nested 50 deep (bubbling) | 405,799 | 359,259 | 11.5 % |
| dispatch event, nested 10 (no handlers) | 105,378 | 98,067 | 6.9 % |
| dispatch event with stopPropagation, nested 10 | 91,868 | 86,831 | 5.5 % |
| render + dispatch, flat | 83,766 | 80,781 | 3.6 % |
Improvements scale with tree depth as the per-ancestor savings compound. The legacy plugin path (FLAG OFF) is unchanged within run-to-run noise on every scenario.
The remaining gap to the legacy path at depth 50 (~2.74×) is dominated by the per-ancestor `NativeDOM.getParentNode` TurboModule call (~5.4 % of total profile inclusive). Closing that requires a non-surgical change (e.g., a bulk native parent-walk API) that is out of scope here.
Changelog:
[Internal]
Reviewed By: javache
Differential Revision: D104414586
fbshipit-source-id: 88513ca40fc3b303931548aac3187ca32f4be9ca
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56762
Fix a crash in `SurfaceMountingManager.updateOverflowInset()` where `getViewState()` throws `RetryableMountingLayerException` when the view state for a tag is not found in the registry.
The crash occurs during batch mount item execution when an `updateOverflowInset` operation references a view tag that has been removed from the registry due to normal lifecycle race conditions. The surface is still active (not stopped), but the view has already been deleted.
The fix replaces `getViewState(reactTag)` (which throws) with `getNullableViewState(reactTag)` + null check + soft exception logging + early return. This matches the defensive pattern already used by peer methods in the same class: `updateLayout`, `addViewAt`, and `removeViewAt`.
Changelog: [Internal]
Reviewed By: cortinico
Differential Revision: D104400233
fbshipit-source-id: 678df406079da98c0c2180766c936b5f2bb9fcf7
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56726
Changelog: [IOS][CHANGED] - Drain React-revision merges from a `BeforeWaiting` main run loop observer instead of dispatching each merge as a separate main-queue block
With Fabric commit branching (`enableFabricCommitBranching`), React commits land on a forked `currentReactRevision_` and are merged into the main branch later via `ShadowTree::mergeReactRevision()`. On iOS, the `schedulerShouldMergeReactRevision:` callback used to do a plain `RCTExecuteOnMainQueue` per promotion, so every promotion enqueued a fresh main queue block that competed for ordering with mount blocks dispatched from concurrent commits with `mountSynchronously=true`.
Instead of dispatching each merge as its own main-queue block, enqueue the surface id into an `unordered_set<SurfaceId>` and drain it from a `MainRunLoopObserver` registered at `kCFRunLoopBeforeWaiting`. The merge calls `ShadowTree::commit(..., mountSynchronously = true)`, so the mount completes inline before the observer returns.
A similar mechanism has already been implemented on Android in D100966623
Reviewed By: javache
Differential Revision: D104227839
fbshipit-source-id: 94953290fad3e65f038846ba81e05591756864a8
Summary:
This PR is a follow-up of https://github.com/facebook/react-native/issues/56358, in order to improve and VirtualizedList tests.
I re-enabled the skipped test `retains batch render region when an item is appended`.
With React 19, the previous approach that was using `jest.runAllTimersAsync` in this test path was unstable because the pre-update render region could still be processing updates.
I adopted the same approach used in https://github.com/facebook/react-native/issues/56358 by introducing a small helper function, `advanceUntilLastCellIndexRendered`, which advances timers one step at a time and stops when the expected state is reached: `cellsAroundViewport.last === items.length - 1`.
As part of this follow-up, I also aligned `advanceUntilRenderAreaChanged` to use performNextBatch for consistent stepwise timer advancement.
## Changelog:
[GENERAL][FIXED] - Re-enabled VirtualizedList "retains batch render region when an item is appended" tes
Pull Request resolved: https://github.com/facebook/react-native/pull/56653
Test Plan:
- Ran the VirtualizedList-test.js and verified all test cases passed.
- Verified test modification correctness by intentionally breaking the related snapshot and check that it is breaking/it is failing.
Reviewed By: cortinico
Differential Revision: D104291284
Pulled By: Abbondanzo
fbshipit-source-id: e32f8707a837a1805ce130d526768228f684e3e7
Summary:
Fixes https://github.com/facebook/react-native/issues/54636. Thanks to the Software Mansion team for the detailed reproduction and analysis.
Based on https://github.com/facebook/react-native/pull/56634
On Android Fabric, events emitted for a tag whose `EventEmitterWrapper` has not yet been set (e.g. the view is preallocated but not mounted) are buffered in a per-ViewState queue. When `updateEventEmitter` later sets the emitter, it drains the queue. However, events arriving between the queue-post and the drain could bypass the queue and dispatch directly, delivering events to JS out of receive order.
This change replaces the lambda-based `enqueuePendingEvent` (which deferred event buffering to a `runOnUiThread` lambda, leaving events "in limbo" in the Handler queue) with direct queue insertion under a `synchronized(viewState)` lock:
- `dispatchEvent` fast path: two volatile reads (`eventEmitter`, `pendingEventQueue`). If the emitter is set and no queue exists, dispatch directly — no lock, no allocation.
- `dispatchEvent` slow path (rare, during view init): `synchronized(viewState)` — re-check emitter under lock; if still null, create queue and enqueue the event. If the emitter became available between the volatile read and the lock, a barrier (`synchronized<Unit>(viewState) {}`) waits for any in-progress drain before dispatching.
- `updateEventEmitter`: `synchronized(viewState)` — set emitter, drain queue, null the queue reference. The queue stays non-null during the drain, so concurrent fast-path checks correctly fall through to the barrier.
Queue nullability (`pendingEventQueue == null`) is the cross-thread signal that replaces the previous `AtomicInteger` counter approach.
## Changelog:
[ANDROID][FIXED] - Fix Fabric out-of-order event delivery for events emitted before view mount
[ANDROID][BREAKING] - Removed SurfaceMountingManager#enqueuePendingEvent
Reviewed By: mdvacca
Differential Revision: D102822618
fbshipit-source-id: d683ef50e8c6bcd52cc947b3eda9cb2c1e1296ff
Co-authored-by: Mohanraj Venkatesan <mohanraj.venkatesan2304@gmail.com>
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56727
Pull Request resolved: https://github.com/facebook/react-native/pull/56725
Remove the stale `disableMaintainVisibleContentPosition` feature flag which was never rolled out (defaultValue: false, expectedReleaseValue: false). This flag was intended to disable the `maintainVisibleContentPosition` prop in ScrollView but was never enabled.
Changes:
- Remove the feature flag definition from ReactNativeFeatureFlags
- Simplify ScrollView.js by removing the unnecessary destructuring of `maintainVisibleContentPosition` (now passed through via otherProps spread)
- Remove related generated code
## Changelog:
[General][Removed] - Removed the unused `disableMaintainVisibleContentPosition` feature flag from ReactNativeFeatureFlags
Reviewed By: javache, cortinico
Differential Revision: D104378114
fbshipit-source-id: 62587caf1aec86010751697217d24cc58cfa0abd
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/55431
Adds `ISetEventLoopControl` to the Hermes-specific JSI. This interface
specifies an user-defined, thread-safe function to schedule some task
provided by the Hermes VM.
The Hermes VM may use this function to "ask" the integrator to run some
arbitrary task when the integrator has exclusive control of the runtime.
Notably, this is useful for the Hermes implementation of Workers, where
the Worker thread may ask the integrator to process an event.
Changelog: [Internal]
Reviewed By: lavenzg
Differential Revision: D91905969
fbshipit-source-id: c006d613862611bb01860a38a99c8881acd0355c
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56721
These have been in experimental for some time and should be moved to canary.
Changelog: [Internal]
Reviewed By: jorge-cab
Differential Revision: D104239097
fbshipit-source-id: 76db513008ea5ca6e4c53411c8b2daad9fe990a8
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56722
Remove `DevServerHelper.websocketProxyURL`, which constructed the URL for the legacy `/debugger-proxy` WebSocket endpoint. This property had no callers — the legacy remote JS debugging proxy has been superseded by `/inspector/device` and `/inspector/debug` endpoints (React Native DevTools CDP).
Changelog: [Android][Removed] - Remove unused `DevServerHelper.websocketProxyURL` property (legacy remote JS debugger)
___
overriding_review_checks_triggers_an_audit_and_retroactive_review
Oncall Short Name: react_native_iroc
Differential Revision: D104253123
fbshipit-source-id: c20922a4a4f21d602e43049144352f6221b9ad99
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56715
Remove the useLISAlgorithmInDifferentiator feature flag and all associated code. This flag was an experimentation flag for using the Longest Increasing Subsequence algorithm in the Differentiator to minimize REMOVE/INSERT mutations during child list reconciliation. The experiment is not being shipped (default was false), so all references are being cleaned up.
Changes include:
- Remove flag from ReactNativeFeatureFlags.config.js and all generated files (C++, Kotlin, JNI, JS)
- Remove the LIS algorithm code path from Differentiator.cpp, keeping only the existing greedy algorithm
- Delete LongestIncreasingSubsequence.h helper and its unit tests
- Update ShadowTreeLifeCycleTest.cpp to remove LIS parameterization (now greedy-only)
- Update Mounting-itest.js and View-benchmark-itest.js to remove LIS flag references and conditional branches
- Remove Facebook Android/iOS overrides and mobile config entries
- Update C++ API snapshots to remove longestIncreasingSubsequence symbol
Changelog:
[General][Removed] - Remove unused `useLISAlgorithmInDifferentiator` feature flag and LIS algorithm code from the Differentiator
Reviewed By: sammy-SC
Differential Revision: D104044772
fbshipit-source-id: 08857d23edba72ec2cf7bdeea876335087b9da8d
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56708
**Context**
Claude-driven audit of Flow source code vs existing public TypeScript API (manual).
**Changes**
Alignments to the `AccessibilityInfo` module for both the source Flow types and manual TS types:
- **Flow**: Move `grayscaleChanged` and `invertColorsChanged` into shared `AccessibilityEventDefinitions` — both events are registered on both platforms in the `EventNames` map.
- **TS**: Add missing event types (`accessibilityServiceChanged`, `announcementFinished`, `darkerSystemColorsChanged`, `highTextContrastChanged`, `windowStateChange`) and platform-specific JSDoc to `AccessibilityChangeEventName` members.
Changelog:
[General][Fixed] - Fix missing and incorrect types in `AccessibilityInfo` TypeScript definitions
Reviewed By: christophpurrer
Differential Revision: D104057500
fbshipit-source-id: d14795aee3d1b55b6c7c06268ae57ab95c8c97ae
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56709
Changelog: [Internal]
Introduces `TouchableSpan`, an interface for spans that receive full
`MotionEvent` touch events from `PreparedLayoutTextView`. Unlike
`ClickableSpan` which only provides an `onClick` callback with no
position information, `TouchableSpan` receives the full `MotionEvent`,
enabling position-aware interactions such as dismiss animations
originating from the tap point.
Reviewed By: Abbondanzo
Differential Revision: D97417356
fbshipit-source-id: 434f9e9e4f2fd5eeb2b535852efdbdfb48ad7734
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56713
Fix a SIGSEGV crash that can occur during WebSocket connection in the React Native JS inspector when `JCxxInspectorPackagerConnectionDelegateImpl::connectWebSocket()` fails (for example, due to allocation failure when constructing the WebSocket delegate hybrid object, or a JNI exception thrown from the Java side).
Previously `InspectorPackagerConnection::Impl::connect()` had no error handling around the `connectWebSocket` call — any exception (`std::bad_alloc`, `JniException`, etc.) would propagate unhandled and terminate the process.
### Changes
1. **`InspectorPackagerConnection.cpp`**: Wrap `connectWebSocket` in try-catch. On failure, log the error, reset the WebSocket, and trigger `reconnect()` (existing 2-second retry mechanism). This is consistent with how other error paths in the same class already handle failures (e.g., `didFailWithError` and `didClose` both call `reconnect()`).
2. **`JCxxInspectorPackagerConnectionDelegateImpl.cpp`**: Add a null check on the JNI return value before calling `wrapInUniquePtr()` to prevent a null dereference if the Java method returns null.
Changelog:
[General][Fixed] - Handle exceptions thrown during WebSocket connect in `InspectorPackagerConnection` to avoid native crashes when the JS inspector fails to connect
[Android][Fixed] - Add null check on JNI return value in `JCxxInspectorPackagerConnectionDelegateImpl::connectWebSocket` to prevent null dereference
Reviewed By: huntie
Differential Revision: D100956267
fbshipit-source-id: e6e7ffa99c600ab437069a5344b4c13ad109eca3
Summary:
Fixes the yarn.lock file where some references to registry.facebook.net leaked
## Changelog:
[Internal] -
Pull Request resolved: https://github.com/facebook/react-native/pull/56719
Test Plan: Tested that yarn install is now passing
Reviewed By: andrewdacenko, zeyap
Differential Revision: D104235290
Pulled By: cipolleschi
fbshipit-source-id: 6396f9d0318e665bb9ece4f12b494b4017dd948d