41837 Commits
Author SHA1 Message Date
Peter Abbondanzo d7ff82ebe4 Fix Activity Result launcher compilation (#58688)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58688

Different AndroidX artifacts expose `ActivityResultLauncher.contract` as either a Kotlin property or a Java `getContract()` method. A Kotlin subclass cannot override both source representations even though they have the same JVM signature.

Route the contract accessor through a package-private Java superclass so both representations resolve to the same JVM method. Use the bridge in production and test launchers, verify that the registered contract is preserved, and allowlist this required Java compatibility source.

Changelog:
[Android][Fixed] - Fix Activity Result launcher compilation across AndroidX source variants

Reviewed By: fkgozali

Differential Revision: D121845437

fbshipit-source-id: 3d4e2c5726a8b39e5bb3863211fb7c88dd16e43a
2026-09-25 17:03:09 -07:00
Peter Abbondanzo 5c87ca977a Guard RTL overhang handling for fixed-line text (#58685)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58685

Add Android regression coverage for exactly constrained RTL text that reserves start-side ink overhang while enforcing a maximum line count and ellipsizing overflow. Also cover the mixed-direction exclusion, where a shared right-side reservation must not be applied.

Changelog: [Internal]

___

Differential Revision: D121670747

fbshipit-source-id: 307461e4ef24d0dad90e609aa8dd7845efc70fa7
2026-09-25 15:46:27 -07:00
Mathieu Acthernoene 447ccd1ddb Make generated props and style types augmentable (#58168)
Summary:
react-native-web and Nativewind extend React Native's types with module augmentation. https://github.com/react/react-native/issues/58062 made the props and style types interfaces, which cleared the duplicate identifier errors. Two things still can't be extended.

**Styles:** `ViewStyle` is an interface derived from `____ViewStyle_Internal`, but `ViewProps['style']` reads the base, so augmenting `ViewStyle` doesn't reach it:

```ts
declare module 'react-native' {
  interface ViewStyle { transitionDuration?: string }
}

<View style={{ transitionDuration: '1s' }} />;             // error
StyleSheet.create({ box: { transitionDuration: '1s' } });  // error
```

`____ViewStyle_Internal` is now named `ViewStyle`, and the same for Text and Image. `StyleSheet` re-exports each name unchanged, so the interface and the base are one symbol.

**Props written as inline object literals:** The transform copies them into the interface body, where a second declaration is a merge conflict rather than an override, so the augmentation is silently ignored. Eleven of the 24 annotated types are affected. Each now moves its inline members into a private `<Name>Core` alias, so they reach the interface through the extends clause and are inherited, like everything from `ViewProps` already was:

```ts
// before
declare interface KeyboardAvoidingViewProps extends Readonly<ViewProps> {
  readonly enabled?: boolean
}

// after
declare interface KeyboardAvoidingViewProps extends Readonly<
  ViewProps & KeyboardAvoidingViewPropsCore
> {}
```

That costs 11 new names in the API snapshot, one per affected type. `PressableProps` set the precedent with `PressableBaseProps`.

`ImagePropsBase` and `ImageBackgroundProps` declare members that shadow keys of the type they spread, and a Flow spread of an optional property unions the two types instead of replacing the member, so those keys get an explicit `Omit`.

Caveat: an augmented member has to be assignable to the inherited one. Adding a key is clean and narrowing works, but widening raises `TS2430` on the declaration file, which `skipLibCheck: true` silences.

## Changelog:

[GENERAL] [CHANGED] - Allow module augmentation to extend generated props and style types

Pull Request resolved: https://github.com/react/react-native/pull/58168

Test Plan:
`yarn build-types`: all 24 annotated types now emit an empty interface body. `ViewStyle`, `TextStyle` and `ImageStyle` are unchanged; the props types gain the 11 `<Name>Core` aliases.

Compiled augmentations with `skipLibCheck: false`. Styles: the two lines above pass here and report `TS2353` on `main`. Props: adding a key and narrowing an existing one on each of the 11 types passes here and reports `TS2717` on `main`.

`yarn flow-check`, `yarn test-generated-typescript`, `yarn format-check` and `yarn lint`: clean, apart from 3 Flow errors in `packages/react-native-codegen/lib` already on `main`. `yarn jest packages/react-native/Libraries packages/react-native/src scripts/js-api`: 632 tests pass, no snapshot changed.

Reviewed By: christophpurrer

Differential Revision: D117876097

Pulled By: cortinico

fbshipit-source-id: c0797f14d95a01662930f7158738ea79e1bf1a30
2026-09-25 15:00:54 -07:00
Intl Scheduler ca92618211 translation auto-update for batch 5/66 on master
Summary:
Chronos Job Instance ID: 1125908310466480
Sandcastle Job Instance ID: 49539596591435978

Processed xml files:
android_res/com/facebook/resources/impl/res/values/strings.xml
android_res/com/facebook/xapp/messaging/common/date/res/values/strings.xml
android_res/com/facebook/messaging/threads/threadconnectivity/res/values/strings.xml
android_res/com/facebook/messaginginblue/inbox/ui/sections/threadlist/res/values/strings.xml
android_res/com/facebook/messaginginblue/diode/ui/components/res/values/strings.xml
android_res/com/facebook/messaginginblue/common/ui/components/msysbootstrap/res/values/strings.xml
android_res/com/facebook/xapp/messaging/message/multiselect/bottomsheet/res/values/strings.xml
android_res/com/facebook/messaging/mutators/res/values/strings.xml
android_res/com/facebook/messaging/snippet/res/values/strings.xml
android_res/com/facebook/messaging/notify/res/values/strings.xml
android_res/com/facebook/messaging/media/viewer/res/values/strings.xml
android_res/com/facebook/messaging/aibot/res/values/strings.xml
android_res/com/facebook/messaging/media/resharehub/res/values/strings.xml
android_res/com/facebook/messaging/notify/permissions/res/values/strings.xml
android_res/com/facebook/messaging/communitymessaging/tab/plugins/tabcontent/res/values/strings.xml
android_res/com/facebook/messaging/aitab/res/values/strings.xml
android_res/com/facebook/messaging/aibot/aistudiotab/res/values/strings.xml
android_res/com/facebook/messaging/linkhandling/res/values/strings.xml
android_res/com/facebook/messaging/montage/viewer/res/values/strings.xml
android_res/com/facebook/messaginginblue/sharesheet/components/externalsharingitem/res/values/strings.xml
android_res/com/facebook/messaging/montage/viewer/viewcontroller/res/values/strings.xml
android_res/com/facebook/ipc/stories/viewer/res/values/strings.xml
android_res/com/facebook/audience/stories/archive/res/values/strings.xml
android_res/com/facebook/messaging/montage/viewer/contextualreplies/res/values/strings.xml
android_res/com/facebook/messaging/montage/viewer/avatarquickreplies/res/values/strings.xml
android_res/com/facebook/messaging/integrity/res/values/strings.xml
android_res/com/facebook/ipc/stories/viewersheet/res/values/strings.xml
android_res/com/facebook/fbavatar/res/values/strings.xml
android_res/com/facebook/presence/note/ui/shared/res/values/strings.xml
android_res/com/facebook/oxygen/preloads/integration/tosacceptance/res/values/strings.xml
android_res/com/facebook/bizapp/auth/res/values/strings.xml
android_res/com/facebook/bizapp/login/res/values/strings.xml
android_res/com/facebook/messaging/montage/composer/art/res/values/strings.xml
android_res/com/facebook/messaging/rtc/meetups/res/values/strings.xml
android_res/com/facebook/xapp/messaging/feature/audiomessage/waveforms/strings/res/values/strings.xml
android_res/com/facebook/video/watchandgo/res/values/strings.xml
android_res/com/facebook/fbshorts/viewer/res/values/strings.xml
android_res/com/facebook/expression/res/values/strings.xml
android_res/com/facebook/rtc/res/values/strings.xml
android_res/com/facebook/messaging/rtc/incall/shared/widgets/res/values/strings.xml
android_res/com/facebook/expression/screensharing/res/values/strings.xml
android_res/com/facebook/messaging/rtc/incall/impl/expression/res/values/strings.xml
android_res/com/facebook/messaging/avatar/upgrade/res/values/strings.xml
android_res/com/facebook/expression/effect/strings/res/values/strings.xml
android_res/com/facebook/messaging/avatar/upsell/res/values/strings.xml
android_res/com/facebook/alohacommon/ar/effects/res/values/strings.xml
android_res/com/facebook/alohacommon/calling/experiences/ar/photobooth/ar/effects/res/values/strings.xml
android_res/com/facebook/alohacommon/ar/photobooth/common/res/values/strings.xml
android_res/com/facebook/workchat/rtc/incall/impl/links/utils/res/values/strings.xml
android_res/com/facebook/video/settings/res/values/strings.xml
android_res/com/facebook/feed/video/inline/res/values/strings.xml
android_res/com/facebook/facecast/display/res/values/strings.xml
android_res/com/facebook/widget/friendselector/res/values/strings.xml
android_res/com/facebook/facecast/view/res/values/strings.xml
android_res/com/facebook/facecast/display/streamingreactions/res/values/strings.xml
android_res/com/facebook/facecast/display/livestatus/res/values/strings.xml
android_res/com/facebook/facecast/display/flexiblebonusbutton/res/values/strings.xml
android_res/com/facebook/search/results/rows/videos/res/values/strings.xml
android_res/com/facebook/zero/nativetemplate/res/values/strings.xml
android_res/com/facebook/video/watch/components/discover/res/values/strings.xml
android_res/com/facebook/video/settings/globalsubtitle/res/values/strings.xml
android_res/com/facebook/video/commercialbreak/res/values/strings.xml
android_res/com/facebook/youth/camera/components/music/res/values/strings.xml
android_res/com/facebook/video/watchandgo/player/plugin/res/values/strings.xml
android_res/com/facebook/spherical/common/res/values/strings.xml
android_res/com/facebook/audience/stories/storysurface/activity/main/res/values/strings.xml
../xplat/orca/msys/feature_aggregation/src/i18n/res/values/strings.xml
android_res/com/facebook/messaging/nativepagereply/pagenotificationsetting/res/values/strings.xml
android_res/com/facebook/messaging/media/download/res/values/strings.xml
android_res/com/facebook/messaging/ui/name/res/values/strings.xml
android_res/com/facebook/messaging/sharing/quickshare/res/values/strings.xml
android_res/com/facebook/rtc/connectionservice/res/values/strings.xml
android_res/com/facebook/rtc/helpers/connectionservicecoordinator/res/values/strings.xml
android_res/com/facebook/messaging/groups/linkshare/res/values/strings.xml
android_res/com/facebook/messaging/rtc/links/res/values/strings.xml
android_res/com/facebook/messaging/rtc/links/sharesheet/res/values/strings.xml
android_res/com/facebook/mig/input/res/values/strings.xml
java/com/facebook/messaging/aura/subs/res/values/strings.xml
android_res/com/facebook/mig/button/progress/res/values/strings.xml
android_res/com/facebook/rtc/permissions/res/values/strings.xml
android_res/com/facebook/messaging/rtc/links/join/res/values/strings.xml
android_res/com/facebook/messaging/rtc/incall/impl/links/errormessage/res/values/strings.xml
../xplat/js/react-native-github/packages/react-native/ReactAndroid/src/main/res/views/uimanager/values/strings.xml
android_res/com/facebook/messaging/rtc/links/blocked/res/values/strings.xml
android_res/com/facebook/messaging/rtc/incall/impl/widgets/useractions/res/values/strings.xml
android_res/com/facebook/messaging/rtc/incall/impl/links/res/values/strings.xml
android_res/com/facebook/rtc/actions/res/values/strings.xml
android_res/com/facebook/messaging/rtc/incall/impl/debugindicator/res/values/strings.xml
android_res/com/facebook/messaging/rtc/incall/impl/active/drawer/ui/res/values/strings.xml
android_res/com/facebook/messaging/rtc/incall/impl/root/res/values/strings.xml
android_res/com/facebook/messaging/rtc/multicall/res/values/strings.xml
android_res/com/facebook/messaging/rtc/incall/impl/emojireactions/res/values/strings.xml
android_res/com/facebook/messaging/rtc/incall/impl/countdown/res/values/strings.xml
android_res/com/facebook/messaging/rtc/incall/impl/widgets/res/values/strings.xml
android_res/com/facebook/payments/p2p/res/values/strings.xml
android_res/com/facebook/payments/p2p/verification/res/values/strings.xml
android_res/com/facebook/payments/p2p/composer/res/values/strings.xml
android_res/com/facebook/payments/p2p/awareness/res/values/strings.xml
android_res/com/facebook/payments/connectivity/res/values/strings.xml
android_res/com/facebook/orca/notify/res/values/strings.xml

allow-large-files
ignore-conflict-markers
opt-out-review
drop-conflicts

Differential Revision: D121865281

fbshipit-source-id: 16362b6be7c91dd98e178bb2fd4eef8f9cd087b9
2026-09-25 14:09:44 -07:00
Peter Abbondanzo c5eb21123b Encapsulate Android 15 text-layout reflection (#58681)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58681

Wrap the three Android 15 text-layout APIs behind typed private helpers that mirror their platform signatures. This keeps reflection isolated and makes replacing each helper with a direct API call a local change once all targets compile against Android 15 or later.

Changelog: [Internal]

___

Differential Revision: D121810388

fbshipit-source-id: d46ac4fd38c4151564fd3f868883fcd470a75924
2026-09-25 13:57:19 -07:00
Ngoc Le 57f408012d Fix RTL start overhang clipping on Android 15+ (#58072)
Summary:
Fixes https://github.com/react/react-native/issues/58064.

Android 15 added glyph-bounds APIs for `StaticLayout`, but `Layout.draw()` only shifts drawing when ink extends past the left edge. In an exactly constrained RTL paragraph, leading ink extends past the right edge instead, so fonts such as Amiri still clip their first glyph at a wrapped line start.

This change:

- enables `setUseBoundsForWidth` and `setShiftDrawingOffsetForStartOverhang` for exactly constrained `StaticLayout`s on API 35+ using the existing reflection approach;
- measures the actual RTL drawing bounds and reserves any right-side overhang in a focused second layout pass while keeping the original exact width reported to Yoga;
- leaves `AT_MOST` and unconstrained text on the existing advance-based measurement path.

On the issue reproducer, the first layout was 1280 px wide while its glyph bounds extended to x=1287.07. Reserving 8 px in the text layout keeps the complete alif-madda ink inside the unchanged 1280 px React Native view.

## Changelog:

[ANDROID] [FIXED] - Prevent RTL line-start glyph ink from clipping on Android 15 and later

Pull Request resolved: https://github.com/react/react-native/pull/58072

Test Plan:
- `JAVA_HOME=$(/usr/libexec/java_home -v 17) ./gradlew :packages:react-native:ReactAndroid:testDebugUnitTest --tests com.facebook.react.views.text.TextLayoutManagerStartOverhangTest -Preact.internal.useHermesStable=true --no-daemon` — BUILD SUCCESSFUL
- `JAVA_HOME=$(/usr/libexec/java_home -v 17) ./gradlew :packages:react-native:ReactAndroid:testDebugUnitTest --tests 'com.facebook.react.views.text.*' -Preact.internal.useHermesStable=true --no-daemon` — BUILD SUCCESSFUL
- `JAVA_HOME=$(/usr/libexec/java_home -v 17) ./gradlew :packages:react-native:ReactAndroid:ktfmtCheck -Preact.internal.useHermesStable=true --no-daemon --rerun-tasks` — BUILD SUCCESSFUL
- Built and installed RNTester on a Pixel 9 Pro emulator running Android 16 / API 36 with `enablePreparedTextLayout` enabled and the Amiri font from the mandatory reproducer. Before the fix, ink reached and was cut at the final pixel column; after the fix, the complete stroke renders inside the tinted Text bounds.

### Visual evidence

**Original clipping reproduction — before and after**

{F1997326330}

**Fixed-line validation at 605 px with `maxLines=5` — before and after**

{F1997312819}

Reviewed By: javache

Differential Revision: D121672279

Pulled By: Abbondanzo

fbshipit-source-id: a66b1a11b434043b849ac71519c58ce7b60b118c
2026-09-25 11:59:44 -07:00
Nicola Corti 1d13ec9889 Bump fbjni to 0.8.1 (#58683)
Summary:
Bump fbjni from 0.7.0 to 0.8.1.

Release notes: https://github.com/facebookincubator/fbjni/releases/tag/v0.8.1

## Changelog:

[ANDROID][CHANGED] - Bump fbjni to 0.8.1

Pull Request resolved: https://github.com/react/react-native/pull/58683

Test Plan:
- `git diff --check`
- Confirmed `com.facebook.fbjni:fbjni:0.8.1` is available from Maven Central
- CI

Reviewed By: christophpurrer

Differential Revision: D121836926

Pulled By: cortinico

fbshipit-source-id: 4a674e346f4aa74dbd97dc3ffb1b211e223069f9
2026-09-25 11:50:39 -07:00
riteshshukla04 ba1ede621c perf: Faster WritableNativeMap.putString value conversion (#58644)
Summary:
I found (while working on https://github.com/react/react-native/pull/58611) that `WritableNativeMap::putString` converted its value with fbjni toString(), which calls Java Object.toString() through JNI before running toStdString(). Since the value is already a `jstring`, I call `toStdString()` directly, which produces identical bytes with one fewer JNI call and local reference.

| Value | Before | After | Delta |
|---|---|---|---|
| 11 ASCII | 0.205 | 0.191 | -6.8% |
| 100 ASCII | 0.265 | 0.231 | -12.8% |
| 300 ASCII | 0.451 | 0.418 | -7.3% |
| 1000 ASCII | 0.984 | 0.966 | -1.8% |
| 100 CJK | 0.325 | 0.298 | -8.3% |

## Changelog:
[ANDROID] [CHANGED] - Skip a redundant JNI Object.toString() call in WritableNativeMap.putString.

Pull Request resolved: https://github.com/react/react-native/pull/58644

Test Plan: I measured putString at 0.614 → 0.474 µs per call for short strings (-23%) on a Galaxy M14, identical output on 21 edge-case strings.

Reviewed By: cortinico

Differential Revision: D121774499

Pulled By: javache

fbshipit-source-id: a20a3d64c6afaf75515f3c3e8173c8e86a1122ce
2026-09-25 11:17:44 -07:00
matinzd ec2b536e14 feat(android): support Activity Result API for native modules (#57798)
Summary:
Rendered readme can be found [here](https://github.com/matinzd/react-native/blob/feat/permission_contracts_android/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/activityresult/__docs__/README.md).

Bare React Native has no way for a native module to use AndroidX `ActivityResultContract`s. Modules are stuck with `ActivityEventListener` and self-assigned int request codes, and some contracts (e.g. Health Connect's permission contract) have no `startActivityForResult` equivalent at all. Calling `registerForActivityResult` on `getCurrentActivity()` instead is a dead end: the lifecycle-observing overload crashes with `LifecycleOwner ... is attempting to register while current state is RESUMED. LifecycleOwners must call register before they are STARTED.`, because AndroidX only allows it before the Activity is `STARTED` — and native modules are created lazily, long after that ([https://github.com/react/react-native/issues/33639](https://github.com/facebook/react-native/issues/33639)).

Libraries work around this by demanding glue code in the consumer's `MainActivity`: react-native-health-connect today requires every app to add `HealthConnectPermissionDelegate.setPermissionDelegate(this)`. The proposed alternative — shipping a transparent `Activity` in the library's manifest ([matinzd/react-native-health-connect#266](https://github.com/matinzd/react-native-health-connect/pull/266), still an unreleased PR) — cuts against Google's single-activity guidance ([https://github.com/react/react-native/issues/33639](https://github.com/facebook/react-native/issues/33639), [https://github.com/react/react-native/issues/36377](https://github.com/facebook/react-native/issues/36377)). Expo solved this with [`registerActivityContracts`](https://docs.expo.dev/modules/module-api/#registeractivitycontracts); bare RN has no equivalent.

`ReactActivity` already extends `ComponentActivity`, so it already owns a real `ActivityResultRegistry` and routes results into it. Core just needs to hand modules a path to that registry:

```kotlin
private val getContent = reactContext.registerForActivityResult(
    /* owner = */ this, ActivityResultContracts.GetContent()) { uri -> ... }

getContent.launch("image/*")
```

Design notes:

- API mirrors `ComponentActivity.registerForActivityResult` and returns the real `androidx.activity.result.ActivityResultLauncher<I>`. The one addition is a leading `owner` argument, which scopes the registration key.
- Modules register before an Activity exists (they are created lazily), so the returned launcher binds to the registry on `onHostResume` and queues a `launch()` issued while unbound.
- No changes to `ReactActivity`/`ReactActivityDelegate`/`ReactDelegate`, no new Gradle dependency, no manifest changes, no forked registry. `ActivityEventListener` is untouched.
- Known limitation: on process death, AndroidX redelivers the pending result under the same key, but the module's in-flight state (typically a `Promise`) died with the JS context.

Demos: `SampleTurboModule.requestSamplePermission()` (CAMERA), plus `pickMedia` and `pickMultipleMedia` (photo picker, single and multi select with a JS-controlled limit), surfaced in rn-tester's SampleTurboModule and PhotoPickerAndroid screens.

## Changelog:

[ANDROID] [ADDED] - Add support for Activity Result API for native modules

Pull Request resolved: https://github.com/react/react-native/pull/57798

Test Plan:
- `./gradlew :packages:react-native:ReactAndroid:compileDebugKotlin` and `:compileDebugJavaWithJavac` pass; codegen emits the sample module methods into `NativeSampleTurboModuleSpec`.
- Flow, ESLint, prettier, and ktfmt clean.

## Example App Recording

https://github.com/user-attachments/assets/63750917-2325-4613-9a0d-b7241ae026eb

Reviewed By: javache

Differential Revision: D115622269

Pulled By: Abbondanzo

fbshipit-source-id: ce623a84d3c5b29f1bae57c2c177517d0cd34190
2026-09-25 10:50:37 -07:00
Jakub Piasecki ab1159ba61 Use umbrella instead of a direct include in runtimescheduler module (#58639)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58639

Changelog: [Internal]

Update the runtimescheduler module to use umbrella includes instead of direct ones.

Reviewed By: javache

Differential Revision: D121206887

fbshipit-source-id: bc346baa96321252b9ab62cddde0d369492cde43
2026-09-25 10:14:31 -07:00
Jakub Piasecki aa0ccf24f1 Use umbrella instead of a direct include in utils module (#58634)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58634

Changelog: [Internal]

Update the utils module to use `React/Debug.h` umbrella include instead of a direct one.

Reviewed By: cipolleschi

Differential Revision: D121165065

fbshipit-source-id: 79cfaa0b6d1227d6761fa35f59dba84b12d532a4
2026-09-25 10:13:06 -07:00
Jakub Piasecki 972860a3f7 Use umbrellas instead of direct includes in rendererdebug module (#58619)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58619

Changelog: [Internal]

Update the rendererdebug module to use the `React/Debug.h` and `React/Utils.h` umbrella includes instead of direct ones.

Reviewed By: cipolleschi

Differential Revision: D121001495

fbshipit-source-id: 92ebf6d9974e44a719b50669903985ffa2d8d8a7
2026-09-25 09:15:32 -07:00
secitr 7f6043bdb0 Avoid closure allocation in RCTDeviceEventEmitter.emit when tracing is disabled (#58661)
Summary:
RCTDeviceEventEmitter.emit is one of the hottest paths in React Native:
NativeEventEmitter.emit delegates to it, so every event delivered from
native (scroll, touch, keyboard, app state, ...) goes through this method.
The current implementation wraps every call in Systrace.trace, which
always allocates two closures (a lazy event-name thunk and a callback)
on every emit — even when tracing is disabled, which is the common case.

This changes emit to guard on Systrace.isEnabled() and use
beginEvent/endEvent directly:

- tracing disabled (common case): one branch check + a plain call —
  zero allocations
- tracing enabled: same trace section name (RCTDeviceEventEmitter.emit#<type>)
  and the same begin/end semantics, including endEvent() in a finally
  block when a listener throws

Behavior is unchanged; only the fast-path allocations are removed.

## Changelog:

[General] [Changed] - RCTDeviceEventEmitter.emit no longer allocates closures on every emit when tracing is disabled, reducing per-event allocation on the native-to-JS event path

Pull Request resolved: https://github.com/react/react-native/pull/58661

Test Plan:
- New Fantom integration tests in packages/react-native/Libraries/EventEmitter/__tests__/RCTDeviceEventEmitter-itest.js (public API, runs against Hermes):
  - event + args are forwarded to listeners
  - no trace section calls when tracing is disabled
  - trace section is begun/ended with the correct name when tracing is enabled
  - end section is still emitted when a listener throws
  - __RCTProfileIsProfiling fallback still enables tracing
- yarn test packages/react-native/Libraries — 433 tests pass (30 suites)
- yarn flow-check — 0 errors
- yarn lint — 0 warnings
- Micro-benchmark (Node v24, tracing disabled, 5M emits with a scroll-like payload):
  - before: 158ms total (~31.6 ns/emit)
  - after: 117ms total (~23.4 ns/emit)
  - ~26% faster per emit; on Hermes/mobile CPUs the win comes from avoiding
    two heap-allocated closures per event

Reviewed By: andrewdacenko

Differential Revision: D121799063

Pulled By: cortinico

fbshipit-source-id: 86607670dfe67fa2faf1df130b8b86d828cc2564
2026-09-25 09:05:49 -07:00
Alex Hunt b26baaeba0 Move Community CLI discovery config into plugin package (1/2) (#58670)
Summary:
Replaces https://github.com/react/react-native/issues/57352.

Self-register commands from the `community-cli-plugin` package via `react-native.config.js` — meaning we can remove the redirect within `packages/react-native/react-native.config.js`.

Progress towards removing `community-cli-plugin` as a direct dep of `react-native`, and paired with https://github.com/react-native-community/template/pull/235.

RNTester and HelloWorld list `react-native/community-cli-plugin` in `devDependencies`, as the template now does (react-native-community/template#235).

Changelog:
[General][Breaking] - `react-native/community-cli-plugin` will no longer be auto-detected from `react-native`. It must now be specified in `devDependencies`.

Pull Request resolved: https://github.com/react/react-native/pull/58670

Test Plan:
Compared `react-native config` output with `react-native-community/cli` 20.2.0.

**RNTester**

- ✅ Commands, platforms, and project config are unchanged from `main`
- ✅ Removing the new `react-native/community-cli-plugin` devDependency drops `bundle`, `start`, `spm`, and `codegen`, so they are registered by plugin discovery

**Template-shaped app** (plugin in `devDependencies`, no project `react-native.config.js`)

- ✅ `bundle`, `start`, `spm`, and `codegen` are registered

Reviewed By: christophpurrer, cortinico

Differential Revision: D121634885

Pulled By: Abbondanzo

fbshipit-source-id: e97c9f820d3c597233ef4a7ddaaf1b752f1f7688
2026-09-25 09:05:12 -07:00
Nicola Corti 4b7f248991 Fix formatting in iOS prebuild header docs
Summary:
Apply the repository formatter to the iOS prebuild header documentation. This restores the expected Markdown line wrapping and the public format check.

Changelog: [Internal]

bypass-github-export-checks

___

Differential Revision: D121797341

fbshipit-source-id: 7a9ac522692341fcf03ba3f76aa111eae50b8f24
2026-09-25 07:26:46 -07:00
Jakub Piasecki 5e12b391e3 Use umbrella instead of a direct include in timing module (#58540)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58540

Changelog: [Internal]

Update the timing module to use `React/Debug.h` umbrella include instead of a direct one.

Reviewed By: cipolleschi

Differential Revision: D120137164

fbshipit-source-id: e6bf6a8b0b8b6684cb9ede64d4daef85879908b6
2026-09-25 05:23:34 -07:00
Jakub Piasecki 63a199f0a7 Fix a circular import in the prebuilt iOS headers (#58635)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58635

Each module ships a small header that acts as its entry point. Those were
being packaged into the React framework, but the code that includes them
lives in the shared headers bundle the framework is built on top of. The two
ended up pointing at each other and the iOS build failed.

Ship the entry-point headers with the shared headers instead. They still
resolve the same way for anyone including them, and no other header moves.

Changelog: [Internal]

Reviewed By: cipolleschi

Differential Revision: D121187558

fbshipit-source-id: c84619b8a37cae457e3eb9578d0ac42f065f152f
2026-09-25 05:23:34 -07:00
Oskar Pawica 361bc240e4 Fix differ creating or deleting a view that a nested (un)flattening moves (#58648)
Summary:
Fixes https://github.com/react/react-native/issues/58647

When a view flattens in the same commit in which its parent unflattens, and one of its children has a negative `zIndex`, the differ creates that child again while it's still mounted, or deletes it even though it only moves.

On iOS this crashes in `RCTComponentViewRegistry` (Debug) or with a SIGSEGV in `RCTMountingManager` (Release). The `zIndex` sorts the child before the view that contains it, and the nested recursion then matches it through a different `ShadowViewNodePair`, so `inOtherTree()` stayed false on the candidate.

I made the final create/delete loop in `calculateShadowViewMutationsFlattener` also skip candidates whose tag the recursion recorded in the sub-visited map. I also fixed `unvisitedRecursiveChildPairs` storing a pointer to a loop-local copy.

## Changelog:

[GENERAL] [FIXED] - Fix the differ creating a mounted view again, or deleting a moved view, when a child with a negative `zIndex` moves in a nested flatten/unflatten

Pull Request resolved: https://github.com/react/react-native/pull/58648

Test Plan: The [reproducer](https://github.com/pawicao/rn-differ-zindex-flatten-repro) from https://github.com/react/react-native/issues/58647 no longer crashes on iOS with React Native built from source with this change; without it, it crashes on the first swap.

Reviewed By: christophpurrer

Differential Revision: D121619877

Pulled By: javache

fbshipit-source-id: d0e692c8645e5cedff9fee0e88133e18809fd3c7
2026-09-25 03:37:58 -07:00
mattijsf 53bf98bf40 Ignore stale image callbacks after an Image view is recycled on iOS (#58669)
Summary:
Fixes https://github.com/react/react-native/issues/58667.

On iOS with the new architecture, an `<Image>` can show the image of another `<Image>` that was unmounted just before. `RCTImageResponseObserverProxy` dispatches its callbacks to the main queue. `RCTImageComponentView` used one proxy for its whole lifetime, and `didReceiveImage` only checked that the view still had a state. When a view was recycled and handed to a new `<Image>` while a callback for the old request was still queued, that callback was applied to the new image. If the new source was cached it had already been applied synchronously on subscribe, so the late old image stayed on screen.

This change:

- creates a new `RCTImageResponseObserverProxy` for every subscription in `_setStateAndResubscribeImageResponseObserver`
- ignores image, progress and failure callbacks whose `observer` is not the current proxy (the `fromObserver:` argument was already passed but not used). For failures this also stops a stale error from clearing the new image.

The proxy's address identifies the subscription. The new proxy is allocated before the previous one is released, so two consecutive subscriptions never share an address. Reuse of an old address would need two resubscriptions while a callback from the first one is still queued.

## Changelog:

[IOS] [FIXED] - Image no longer shows the image of a previous source after its native view is recycled

Pull Request resolved: https://github.com/react/react-native/pull/58669

Test Plan:
Reproducer: https://github.com/mattijsf/rn-image-recycled-view-stale-image (React Native 0.87.1, also as a Snack: https://snack.expo.dev/mattijsf/image-recycle-stale-load-ios?platform=ios). It mounts 64 uncached remote images (red), replaces them with a cached one (green) as soon as the first red one has loaded, and counts a wrong image when the new image's `onLoad` reports the old image's size. A run is 50 rounds.

Release build on the iOS simulator (iPhone 17 Pro Max, iOS 26.5), React Native built from source (`RCT_USE_PREBUILT_RNCORE=0`), one run of 50 rounds each. The diff applies unchanged to 0.87.1.

| | rounds with a wrong image | wrong images |
| --- | --- | --- |
| 0.87.1 | 27 of 50 | 120 |
| 0.87.1 with this change | 0 of 50 | 0 |

With the change the red images still show up briefly before each swap, as intended, but none of them end up on a green tile.

Reviewed By: christophpurrer

Differential Revision: D121619393

Pulled By: javache

fbshipit-source-id: 78c29450bb25083667515c95f8c704d3b7db5eef
2026-09-25 02:46:25 -07:00
Christoph Purrer 86c2cf1b84 Remove FDSTooltipView from LegacyViewManagerInteropComponentDescriptor (#57891)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57891

Changelog: [INTERNAL]

Agent plan: https://www.internalfb.com/agent-home?session_id=dmh-5d8c6289-e388-47f0-8069-163c8b3ac508

Reviewed By: GijsWeterings, mdvacca

Differential Revision: D115470032

fbshipit-source-id: 7b04e19d644c3c724d33408a4f932734ef13632a
2026-09-24 23:30:04 -07:00
generatedunixname1563563004708334 de350e65e1 xplat/js/react-native-github/packages/react-native/ReactCommon/jsi/jsi/JSIDynamic.cpp (#58677)
Summary: Pull Request resolved: https://github.com/react/react-native/pull/58677

Reviewed By: christophpurrer

Differential Revision: D121160587

fbshipit-source-id: cfb9b8cf9dff91cc15b6598ba114103c31e7dd8c
2026-09-24 18:58:24 -07:00
Sam Zhou 5880e42ce8 Deploy 0.333.0 to xplat
Summary:
[changelog](https://github.com/facebook/flow/blob/main/Changelog.md)
Changelog: [Internal]

Reviewed By: gkz

Differential Revision: D121669551

fbshipit-source-id: cb1baae809941e0c970bfe80209db284623fade0
2026-09-24 17:03:47 -07:00
Alan Hughes 0e9d314184 Close the Android dev menu when the menu key is pressed again (#58668)
Summary:
On Android, the menu key (`Cmd+M`) opens the dev menu, but a second press does not close it. On iOS, `Cmd+D` toggles the dev menu. This PR makes Android work the same way.

## Changelog:
[ANDROID] [FIXED] - Pressing the menu key while the dev menu is open now closes it

Pull Request resolved: https://github.com/react/react-native/pull/58668

Test Plan: RNTester on an emulator. Toggling works as expected

Reviewed By: andrewdacenko

Differential Revision: D121616477

Pulled By: shwanton

fbshipit-source-id: 9d16a3349c5f9ddff5c7e46d5a590b9dbd525d3b
2026-09-24 12:17:48 -07:00
tshmieldev 585b28c5f0 fix(android): skip null gradient color stop positions instead of warning (#58636)
Summary:
`processBackgroundImage` emits `position: null` for every color stop that has no explicit position, which is the common case (`linear-gradient(red, blue)`). On Android, `LinearGradient` and `RadialGradient` pass that value straight to `LengthPercentage.setFromDynamic`, which logs

```
W ReactNative: Unsupported type for radius property: Null
```

once per such stop on every props update. A static view logs it on each render; an animated `backgroundImage` (e.g. Reanimated CSS animations) floods logcat at frame rate. The value itself is handled correctly (`null` position → evenly spaced), so this is purely log noise, but it drowns out real warnings.

`BackgroundPosition` already guards against `ReadableType.Null` before calling `setFromDynamic`; this change does the same for gradient color stops in both gradient parsers.

## Changelog:

[ANDROID] [FIXED] - Stop logging "Unsupported type for radius property: Null" for gradient color stops without an explicit position

Pull Request resolved: https://github.com/react/react-native/pull/58636

Test Plan:
Built React Native from source (`includeBuild('../node_modules/react-native')`) in an app that animates `backgroundImage` on Android (Pixel 9 Pro emulator, API 37) and counted the warning in `adb logcat` over an identical ~90 s run:

- before: 1386 occurrences of `Unsupported type for radius property: Null`
- after: 0 occurrences

Gradients with and without stop positions render the same as before. `yarn format-check-kotlin` (ktfmt) passes on the changed files.

Reviewed By: Abbondanzo

Differential Revision: D121621185

Pulled By: javache

fbshipit-source-id: 7baeea9e373dd03db9b911c6a57d9cb90e33a866
2026-09-24 11:27:37 -07:00
Mathieu Acthernoene ab373989c3 Remove TextInput blurOnSubmit (#57393)
Summary:
Removes the `blurOnSubmit` TextInput prop, deprecated since 0.77 in favor of `submitBehavior`. Cleans it from the JS API, types, native component spec, and rn-tester examples. Default behavior is unchanged: single-line inputs blur and submit, multiline inputs insert a newline.

See https://github.com/react/react-native/issues/57384

## Changelog:

[GENERAL] [REMOVED] - Remove deprecated `TextInput` `blurOnSubmit` prop (use `submitBehavior` instead)

Pull Request resolved: https://github.com/react/react-native/pull/57393

Test Plan:
- `yarn flow check` passes
- `yarn build-types` regenerates the API snapshot without `blurOnSubmit`
- rn-tester "Submit behavior" example still covers all `submitBehavior` values

Reviewed By: andrewdacenko

Differential Revision: D110336776

Pulled By: Abbondanzo

fbshipit-source-id: 214e6270e8cab04b87f7a90972c6be5174cacc40
2026-09-24 10:42:22 -07:00
Rubén Norte 765d153ece Complete remaining deep import migration (#58673)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58673

Migrate remaining React Native consumer deep imports to supported root and secondary entrypoints. Keep Jest preset package-internal type imports on OSS-exported implementation paths while preserving runtime mock behavior.

Changelog: [Internal]

Reviewed By: cipolleschi

Differential Revision: D121588775

fbshipit-source-id: 6f75784647a75b95e8e5e3e706f6299ad97eb146
2026-09-24 10:05:17 -07:00
Rubén Norte f156ef2b02 Consolidate generated view config imports (#58651)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58651

Generated view configs currently emit repeated property accesses from React Native entry-point requires and route commands through a renderer namespace. Consolidate imports by source and expose `dispatchCommand` directly from the unstable internals entry point, reducing generated Hermes bytecode while preserving existing stable root exports. Metro's inline-require transform would otherwise expand the consolidated unstable-internals binding back into repeated `require(...)` calls, so keep that dependency non-inlined while leaving other generated imports eligible for lazy loading. Make the unstable `HMRClient` export follow React Native's normal development/production selection so production consumers receive `HMRClientProdShim` instead of including HMR tooling.

Changelog:
[General][Fixed] - Reduce generated native component bundle overhead

Reviewed By: javache

Differential Revision: D121383217

fbshipit-source-id: 3b81db620bcff172d43d0493dd4ca22b30f305d6
2026-09-24 09:23:32 -07:00
Rob Hogan c33c241c98 Bump @babel/parser to ^7.29.9, @babel/types to ^7.29.8 (#58641)
Summary:
X-link: https://github.com/react/metro/pull/1962

Pull Request resolved: https://github.com/react/react-native/pull/58641

This picks up https://github.com/babel/babel/pull/18241, fixing parsing of arrow function params inside ternaries with Flow (eg `cond ? async (...args) => {} : null`).

(I remember hitting this one internally and not realising where it came from - IIRC it also applies to arrows within conditional types)

The update brings `babel/types` 7.29.7 -> 7.29.8, requiring regeneration of generated flow types. ~~**The `xplat/js/yarn.lock` version will likely need updating to match, or the Babel types sync test will fail**~~ - I've updated specifiers to bring everyone onto that version.

Changelog: [Internal]

X-link: https://github.com/react/metro/pull/1958

Test Plan: CI

Reviewed By: javache

Differential Revision: D121188416

Pulled By: vzaidman

fbshipit-source-id: 60f9c3514b5d6018825423644c47e66b3610b652
2026-09-24 09:18:50 -07:00
iray-tno 2915fe02ca Fix TalkBack crash in ReactScrollViewAccessibilityDelegate when a list child has no accessibilityCollectionItem (#58660)
Summary:
With TalkBack on, a `ScrollView` that has `accessibilityCollection` set crashes the app as soon as any direct child of its content view lacks `accessibilityCollectionItem` — e.g. a FlatList `ListHeaderComponent` or `ListFooterComponent`. It reproduces on a common path: a screen reader user navigating away from a list screen. In release builds there is no red box; the process just dies.

```
java.lang.NullPointerException: null cannot be cast to non-null type com.facebook.react.bridge.ReadableMap
  at ReactScrollViewAccessibilityDelegate.onInitializeAccessibilityEventInternal(ReactScrollViewAccessibilityDelegate.kt:74)
  ...
  at android.view.View.clearAccessibilityFocus(View.java:15215)
  at android.view.ViewGroup.removeViewInternal(ViewGroup.java:5611)
  at com.facebook.react.fabric.mounting.SurfaceMountingManager.removeViewAt(SurfaceMountingManager.kt:493)
```

The cause is a non-null cast on a value the code expects to be null:

```kotlin
var accessibilityCollectionItem: ReadableMap? =
    nextChild.getTag(R.id.accessibility_collection_item) as ReadableMap   // throws on null
...
// If this child's accessibilityCollectionItem is null, we'll check one more nested child.
if (nextChild.childCount > 0 && accessibilityCollectionItem == null) {
```

The variable is declared nullable and the null branch right below it was written for exactly this case, but the `as` cast throws before that branch can run. This PR changes it to `as?`, matching the other tag reads in the same file. No behavior change for children that do carry the tag.

It has gone unnoticed because no React Native component sets `accessibilityCollection` itself (it was added in 105a2397b6 for https://github.com/react/react-native/issues/30977), so the early return at the top of the method skips this code for core lists. Any library that sets it to announce a windowed list's real length hits the crash immediately. Observed on 0.87.1 (API 36, new architecture, Hermes); details in https://github.com/iray-tno/hozo/issues/512.

## Changelog:

[ANDROID] [FIXED] - Fix crash in ScrollView accessibility delegate when `accessibilityCollection` is set and a child (e.g. a list header or footer) has no `accessibilityCollectionItem`

Pull Request resolved: https://github.com/react/react-native/pull/58660

Test Plan:
- One-token change (`as` → `as?`); the assigned variable is already `ReadableMap?` and all later uses are null-checked, so types are unchanged.
- Not built or tested locally: the environment had no Android SDK. Relying on CI for the Android build.
- Repro (before this change): Android + TalkBack, a `FlatList` with `ListHeaderComponent`, `accessibilityCollection` on the list and `accessibilityCollectionItem` on cells only; put accessibility focus inside the list and unmount the screen → crash above. Expected after: no crash.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Reviewed By: Abbondanzo

Differential Revision: D121556760

Pulled By: cortinico

fbshipit-source-id: ccbfe470dc53adec3deac3458b83ae2bc08a48cb
2026-09-24 08:36:09 -07:00
Alan Hughes 9fae71c2dd Bump targetSdk to 37 (#58666)
Summary:
Bump `targetSdk` to 37. This follows the `compileSdk` and `buildTools` bump to 37 in https://github.com/react/react-native/issues/57284.

I checked each [Android 17 change for apps that target 37](https://developer.android.com/about/versions/17/behavior-changes-17) against React Native core.

## Changelog:
[ANDROID] [CHANGED] - Update `targetSdk` to 37

Pull Request resolved: https://github.com/react/react-native/pull/58666

Test Plan: RNTester, on two Android 17 emulators. A phone and a Pixel Tablet

Reviewed By: cortinico

Differential Revision: D121603066

Pulled By: Abbondanzo

fbshipit-source-id: 288b3a425ed597cc0b01996b6692e4b98aae94fb
2026-09-24 07:53:20 -07:00
Nicola Corti 165acc04b6 Make Fantom CI retries rerun the test suite (#58672)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58672

Fantom CI retries used Jest's `--onlyFailures` cache after a failed full-suite run. Process-level failures such as `SIGSEGV` are not recorded as failed test results, so Jest selected no tests and both retries exited immediately.

Run the full Fantom suite on each retry so transient runner crashes get real retry attempts.

Changelog: [Internal]

___

Differential Revision: D121570534

fbshipit-source-id: 7d325eb8786848cbb018d9db6fea7e51650bb9e1
2026-09-24 07:10:35 -07:00
Peter Abbondanzo 88b9c3fb7c Retry suite-level runtime failures (#58631)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58631

Fantom's CI retries use Jest's `--onlyFailures` mode. Jest 29's default sequencer caches suite-level runtime errors as passing because they contain no failed test cases, so retries select no suites.

See https://github.com/react/react-native/actions/runs/35630015753/job/106440689782?pr=58624 of an example of this, where retries didn't actually do anything

Add a Fantom-specific sequencer that marks runtime-error suites as failed only for cache bookkeeping. This preserves the original test reporting while ensuring targeted retries rerun the crashed suite.

Changelog: [Internal]

Reviewed By: cipolleschi

Differential Revision: D121063351

fbshipit-source-id: e24737cc247ea0e11aa04dac74d557a3f41f9db6
2026-09-24 06:58:58 -07:00
Amro Altahtamouni b71d466561 Fix jest-preset resolution under pnpm and Yarn pnpm-mode (#58598)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58598

Fixes https://github.com/facebook/react-native/issues/56641

The preset failed in two ways under strict-isolation installs (pnpm and Yarn pnpm-mode): `react-native` was not a declared dependency so `jest-preset.js` could not resolve it, and the `transformIgnorePatterns` rule only matched classic `node_modules` layouts so preset sources shipped untransformed.

- Declare `react-native` as a peer dependency so the installer links it into the preset's scope.
- Move `babel/core` from dependencies to peerDependencies: `babel-jest` peer-depends on it, so it must be provided, but as a direct dependency a strict installer gives the preset its own copy and the consumer's `babel.config.js` presets would then load under a different `babel/core` instance than the consumer's own. A peer keeps one copy, matching how `react` and `react-native` are already declared. `babel/runtime` stays a direct dependency: the preset's sources are compiled with `babel/plugin-transform-runtime` helpers enabled, so the transformed `jest/setup.js` requires `babel/runtime/helpers/*` from the preset's own scope at Jest runtime (verified: removing it makes the pnpm harness fail with `Cannot find module 'babel/runtime/helpers/interopRequireDefault'`).
- Resolve the `babel-jest` transformer from the preset's own scope via `require.resolve('babel-jest')` instead of the bare specifier.
- Match `react-native` sources in `transformIgnorePatterns` at each layout's anchored location - classic `node_modules`, pnpm (`.pnpm/<id>/node_modules/...`), and Yarn pnpm-mode (`.store/<flat>-<protocol>-<hash>/package/...`) - so strict-isolation layouts still transform preset and `react-native` sources. Yarn records the resolution protocol in the store entry name, so the pattern accepts `npm` (which also carries the version) plus `virtual`, `patch`, `file`, `portal`, `link`, `exec` and `workspace`; `yarn patch react-native` is common enough that matching only `-npm-`/`-virtual-` would leave those installs broken. The protocols are listed explicitly rather than accepting any word, so `react-native-reanimated-npm-<hash>` cannot put `reanimated` in the protocol position. The classic layout is matched exactly as before this change: scoped third-party packages whose unscoped name is `react-native` (`sentry/react-native`, `notifee/react-native`), nested directories literally named `react-native`, and real `-suffix` packages all stay ignored.
- Write the `.store` scoped-package segment as `(?:-[^-\/]+)*` rather than `(-[^\/]+)*`. The inner class in the original form could itself consume `-`, so a dash-separated name had exponentially many ways to be partitioned and any near-miss path under `node_modules/.store/react-native-...` forced catastrophic backtracking. Jest evaluates `transformIgnorePatterns` against every candidate file path, so one pathological path could hang a run. Restricting the segment to non-dash characters makes the partition unique and the match linear, with no change to which paths are ignored.

Known limitation: under Yarn pnpm-mode's `.store` layout, a scoped package's slash flattens to a dash, erasing the scope boundary - so third-party `react-native-<scope>/*` packages (e.g. `react-native-async-storage/async-storage`) are indistinguishable from genuine `react-native/*` ones and are also transformed there. Transforming is the safe direction (a miss would ship untransformed sources); the impact is performance-only and confined to Yarn pnpm-mode.

Changelog:
[General][Fixed] - Fix `react-native/jest-preset` failing to resolve `react-native` and to transform preset sources under pnpm and Yarn pnpm-mode installs

Reviewed By: robert68-code, vzaidman

Differential Revision: D119701713

fbshipit-source-id: 9f841197bc087b86ae29e77218e13644eb82913e
2026-09-23 17:29:09 -07:00
Sam Zhou 18f5ddb6bb Upgrade flow in fbsource (#58655)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58655

X-link: https://github.com/react/metro/pull/1964

Changelog: [Internal]

Reviewed By: gkz

Differential Revision: D121416054

fbshipit-source-id: 451ecdfea111919e24bdbd274d00622bb66b50bc
2026-09-23 11:57:54 -07:00
Christian Falch b935e74ad5 Repair stale staged headers in the iOS prebuild (#58596)
Summary:
The iOS prebuild (`node scripts/ios-prebuild`) stages React Native's headers into `packages/react-native/.build/headers` as hard links, and skipped any target that already existed.

When changing the original source files, these hard links can become stale and errors like this can occur:

```
Libraries/LinkingIOS/RCTLinkingManager.mm:91:7: error: use of undeclared identifier 'RCTIsSceneDelegateApp'
```

This is a problem that contributors will see - not regular users, but the fix helps with strange error messages.

## Changelog:

[INTERNAL] [FIXED] - Repair stale staged headers in the iOS prebuild instead of compiling against a previous checkout's copies

Pull Request resolved: https://github.com/react/react-native/pull/58596

Test Plan:
✅ New unit tests, 16 cases in `packages/react-native/scripts/ios-prebuild/__tests__/setup-test.js`, using real temporary directories rather than an `fs` mock, since the defect is about inodes.

End to end on an Xcode 27 checkout:

- Replaced a staged header with a copy, so it kept the same contents but a different inode. `node scripts/ios-prebuild -s -f Debug` restored it to the source inode and logged `Linked React/Base → .build/headers/React`. The previous code skipped it.
- Ran setup a second time with nothing changed: no file was relinked, and nothing was logged.
- Confirmed the three colliding targets still resolve to the same source as before the change, by inode.
- `node scripts/ios-prebuild -b -f Debug -p ios-simulator` → `** BUILD SUCCEEDED **`.

Reviewed By: cipolleschi

Differential Revision: D120740409

Pulled By: shwanton

fbshipit-source-id: 41c1eb112c3395d6c7158d7151be7fdd92a21cef
2026-09-23 07:06:12 -07:00
Sedat Çiftçi 731ae45ae6 Reduce allocations in VirtualizedList render and scroll path (#58593)
Summary:
`VirtualizedList`/`FlatList`/`SectionList` re-run a small amount of
bookkeeping on every render and on every scroll event (60–120 Hz on
ProMotion displays). This PR removes three allocations from those hot
paths without changing any observable behavior:

1. **`VirtualizedList.render` no longer builds a `Set` for
   `stickyHeaderIndices` on every render** when the prop is not provided
   (the common case). The Set is now only created when the prop is
   present; the two `.has()` lookups use optional access.
2. **`ChildListCollection.forEach` returns early when there are no nested
   child lists** (the common case) instead of allocating a
   `Map.values()` iterator. This is called from `_onScroll` and the four
   other scroll callbacks on every scroll event.
3. **`_orientation()` caches its result** and only rebuilds the object
   when the `horizontal` prop changes. `I18nManager.isRTL` is a
   module-load constant (only changes on app reload), so the cache is
   invalidated solely by the `horizontal` prop. The object is replaced,
   never mutated, which keeps `ListMetricsAggregator`'s field-based
   invalidation correct.

## Changelog:

[GENERAL][CHANGED] - Reduce allocations in the `VirtualizedList` render and scroll path (avoid per-render `Set` allocation for `stickyHeaderIndices`, per-scroll-event `Map` iterator for the empty nested-list collection, and per-call `orientation` object allocation)

Pull Request resolved: https://github.com/react/react-native/pull/58593

Test Plan:
- `yarn test packages/virtualized-lists` → 9 suites, 186 passed, 69
  snapshots:
  - `ChildListCollection-test.js` (new): forEach over populated/empty
    collection, removal, `forEachInCell`/`anyInCell`
  - `VirtualizedList-test.js`: `stickyHeaderIndices` not forwarded when
    the prop is absent (with `ListHeaderComponent`), forwarded when
    provided; orientation cache identity + invalidation on
    `horizontal` change
- `yarn flow-check` → 0 errors
- `yarn lint` → 0 errors, 0 warnings
- `yarn format-check` (changed files)

Micro-benchmark (Node v24, V8, 2M iterations, before vs after, same
machine; the real-world benefit is dominated by reduced GC pressure,
which is largest on low-end Android):

Reviewed By: Abbondanzo

Differential Revision: D121177373

Pulled By: javache

fbshipit-source-id: 1befd7e6d90fbd1fcea9c4cc8cf6d575c6c26111
2026-09-23 05:15:29 -07:00
Vitali Zaidman 7ce1b2c536 Format ParagraphEventEmitterTest.cpp with clang-format (#58649)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58649

Whitespace-only fix. The file was added unformatted in d38c8495e6e2, which makes the react/react-native Format check (yarn format produces a diff) fail on every PR until fixed.

Changelog: [Internal]

___

Reviewed By: javache

Differential Revision: D121381554

fbshipit-source-id: 78a164e006ffe324c8d85e9645c552f7661061ae
2026-09-23 04:49:01 -07:00
Jakub Piasecki 7a65eab410 Fix iOS frameworks build after switching to umbrella (#58646)
Summary:
After https://github.com/react/react-native/pull/58571, the iOS frameworks build started failing due to missing search paths. This PR adds them, which should fix the build.

Changelog: [INTERNAL]

Pull Request resolved: https://github.com/react/react-native/pull/58646

Test Plan: Checks should be green

Reviewed By: cortinico

Differential Revision: D121375796

Pulled By: j-piasecki

fbshipit-source-id: 5a6fa54576584fc4742cfd71db417249393f283e
2026-09-23 04:09:08 -07:00
Nicola Corti d950a46cb9 Expand RNTester native interop Maestro coverage (#58444)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58444

Add direct-deep-link Maestro coverage for RNTester native interop scenarios and expand the legacy native module flow to validate its platform-specific result set. Make deep-link flows reliable by cold-starting their first route, acknowledging the iOS system confirmation, waiting for route-specific readiness, and using target-driven list scrolling. Extend the Maestro Cloud execution window for the expanded suite and exercise the intended native methods. Exclude the local screenshot-baseline flow from Maestro Cloud.

Reviewed By: Abbondanzo

Differential Revision: D119484762

fbshipit-source-id: 4004cdfd84f85420eb9e28a4fb9e2f0312ea05e0
2026-09-23 03:08:07 -07:00
Nicola Corti b9a959643c Deep-link RNTester Pressable and Modal Maestro flows (#58482)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58482

Update the existing Pressable and Modal Maestro flows to open their RNTester examples directly. Extend the Pressable flow to cover content presses, feedback events, hit slop, and text presses.

Changelog: [Internal]

Reviewed By: Abbondanzo

Differential Revision: D119484761

fbshipit-source-id: 54bed143962b1c40e6c18ba2ba75eb965281f744
2026-09-23 03:08:07 -07:00
Nicola Corti eba89ccc99 Add deep-link Maestro flows for RNTester lists (#58481)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58481

Add Maestro coverage for FlatList and SectionList viewability behavior using direct RNTester example deep links. Use explicit gestures inside the virtualized lists and wait for the callback output. Add nonvisual, route-specific readiness IDs so successive deep links cannot match the previously mounted list.

Changelog: [Internal]

Reviewed By: Abbondanzo

Differential Revision: D119484760

fbshipit-source-id: 4fccf77355265728b7574f53600105de7ff34daa
2026-09-23 03:08:07 -07:00
Nicola Corti b3839a3d03 Add deep-link Maestro flows for RNTester basics (#58480)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58480

Add Maestro coverage for portable RNTester interaction scenarios using direct example deep links. The flows cover alerts, animations, appearance, filters, text input, and touchables without screenshot baselines.

Changelog: [Internal]

Reviewed By: Abbondanzo

Differential Revision: D119484759

fbshipit-source-id: f17aa255cdbf860ac9864185b509ddddb34089e5
2026-09-23 03:08:07 -07:00
Sam Zhou 4b6cd413d6 Replace legacy compat types with their new names in TS based lib.dom.d.ts in xplat: 2/n (#58643)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58643

X-link: https://github.com/react/metro/pull/1960

Changelog: [Internal]

Reviewed By: gkz

Differential Revision: D121075922

fbshipit-source-id: 0f4bdcb339e2c3987dc5942deb47c026668a9fa1
2026-09-22 12:04:26 -07:00
Peter Abbondanzo 4ffc4a6523 Move sample TurboModule spec to RNTester (#58626)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58626

Move `NativeSampleTurboModule` into RNTester so React Native core codegen no longer treats the sample as public API. Retarget the sample native implementations to RNTester's generated `AppSpecs` on Android, iOS, and macOS.

Changelog:
[General][Removed] - Remove the sample TurboModule from React Native's public API

Reviewed By: christophpurrer, javache

Differential Revision: D121032097

fbshipit-source-id: 865222ce4d4d4c8da323ae444eb43bec940ef000
2026-09-22 11:15:18 -07:00
Pieter De Baets a016535a83 Remove differentiator unflatten feature flag
Summary:
Make the corrected parent-tag path unconditional and remove obsolete flag plumbing now that the behaviour is fully enabled.

Changelog: [Internal]

Reviewed By: jehartzog

Differential Revision: D121181685

fbshipit-source-id: bf2d3fc99734df51ed37404bfd628a12ed946c2b
2026-09-22 09:09:58 -07:00
Kaic Bastidas 099bcb444e Update eslint-plugin-ft-flow to fix ESLint v9 issue (#55628)
Summary:
When trying to use the `react-native/eslint-config` with ESLint v9, we get an issue with the `eslint-plugin-ft-flow`:

```bash
Oops! Something went wrong! :(

ESLint: 9.39.2

TypeError: Error while loading rule 'ft-flow/define-flow-type': context.getAllComments is not a function
```

Looking into it, I noticed that our current version (`^2.0.0`) does not support ESLint v9. Only in version `^3.0.11` it show as a valid peer dependency version.

So, although we do have a flat config, we don't support ESLint v9 out of the box.

## Changelog:

<!-- Help reviewers and the release process by writing your own changelog entry.

Pick one each for the category and type tags:

[ANDROID|GENERAL|IOS|INTERNAL] [BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY] - Message

For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests
-->

[General] [Fixed] - Fixed the issue when using the flat config with ESLint v9.

Pull Request resolved: https://github.com/react/react-native/pull/55628

Test Plan:
I've made a repro repo: https://github.com/tcK1/Repro-ESLint9-RN

Updated the ESLint version to v9 and added the `eslint-plugin-ft-flow` version in the `resolutions` configuration in the `package.json`.

In this state, running `yarn eslint .` works as expected. To reproduce the issue, remove the `resolutions` field (and run `yarn install` again to update the dependencies) and run the command again.

Reviewed By: cipolleschi

Differential Revision: D121042705

Pulled By: cortinico

fbshipit-source-id: fd330a514ad991de379ddadc2295190e75ccb663
2026-09-22 08:17:41 -07:00
Dawid Małecki d381a99491 Use public umbrellas in text headers (#58571)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58571

Route public C++ dependencies through their supported umbrella entry points so framework consumers can use the text module with strict API enforcement enabled.

Changelog: [Internal]

Reviewed By: cortinico

Differential Revision: D120529435

fbshipit-source-id: 5f0b698acd9a0363c3f56d1a0b9831c27c31fad3
2026-09-22 08:04:18 -07:00
Christian Falch 97cc934dc7 Stop re-creating library package roots on every sync (#58597)
Summary:
Building an app in Xcode fails when it autolinks a library that ships its own `Package.swift`, with one error per such library:

```
Missing package product 'reactnativeskia_ReactNativeSkia.ReactNativeSkia'
Missing package product 'reactnativesafeareacontext_ReactNativeSafeAreaContext.ReactNativeSafeAreaContext'
```

The same project builds fine from the command line. Two problems combine.

**The sync destroys package roots Xcode has already loaded.** Autolinking writes one symlink per self-managed library into `build/generated/autolinking/libs/<Name>`, and Xcode treats each as a local Swift package root. The generator deleted that whole directory and recreated it on every run, even when the generated output was byte-for-byte identical. Measured on a real app, across one no-op sync: the `libs/` inode changed from 1913513750 to 1913930645, `libs/ReactNativeSkia` from 1913513937 to 1913930649, while the generated `Package.swift` kept the same MD5. Recreating a package root that Xcode has already resolved is what produces the error above.

**Xcode's own bookkeeping made the sync run every time.** The "Sync SPM Autolinking" build phase re-syncs when a watched input looks newer than its stamp, and it checked each library's whole directory with `find <dir> -newer <stamp>`. Xcode writes its per-user scheme state inside that directory, at `<lib>/.swiftpm/xcode/xcuserdata/<user>.xcuserdatad/xcschemes/xcschememanagement.plist`. So Xcode's own write marked the next build stale, which triggered the destructive re-sync, which broke that build. `xcodebuild` does not write that file, which is why command-line builds were never affected.

This change makes the `libs/` tree idempotent — unchanged entries keep their inode, and entries that are no longer autolinked are pruned instead of wiped — and makes the staleness check skip `.swiftpm`.

### How to verify

In an app that autolinks a library shipping its own `Package.swift`, build in Xcode twice in a row. Both builds should succeed. Before this change the second build fails with `Missing package product`.

## Changelog:
[IOS][FIXED] - Stop SwiftPM autolinking from recreating library package roots on every sync, which broke Xcode builds of apps using libraries that ship their own Package.swift

Pull Request resolved: https://github.com/react/react-native/pull/58597

Test Plan:
**Unit tests.** `yarn test packages/react-native/scripts/spm` — 21 suites, 1009 tests pass.

New tests, written and seen failing before the fix:

- Two consecutive generation runs over an unchanged self-managed dependency keep both the `libs/` inode and each entry's inode. Failed before the fix with the same inode churn measured on the real app.
- A dependency removed between two runs leaves no symlink under `libs/`.
- The emitted staleness snippet is extracted from the generated script and executed under `/bin/bash -c` with `set -euo pipefail` against a temporary tree. A write under `.swiftpm/` is ignored; a real source change is still detected.

**Real app.** A React Native 0.87.1 app on Xcode 27 autolinking `shopify/react-native-skia` and `react-native-safe-area-context`, both self-managed. Before: `xcodebuild` succeeded, Xcode failed in about 5 seconds with the two errors above, on nearly every build.

**Not run:** the full CI matrix, and no Android-side check — this touches iOS SwiftPM tooling only.

## Scope

Deliberately minimal.

One case still re-syncs: the first time Xcode creates `.swiftpm` inside a library, that bumps the library directory's own mtime, so the build after a fresh checkout reports stale once per library. That is harmless now that the sync is idempotent.

One related item is left alone: the aggregate `Package.swift` is still rewritten on every sync even when its content is unchanged, which bumps its mtime and can make Xcode re-resolve. That is wasteful but not destructive, and it is no longer reached on an ordinary IDE build now that `.swiftpm` writes do not mark the sync stale.

Reviewed By: cipolleschi

Differential Revision: D120740029

Pulled By: shwanton

fbshipit-source-id: 3783d4cee4791ab13517d8f0dcac71f752cb7c1b
2026-09-22 06:57:35 -07:00
Jakub Piasecki 900b717e83 Update branching implementation to default to the JS thread merge (#58615)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58615

Changelog: [Internal]

The current behavior, merge on the main thread, is kept behind the new `enableFabricCommitBranchingMergeOnMainThread` flag.

Reviewed By: rubennorte

Differential Revision: D120981616

fbshipit-source-id: 47f00ddc150f154481cc908548f39662abf32cbf
2026-09-22 06:30:26 -07:00
Dawid Małecki b16845f69b Add umbrella for react/renderer/graphics subtree (#58373)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58373

Pull Request resolved: https://github.com/react/react-native/pull/58032

Rolls the umbrella-header + include-guard mechanism across the
`react/renderer/graphics` module, classifying the target as public.

- Adds `<React/Graphics.h>`, re-exporting the module's public interface headers.
- Adds `<react/cxxstableapi/UmbrellaGuard.h>` to 24 root headers and all 18
  platform headers.
- Wires the umbrella header directory into the Buck, CMake, CocoaPods, Gradle,
  and iOS prebuild header configurations.

`conversions.h` and `Geometry.h` are deliberately left unguarded. Both are
deprecation shims whose only content is a `#warning` redirecting to their
replacements.

`PlatformColorParser.h` and `fromRawValueShared.h` include
`react/renderer/core/RawValue.h`, which was only reachable on Apple platforms
because `react/renderer/core:rawValue` was restricted to `platforms = APPLE`.
No source inside the graphics target included those headers off-Apple, so the
breakage was latent and invisible; reaching them through the umbrella surfaces
it.

Changelog:
[Internal]

Reviewed By: javache

Differential Revision: D116779866

fbshipit-source-id: 22a118acc4b0fc2e19d1da605acd9ee926905cd5
2026-09-22 06:26:57 -07:00