Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58180
Classifies `jserrorhandler:jserrorhandler` as a "for frameworks" target under the C++ stable API three-tier visibility model. Adds `#include <react/cxxstableapi/FrameworksGuard.h>` to the module's three exported headers (`ErrorUtils.h`, `JsErrorHandler.h`, `StackTraceParser.h`), and wires the guard dependency into BUCK, CMake and CocoaPods.
Consumers that opt into `RN_STRICT_API` now get a warning if they include these headers directly, which they can acknowledge with `RN_ALLOW_FRAMEWORKS`; without that flag the guards are inert, so no existing build changes behaviour.
Changelog: [Internal]
Reviewed By: javache
Differential Revision: D117842041
fbshipit-source-id: dd3036c98f16d906bfb4a9909fb7707eb2802f4e
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58131
Classifies `devtoolsruntimesettings:devtoolsruntimesettings` as a private target under the C++ stable API three-tier visibility model. Adds `#include <react/cxxstableapi/PrivateGuard.h>` to the module's single exported header (`DevToolsRuntimeSettings.h`), and wires the guard dependency into BUCK and CMake.
The guards are inert unless a consumer defines `RN_STRICT_API`, so there is no behavior change.
Changelog: [Internal]
Reviewed By: cortinico
Differential Revision: D117328566
fbshipit-source-id: e63e8d1fb710b95ec96ce3f0227ab2f47ccbbd7a
Summary:
This adds an AI code review bot to React Native. It leaves a single comment on PRs with findings from three reviewers (correctness, security, consistency) and never blocks merging or auto-approves.
How it works:
- Config lives in `.expo-code-review/` — `config.jsonc`, shared prompts, and the three agent files. The model is `meta/muse-spark-1.2` (Muse Spark) using `META_API_KEY`.
- Three workflows: auto-review on `pull_request`, on-demand `/review` comment, and `/dismiss` to hide a finding. They check out the base commit and run the published `expo/code-review-cli` via `npx`, so PR code is never executed.
What changed:
- Added `.expo-code-review/` with the config and prompts
- Added `.github/workflows/expo-code-review.yml`, `expo-code-review-command.yml`, `expo-code-review-dismiss.yml`
The bot is wired but dormant until the `META_API_KEY` secret is set (from https://developer.meta.com/ai/, stored as `EXPO_CODE_REVIEW_API_KEY` and forwarded as `META_API_KEY`). It now only runs when you add the `ai-review` label.
## Changelog:
[INTERNAL] [ADDED] - Add expo/code-review-cli AI code review (Muse Spark)
Pull Request resolved: https://github.com/react/react-native/pull/58021
Test Plan:
Tested locally on `add-expo-code-review-muse-spark` (`Abbondanzo/react-native` fork):
```bash
npx --yes expo/code-review-cli init --token-env META_API_KEY
# set model to meta/muse-spark-1.2 in config.jsonc, workflows forward META_API_KEY from secrets.EXPO_CODE_REVIEW_API_KEY
ECR_EXPECTED_TOKEN_ENV=META_API_KEY ecr verify-config
# → OK — tokenEnv locked to META_API_KEY
ecr doctor
# → ✓ 3 agents (consistency, correctness, security), coordinator meta/muse-spark-1.2
ecr ref-check
# → 1 ref(s) across 6 files — all resolve
ecr review --json
# → correctly waits for META_API_KEY
```
CI is `continue-on-error` and `pull-requests: write` only. After the secret is set, adding `ai-review` on a PR triggers the review.
Reviewed By: zeyap
Differential Revision: D117580751
Pulled By: Abbondanzo
fbshipit-source-id: 9f6e5123b9d73d3f5cdf38c5f1fdabaec9a061c3
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58023
Classifies `jsc:JSCRuntime` as a for-frameworks target under the C++ stable API three-tier visibility model. Adds `#include <react/cxxstableapi/FrameworksGuard.h>` to the module's only header, `JSCRuntime.h`, and declares the guard dependency in BUCK. Consumers that opt into `RN_STRICT_API` now get a suppressible warning if they include it directly, silenced by defining `RN_ALLOW_FRAMEWORKS`; without that flag the guard is inert, so no existing build changes behaviour.
There is no CMake or podspec wiring to update — the module has no `CMakeLists.txt` and no podspec compiles it.
Changelog: [Internal]
Reviewed By: cortinico
Differential Revision: D116601629
fbshipit-source-id: adab5ed6974cac12eb140c452946f64311fc47d6
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58154
`sendIntent` is an Android-only Linking API. On iOS the JS layer never reaches
the native module at all — `Linking.sendIntent()` returns
`Promise.reject(new Error('Unsupported'))` for any non-Android platform, so the
exported ObjC method was unreachable. Its body was only
`RCTLogError(@"Not implemented: ...")`.
It is also absent from `NativeLinkingManagerSpec`, the codegen'd protocol
`RCTLinkingManager` conforms to, so a TurboModule call could not dispatch to it
either: only spec methods appear on `NativeLinkingManagerSpecJSI`. The
`sendIntent` declaration lives on the separate Android spec instead.
Removing the dead stub. No behaviour change — the JS-visible rejection on iOS is
produced in `Linking.js` and is untouched.
Changelog: [Internal]
Reviewed By: cipolleschi
Differential Revision: D117534390
fbshipit-source-id: 9050da88e0e7189962639c2b60b43bf4026bae22
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58150
Classifies `react/renderer/runtimescheduler:runtimescheduler` as a "for frameworks" target under the three-tier C++ stable API visibility model. Consumers that opt into `RN_STRICT_API` now get a warning if they include its headers directly, which they can acknowledge with `RN_ALLOW_FRAMEWORKS`; without that flag the guards are inert, so no existing build changes behaviour.
`RuntimeScheduler_Legacy.h` gets its guard above the `RCT_REMOVE_LEGACY_ARCH` block so it is still evaluated when the legacy architecture is compiled out.
Changelog: [Internal]
Reviewed By: cipolleschi
Differential Revision: D117508561
fbshipit-source-id: 0be49676974d950e3c9a2e1d9053ab0262555098
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58160
Pull Request resolved: https://github.com/react/react-native/pull/58053
Add `<React/Debug.h>` as the canonical public C++ entry point for React Native's debug assertion macros: `react_native_assert`, `react_native_expect`, and the `REACT_NATIVE_DEBUG` / `REACT_NATIVE_PRODUCTION` flags. Guard direct leaf-header inclusion for strict API consumers while preserving existing React Native builds and legacy include paths.
Classify the `redbox/` headers as private instead. They live in namespace `unstable_redbox`, have no consumers outside React Native, and are reachable only from three dev-menu `.mm` files, so they are fenced off with the private guard and deliberately left out of the umbrella.
Changelog:
[Internal]
Reviewed By: cipolleschi
Differential Revision: D116930195
fbshipit-source-id: 8942eed7fc41982dbf5ab4aa0d2466703db8a81e
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58159
Pull Request resolved: https://github.com/react/react-native/pull/58049
Add `<React/CallInvoker.h>` as the canonical public C++ entry point for `CallInvoker`, `NativeMethodCallInvoker`, and `SchedulerPriority`. Guard direct leaf-header inclusion for strict API consumers while preserving existing React Native builds and legacy include paths.
Export and stage the umbrella consistently through Buck, CMake, Android Prefab, CocoaPods, and the Apple prebuilt-header inventory. SwiftPM needs no change, since its header mapping for this module already preserves the directory structure.
The `ios-prebuild` header configuration needs an explicit entry here: the generic podspec parser only reads the first `header_dir`, so it would have flattened the umbrella into `ReactCommon/` and collided with the existing leaf header of the same basename.
Changelog:
[Internal]
Reviewed By: cipolleschi
Differential Revision: D116921026
fbshipit-source-id: 1838a18632f4493f22397bfebe44f38895cbfc7d
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58152
Two crashes can occur when a synchronous mount batch runs before its root view is attached. Both need the same bad state: a `ViewState` for a tag is present in `tagToViewState`, but its `view` field is null.
## Cause
A surface can render before its root view is attached. While the root view is not attached, `MountItemDispatcher.executeOrEnqueue` defers every mount item into `SurfaceMountingManager.onViewAttachMountItems`. The pull model does not defer one of them: `FabricUIManager.scheduleMountItem(synchronous = true)` calls `mountItem.execute()` directly.
That gives this sequence for a tag `T`:
1. **C++ claims the tag first.** `preallocateShadowView` puts `T` into `allocatedViewRegistry_`. It does this before it calls Java.
2. **Java does not create the view.** The `PreAllocateViewMountItem` for `T` is deferred, because `isWaitingForViewAttach` is true. No `ViewState` exists for `T`.
3. **C++ omits the Create instruction.** `executeMount` finds `T` in `allocatedViewTags`, so it does not add a Create for `T`.
4. **The mount batch runs too early.** The batch is not deferred, so it runs while the root view is still not attached. It has no Create for `T`, but it has an `UpdateEventEmitter`. `updateEventEmitter` calls `tagToViewState.getOrPut(T) { ViewState(T) }`, which makes a `ViewState` with a null `view`.
5. **The preallocation is cancelled.** The root view attaches and the deferred `PreAllocateViewMountItem` runs. `preallocateView` finds a `ViewState` for `T` and returns. `T` now has no view, and no Create will come.
The next `updateState` or `updateOverflowInset` for `T` throws.
## Fix
Apply the same attach barrier to the synchronous batch that every other mount item already obeys. If the root view is not attached, put the batch in the dispatcher queue instead of running it inline. The preallocations then run first, and the batch runs after the root view is attached.
Only `pullAndExecuteTransaction` passes `synchronous = true`, so the push model never reaches this path.
## Changelog:
[Android] [Fixed] - pull model mounting is now deferred until the root attaches
Reviewed By: zeyap
Differential Revision: D117519782
fbshipit-source-id: 5d5104eccbdd382b5be06417d6d31450ef86b697
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58133
Classifies `jsiexecutor:jsiexecutor` as a private target under the C++ stable API three-tier visibility model. Adds `#include <react/cxxstableapi/PrivateGuard.h>` to both exported headers (`JSIExecutor.h` and `JSINativeModules.h`), and wires the guard dependency into BUCK, CMake and the podspec.
The podspec needs no `USE_FRAMEWORKS` header search path edit: it already sets `HEADER_SEARCH_PATHS` to `"$(PODS_TARGET_SRCROOT)/.."` unconditionally, and that resolves to `ReactCommon`.
The guards are inert unless a consumer defines `RN_STRICT_API`, so there is no behavior change.
Changelog: [Internal]
Reviewed By: cipolleschi
Differential Revision: D117330790
fbshipit-source-id: 698a30cf536c4c4e6c6f61aed9afbc1267153c13
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58126
Classifies `react/renderer/observers/mutation:mutation` and `react/nativemodule/mutationobserver:mutationobserver` as private targets under the three-tier C++ stable API visibility model. Consumers that opt into `RN_STRICT_API` now get an error if they include their headers directly; without that flag the guards are inert, so no existing build changes behaviour.
Changelog: [Internal]
Reviewed By: christophpurrer
Differential Revision: D117326015
fbshipit-source-id: 8a9cfa85f9179c4c07ae8d5a6fe82dffdd37f5e5
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58147
On Android, React Native's Networking module fell back to OkHttp's default
User-Agent (okhttp/<version>) when no User-Agent was supplied, so requests
omitted the app name and version. iOS already includes this automatically via the
system networking stack.
This synthesizes a default User-Agent of "AppName/Version" (or just "AppName"
when no versionName is available) from the app's PackageManager, applied only
when no User-Agent is otherwise set. JS-supplied User-Agent headers still take
precedence.
Resolves https://github.com/react-native-community/discussions-and-proposals/issues/284
Changelog:
[Android][Added] - Send app name and version as the default `User-Agent` header for network requests, matching iOS
Reviewed By: cortinico
Differential Revision: D116705471
fbshipit-source-id: 91f919912fd30d11579f196a5260dc418f12c57b
Summary:
X-link: https://github.com/react/yoga/pull/2015
> [!NOTE]
> **This PR description is AI-generated.**
Fabric runs layout on candidate trees before taking the commit mutex, and concurrent commits share every unchanged subtree, so Yoga's pixel-grid rounding pass could write rounded positions and dimensions into the same shared `yoga::Node` from two threads at once. The layout pass itself never mutates nodes it does not own (`Node::cloneChildrenIfNeeded`), but `roundLayoutResultsToPixelGrid` recursed across the ownership frontier. I made the rounding recursion skip children whose owner is not the current node, mirroring the existing owner checks in `Node::cloneChildrenIfNeeded` and `YGNodeFreeRecursive`. The skipped writes had no reader: `YogaLayoutableShadowNode::layout` copies metrics only from children with `hasNewLayout` (asserting they are owned), `hasNewLayout` is set only on nodes the pass laid out, and the shadow nodes past the frontier are sealed, so their `LayoutMetrics` could not change in that commit anyway.
## Changelog:
[GENERAL] [FIXED] - Fix data race between concurrent Fabric commits in Yoga's pixel-grid rounding pass
Pull Request resolved: https://github.com/react/react-native/pull/58144
Test Plan: ThreadSanitizer reports of the race, from react-native-reanimated's sanitizer nightly (React commit on the JS thread racing a Reanimated commit on the main thread over a shared `ParagraphShadowNode`): https://github.com/software-mansion/react-native-reanimated/actions/runs/32811464205/job/97691453444
Reviewed By: christophpurrer
Differential Revision: D117688567
Pulled By: zeyap
fbshipit-source-id: 3f0662aee2ce865b4a13edffd46217f349a4285d
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58166
The screenshot baselines used by two Android RNTester flows were captured on the local CI emulator and have fixed pixel dimensions that do not match the Maestro Cloud device profile.
Tag those flows as local screenshot baselines and exclude that tag from the Android Maestro Cloud job. The existing local Android E2E job continues to run both flows and validate their screenshots.
Changelog: [Internal]
___
Differential Revision: D117687713
fbshipit-source-id: de7cb4c8b395f204d672f8a209a29ccaa6ab0226
Summary:
**Motivation**
Minimum infra fix to enable subsequently landing https://github.com/react/react-native/pull/57940.
Referencing `ReactNativeFeatureFlags` on the existing `react-native/react-private-interface` boundary is blocked by a gap in the `build-types` pipeline and a type translation error, addressed here.
**Changes**
- `simpleResolve.js`: Explicitly support `react-native/react-private-interface` as a special case, fixing resolution.
- `ReactNativeFeatureFlagsBase.js`: Tweak the `OverridesFor` type here to fix TypeScript translation compatibility, where the unconstrained `T` type param is now narrowed.
**Impact**
No change to the API snapshot (the `ReactNativeFeatureFlags` import is ultimately tree-shaken!), and no effect on generated types until https://github.com/react/react-native/issues/57940 lands.
Changelog: [Internal]
Pull Request resolved: https://github.com/react/react-native/pull/58075
Test Plan:
- `yarn build-types`
- Applied https://github.com/react/react-native/issues/57940 patch on top; both stayed green, no `types_generated/**/featureflags/**`
Reviewed By: GijsWeterings
Differential Revision: D117513265
Pulled By: cortinico
fbshipit-source-id: 348e8de3d622081fe0062ef939ce14c21af587a8
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58151
Run the release RNTester Maestro flows in Maestro Cloud for iOS and Android on pushes to main and same-repository pull requests. Reuse the existing build artifacts and read both the API key and project ID from repository secrets.
The existing local Maestro jobs remain unchanged because debug flows require a running bundler that is unavailable in Maestro Cloud.
Changelog: [Internal]
Reviewed By: cipolleschi
Differential Revision: D117513755
fbshipit-source-id: 78ad2b627783c2a750796a1c95648b00c913f350
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58125
Classifies `react/renderer/observers/intersection:intersection` and `react/nativemodule/intersectionobserver:intersectionobserver` as private targets under the three-tier C++ stable API visibility model. Consumers that opt into `RN_STRICT_API` now get an error if they include their headers directly; without that flag the guards are inert, so no existing build changes behaviour.
Changelog: [Internal]
Reviewed By: christophpurrer
Differential Revision: D117324071
fbshipit-source-id: 0ee34eea6ba8688da5f4e51b51d0e945ee295df8
Summary:
`codegenNativeComponent()` declared its return type as `NativeComponentType<Props>`. That alias lives in `Libraries/Utilities/codegenNativeComponent.js` and is not re-exported from the `react-native` root, and the package's `exports` map has no `./types_generated/*` subpath, so the deep specifier is not resolvable either.
As a result, any library that calls `codegenNativeComponent()` and emits declaration files fails to build under `moduleResolution: node16/nodenext/bundler` - TypeScript cannot name the inferred return type portably:
```
src/ReactNativeTestViewNativeComponent.ts:11:1 - error TS2883: The inferred type of 'default' cannot be named without a reference to 'NativeComponentType' from '../node_modules/react-native/types_generated/Libraries/Utilities/codegenNativeComponent'. This is likely not portable. A type annotation is necessary.
11 export default codegenNativeComponent<NativeProps>('ReactNativeTestView');
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```
This is the default `fabric-view` template from `create-react-native-library`, so every new Fabric view library hits it.
It used to work before RN 0.87.0, until https://github.com/react/react-native/issues/57490 has removed visibility of the internally exported types.
Example of breakage - this test run in `react-native-builder-bob`: https://github.com/callstack/react-native-builder-bob/actions/runs/32675382955/job/97282442650#step:19:20
### Fix
The fix is to declare the return type as `HostComponent<Props>` instead. `NativeComponentType<T>` is defined as `HostComponent<T>`, but only `HostComponent` is exported from root. Consumers can reach it via `import('react-native').HostComponent<Props>`.
## Changelog:
[GENERAL] [FIXED] - Fix TS2883 when building declaration files for libraries that use `codegenNativeComponent` due to unreachable `NativeComponentType<T>`
Pull Request resolved: https://github.com/react/react-native/pull/58102
Test Plan: Tested locally on a library generated with Bob.
Reviewed By: cipolleschi
Differential Revision: D117336232
Pulled By: fabriziocucci
fbshipit-source-id: 173fcfbc568cc4a8e79c32d16fbcee988db9b104
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58121
Classifies `react/renderer/observers/events:events` as a private target under the C++ stable API three-tier visibility model. Adds `#include <react/cxxstableapi/PrivateGuard.h>` to the module's only exported header (`EventPerformanceLogger.h`), and wires the guard dependency into BUCK and CMake. On iOS the module ships as the `React-Fabric/observers/events` subspec, and the parent `React-Fabric` spec already depends on `React-cxxstableapi` from an earlier migration, so no podspec change is needed.
`Scheduler.h` is a "for frameworks" header that still includes `EventPerformanceLogger.h`, so the module is not cleanly private until that include is replaced with a forward declaration. That change is in review separately (D116909093) and can land in either order relative to this one, since the guards are inert on their own.
The guards are inert unless a consumer defines `RN_STRICT_API`, so there is no behavior change.
Changelog: [Internal]
Reviewed By: christophpurrer
Differential Revision: D117320589
fbshipit-source-id: 4e17fb4d25b1a51b2c06391d77cbe071b01ac3ab
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58123
Classifies `react/nativemodule/webperformance:webperformance` as a private target under the C++ stable API three-tier visibility model. Adds `#include <react/cxxstableapi/PrivateGuard.h>` to the module's single exported header (`NativePerformance.h`), and wires the guard dependency into BUCK, CMake, and the podspec.
The guards are inert unless a consumer defines `RN_STRICT_API`, so there is no behavior change.
Changelog: [Internal]
Reviewed By: cortinico
Differential Revision: D117322371
fbshipit-source-id: e99c9d1f867a843da60f5166621cc7794dfbbe1e
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58138
`enableSchedulerDelegateInvalidation` gated a defensive invalidation token in
`Scheduler`: a `shared_ptr<atomic<bool>>` captured into every rendering-update
lambda, flipped on delegate swap and on `Scheduler` destruction, so a lambda
that outlived its captured raw delegate pointer would no-op instead of
dereferencing freed memory.
We are not keeping it. The dominant path into that race - a pending rendering
update draining after an uncaught error tore down the delegate - is now closed
upstream in `RuntimeScheduler_Modern::handleTaskError`, which clears the pending
task and rendering-update queues before the host error handler runs. That leaves
the token as a second mechanism guarding an already-closed window, at the cost
of an atomic allocation per delegate swap and a branch in every deferred
rendering update.
So the flag and the guard both go: the token, its reallocation in `setDelegate`,
the destructor flip, and the per-lambda `guardEnabled` capture are all removed,
returning `setDelegate` to a plain assignment.
The test suite keeps its coverage of the underlying race - teardown via both
`uiManagerDidFinishTransaction` and `uiManagerDidDispatchCommand`, plus the
assertion that surface unregistration alone does not drain pending updates - now
exercising the queue-clearing behaviour that actually closes it. The two tests
that differed only in the flag's value collapse into one.
One window is genuinely left open, and is now pinned by a new death test: a
delegate dropped and destroyed with no error involved never reaches
`handleTaskError`, so nothing clears the queue and the drained lambda
dereferences freed memory. Closing that properly needs a
runtime-scheduler-level shutdown signal rather than a per-`Scheduler` token.
Changelog: [Internal]
Reviewed By: christophpurrer
Differential Revision: D117328638
fbshipit-source-id: d01769dc269c420482b8271576c2332bd28ab116
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58132
Clearing the `RuntimeScheduler` queues before handling a task error is now the
default everywhere, so drop the flag and make the behaviour unconditional.
While removing the gate, one call site needed correcting. `updateRendering`
routed a throwing resize-observer callback through `handleTaskError`, which
clears the queues. That is wrong inside the "update the rendering" step: it
drops the pending rendering updates the step is about to drain, so a throwing
observer callback aborts the remaining steps - exactly what the call site's own
comment says must not happen. That path now reports the error without clearing.
Queue clearing stays on the task-execution and microtask-checkpoint paths, which
are the ones that unwind before the rest of the tick runs.
The two death tests in `SchedulerDelegateInvalidationTest` both reached the
use-after-free by way of an uncaught JS throw, which is now the very thing that
empties the queue before the delegate goes away - so they no longer die. Rather
than drop that coverage, one is retargeted to the trigger that still reaches the
race: a plain `setDelegate` swap followed by delegate destruction never runs
`handleTaskError`, so the queued lambda still dereferences freed memory. The
second was the same mechanism through the other lambda site and is dropped as
redundant; both sites keep their safe-path coverage.
Changelog: [Internal]
Reviewed By: christophpurrer
Differential Revision: D117324787
fbshipit-source-id: ffbb6e6370abdd635abf3366d1e6decb782458ac
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58008
Classifies `react/networking:networking` as a private target under the C++ stable API three-tier visibility model. Adds `#include <react/cxxstableapi/PrivateGuard.h>` to both of the module's exported headers (`NetworkReporter.h`, `NetworkTypes.h`), and wires the guard dependency into BUCK, CMake, and the podspec.
The guards are inert unless a consumer defines `RN_STRICT_API`, so there is no behavior change.
Changelog: [Internal]
Reviewed By: cortinico
Differential Revision: D116591313
fbshipit-source-id: 4d789b42df63b61db3951712d59cdb1f4b03f90c
Summary:
Stabilizes the Android RNTester E2E jobs after switching their APKs to ARM64 while continuing to run the emulator on an x86_64 host.
- Updates the Android wide-gamut screenshot baseline using the stable ARM64 result from the API 35 emulator. The emulator does not support wide color, so the Display-P3 fixture is converted to solid sRGB red.
- Marks the FlatList `maintainVisibleContentPosition` flows as Android release-only. These flows remain fully covered by the release APK, where they consistently pass, while avoiding debug-only timing failures caused by running the ARM64 debug runtime through native translation.
- Adds generic tag filtering to the Android Maestro runner and unit coverage for it.
Across seven post-migration `main` runs, the release APK passed every FlatList flow, while the debug APK consistently dropped or delayed Maestro interactions and skipped up to 172 frames during startup.
## Changelog:
[INTERNAL] [FIXED] - Stabilize Android RNTester E2E tests when running ARM64 APKs on x86_64 emulators.
Pull Request resolved: https://github.com/react/react-native/pull/58140
Test Plan:
- `./node_modules/.bin/jest .github/workflow-scripts/__tests__/maestro-android-test.js --runInBand --config='{"testEnvironment":"node","transform":{},"roots":["<rootDir>/.github/workflow-scripts"]}'` — passed (3 tests)
- `maestro 2.6.1 check-syntax` for all 24 tagged FlatList flows — passed
- Prettier check for all changed text files — passed
- `git diff --check` — passed
- Verified the filtered RNTester suite contains 16 debug flows and excludes 24 release-only FlatList MVCP flows
- Compared the new baseline against ARM64 CI screenshots: exact match for release; debug RMSE 0.0024
- Manually exercised the ARM64 release APK on an API 35 ARM64 emulator at 320×640: FlatList offsets progressed as expected (`500 → 544 → 2744 → 4944 → 7144`), and five rapid prepends reached `11500`
Related failing run: https://github.com/react/react-native/actions/runs/32821468795
Reviewed By: Abbondanzo
Differential Revision: D117361459
Pulled By: cortinico
fbshipit-source-id: 4514f8c42f7599c875672efe3c56aae7c9f0395c
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58129
The experiment for clearing the `RuntimeScheduler` queues before handling a task
error has run its course, so make the behaviour the default for everyone.
When a task throws, `RuntimeScheduler_Modern` now drops the pending task queue
and any pending rendering updates before invoking the host error handler. That
stops queued work from being executed against state the error handler is about
to tear down.
Turning this on for everyone exposed a bug in one of the call sites. A throwing
resize-observer callback was routed through `handleTaskError`, which clears the
queues - wrong inside the "update the rendering" step, because it drops the
pending rendering updates that same step is about to drain, so a throwing
observer callback aborts the remaining steps. That is exactly what the call
site's own comment says must not happen. That path now reports the error without
clearing. Queue clearing stays on the task-execution and microtask-checkpoint
paths, which are the ones that unwind before the rest of the tick runs.
The flag default flips to `true`, and the per-app runtime gates are removed so
every consumer picks up the default rather than an override.
Changelog:
[General][Changed] - `RuntimeScheduler` now clears pending tasks and rendering updates when a task throws
Reviewed By: christophpurrer
Differential Revision: D117322680
fbshipit-source-id: e47de49b0fbb240023f8ee25bdb111a19b50a5b1
Summary:
An app declares extra native modules through spm.modules in its react-native.config.js. Those names went into the generated package graph unvalidated, and two of the ways they can go wrong fail silently.
This PR fixes this by using the same Swift name collision detection/resolving as we introduced in https://github.com/react/react-native/issues/58044
> **NOTE:** https://github.com/react/react-native/issues/58044 must be merged before this one so that we can change the base branch for this one to `main`
## Changelog:
[IOS] [FIXED] - Reject colliding or invalid spm.modules names instead of silently dropping a module from the build
Pull Request resolved: https://github.com/react/react-native/pull/58060
Test Plan: ✅ Unit tests/CI
Reviewed By: mdvacca
Differential Revision: D117360298
Pulled By: cipolleschi
fbshipit-source-id: d2531d51b6d371cf6bc98dc85c9071ee81fb7a37
Summary:
A dependency's Swift name is derived from its npm package name with the scope dropped, which makes two collisions unavoidable: `powersync/react-native` derives `ReactNative`, one of React Native's own names, and `a/foo` and `b/foo` both derive `Foo`.
Either was emitted into the package graph as-is, and SwiftPM then failed deep inside dependency resolution with a duplicate-name error that named neither the library nor the react-native.config.js that caused it.
This was seen in the PR here https://github.com/powersync-ja/powersync-js/pull/1076 - and was hard to fix.
This PR fixes this by adding support for prefixing the name with the scope if the name without scope crashes.
In addition the same logic is added when two packages have names that collide with each other.
If the name given by the SwiftPM scaffolder doesn't work for you - you can use the `spm.name` field in the `react-native.config.js` file to set a specific name (see SwiftPM docs).
## Changelog:
[IOS] [FIXED] - Resolve Swift manifest naming collisions
Pull Request resolved: https://github.com/react/react-native/pull/58044
Test Plan: ✅ Unit tests green
Reviewed By: mdvacca, cortinico
Differential Revision: D117178818
Pulled By: cipolleschi
fbshipit-source-id: 23269f4d959b84ac484be1911e8a863c74008ff9
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58095
`RCTTestModule` is a TurboModule: it conforms to `NativeTestModuleSpec` and returns
`NativeTestModuleSpecJSI` from `getTurboModule:`, so JS->ObjC dispatch is driven by
codegen, not by `RCT_EXPORT_METHOD`'s `__rct_export__` metadata. The macro is dead weight.
Convert the three spec-declared methods to plain ObjC declarations; conformance to
`NativeTestModuleSpec` keeps their signatures compiler-enforced.
```
- (void)markTestCompleted;
- (void)markTestPassed:(BOOL)success;
- (void)verifySnapshot:(RCTResponseSenderBlock)callback;
```
`sendAppEvent:body:` keeps its macro because it is not declared in the spec protocol, and
the two `RCT_REMAP_METHOD` exports keep theirs because they define custom JS names.
Changelog: [Internal]
Reviewed By: cipolleschi
Differential Revision: D117201272
fbshipit-source-id: 38101da690d8267f8ac4291f9bfc14ab75fd45d3
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58135
Classifies `react/renderer/scheduler:scheduler` as a "for frameworks" target under the three-tier C++ stable API visibility model. Consumers that opt into `RN_STRICT_API` now get a warning if they include its headers directly, which they can acknowledge with `RN_ALLOW_FRAMEWORKS`; without that flag the guards are inert, so no existing build changes behaviour.
Changelog: [Internal]
Reviewed By: javache
Differential Revision: D116909091
fbshipit-source-id: 80692c74e44fa98a97fe42fd8485c3bc7babf4e1
Summary:
The GitHub release body generated by `createDraftRelease.js` labeled the last section **ReactNative Core dSYMs**, but the Maven URLs omitted the `dSYM-` classifier.
That made the links download the prebuilt `React.xcframework` tarball (`reactnative-core-debug.tar.gz` / `reactnative-core-release.tar.gz`) instead of the actual dSYMs (`reactnative-core-dSYM-debug.tar.gz` / `reactnative-core-dSYM-release.tar.gz`). Hermes and ReactNativeDependencies links already include `dSYM-`; Core did not.
This matches the classifier used when publishing Core dSYMs and the URL `rncore.rb` builds when `RCT_SYMBOLICATE_PREBUILT_FRAMEWORKS=1`.
Companion docs fix: https://github.com/reactwg/react-native-releases/pull/1394
## Changelog:
[INTERNAL][FIXED] - Point GitHub release Core dSYM links at the dSYM Maven artifacts instead of the framework tarballs
Pull Request resolved: https://github.com/react/react-native/pull/58114
Test Plan:
- Updated the expected strings in `.github/workflow-scripts/__tests__/createDraftRelease-test.js` to match the corrected URLs.
- Did not run Jest locally: a full `yarn install` in this monorepo rewrites `hermes-compiler` / `yarn.lock` via the preinstall hook.
- Confirmed the new URLs follow the same `dSYM-` classifier already used for ReactNativeDependencies in this template, and for Core dSYMs in `packages/react-native/scripts/cocoapods/rncore.rb` (`stable_tarball_url(..., dsyms = true)`).
Reviewed By: GijsWeterings
Differential Revision: D117330772
Pulled By: cipolleschi
fbshipit-source-id: 761f4b821a05f078ea9d1a9cb1882edca822a834
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58118
Classifies `react/nativemodule/defaults` as a private target under the three-tier C++ stable API visibility model. `DefaultTurboModules.h` now includes `<react/cxxstableapi/PrivateGuard.h>`, and the module picks up a dependency on the guard target so the include resolves for every build.
Changelog: [Internal]
Reviewed By: cortinico
Differential Revision: D116287984
fbshipit-source-id: c0018bba702b7885cd4acac744625c5e2d42dd35
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58026
Classifies `react/timing:timing` as a public target under the C++ stable API three-tier visibility model and introduces the module umbrella `React/Timing.h` as its public entry point.
Wires into all the environments that need it: the guard dependency and the umbrella glob in BUCK, `react_cxxstableapi` in CMake, a `React-cxxstableapi` dependency plus a `timingUmbrella` subspec in the podspec, a header-staging entry for the iOS prebuild, and a prefab export for Android. SwiftPM needs no change.
The guards are inert unless a consumer defines `RN_STRICT_API`, so there is no behavior change.
Changelog:
[General][Added] - Add `<React/Timing.h>` umbrella header as the public entry point for `react/timing`
Reviewed By: cipolleschi
Differential Revision: D116769152
fbshipit-source-id: 9a566e78851e7f3bce4e9d0ff03c728a6cf24fe4
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58094
`DevSupportHttpClient` derived its clients from the app's shared `OkHttpClient` with `newBuilder()`, which shares the underlying `Dispatcher` and `ConnectionPool`.
Dev support keeps several long-lived WebSockets open to the dev server — the packager connection and the inspector among them — and a WebSocket occupies a running-call slot for its entire lifetime, because `RealWebSocket.loopReader` runs inside `RealCall.AsyncCall.execute`. OkHttp allows five concurrent calls per host by default, so those sockets throttle, and eventually stall, every other request to the dev server: `BundleDownloader` fetching the bundle itself, `PackagerStatusCheck`, and any application request that happens to target the same host.
Give the devsupport clients a `Dispatcher` and a `ConnectionPool` of their own, still configured from the shared client so an `OkHttpClientFactory` override continues to apply. The per-host limit is raised on that dispatcher as well — without it the WebSockets would simply starve bundle traffic on the new dispatcher instead of the app's.
Changelog:
[Android][Fixed] - Stop dev server WebSockets from throttling bundle downloads and other dev server requests
Reviewed By: cortinico
Differential Revision: D117196401
fbshipit-source-id: 60f67c8ce6deb6045ac142e08cd8243ec0a1373d
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58055
Classifies `hermes/executor:executor` as a private target under the three-tier C++ stable API visibility model. Consumers that opt into `RN_STRICT_API` now get an error if they include its headers directly; without that flag the guards are inert, so no existing build changes behaviour. No podspec edit is needed — `React-hermes`, the pod that compiles this module, is already configured.
Changelog: [Internal]
Reviewed By: javache
Differential Revision: D116934196
fbshipit-source-id: b49408aa62d6e98bd45fe7d62de1770f59ac0c8b
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58096
This was added ages to serve an internal use-case and is a major security risk if left unguarded in production (D4650999 / S670581). It was never ported to iOS and a platform inconsistency.
Changelog: [Android][Changed] Removed FileIoHandler packager message handlers
(Not breaking since this is a devtooling-related API change: https://reactnative.dev/releases/versioning-policy#what-is-a-breaking-change)
Reviewed By: christophpurrer, cortinico
Differential Revision: D117176703
fbshipit-source-id: c79cb8d7758706b1871f81e72c6e356ae32ed6a9
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58086
Classifies `react/renderer/bridging:bridging` as a public target under the C++ stable API three-tier visibility model and introduces the module umbrella `React/RendererBridging.h` as its public entry point.
The umbrella is named `RendererBridging` rather than `Bridging` because all umbrellas share a single `React/` include namespace, and `React/Bridging.h` belongs to the separate `react/bridging` module.
The guards are inert unless a consumer defines `RN_STRICT_API`, so there is no behavior change.
Changelog:
[General][Added] - Add `<React/RendererBridging.h>` umbrella header as the public entry point for `react/renderer/bridging`
Reviewed By: cortinico
Differential Revision: D117179017
fbshipit-source-id: bd64c8c1093c8e50370c354d2c021d80f0046cc1
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58090
Classifies `react/renderer/leakchecker:leakchecker` as a private target under the three-tier C++ stable API visibility model. Consumers that opt into `RN_STRICT_API` now get an error if they include its headers; without that flag the guards are inert, so no existing build changes behaviour. The pod that ships the module, `React-Fabric`, already depends on `React-cxxstableapi` and is already marked as a React Native build, so no podspec change is needed.
Changelog: [Internal]
Reviewed By: cortinico
Differential Revision: D117188751
fbshipit-source-id: 61e8258ea4ab310640fbd9a85da7137a25333be9
Summary:
`NativeAnimatedAllowlist.h` carries this instruction:
```c++
/**
* Direct manipulation eligible styles allowed by the NativeAnimated JS
* implementation. Keep in sync with
* packages/react-native/Libraries/Animated/NativeAnimatedAllowlist.js
*/
```
It has drifted by one entry. `SUPPORTED_STYLES` in the JS file lists `filter` between `opacity` and `transform`; the C++ set goes straight from `"opacity"` to `"transform"`. Every other member of the JS list's non-layout half is present, so this is a missed sync rather than a deliberate exclusion.
The set is not advisory — it is what separates layout props from paint props:
```c++
// StyleAnimatedNode.cpp
bool isLayoutPropsUpdated(const folly::dynamic& props) {
for (const auto& styleNodeProp : props.items()) {
if (getDirectManipulationAllowlist().count(styleNodeProp.first.asString()) == 0u) {
return true; // absent => treated as a layout prop
}
}
return false;
}
```
and that verdict picks the transport:
```c++
// NativeAnimatedNodesManager.cpp
auto& current = layoutStyleUpdated
? updateViewPropsForBackend_[viewTag] // Fabric commit
: updateViewPropsDirectForBackend_[viewTag]; // direct manipulation
```
So animating `filter` runs a shadow-tree commit on every frame instead of taking the direct-manipulation path, for a property that cannot affect layout — `filter` lives in `BaseViewProps` (`std::vector<FilterFunction> filter{}`), not in `YogaStylableProps`, and nothing in `react/renderer/animated/` treats it specially.
Note the C++ set is deliberately *not* a mirror of the whole JS `SUPPORTED_STYLES`: the entries the JS file adds under `useSharedAnimatedBackend()` (`width`, `height`, `margin`, `padding`, `flex`, `gap`, …) are genuine layout props and must stay out so they keep going through Fabric. Only the non-layout half has to match, and `filter` belongs to it.
## Changelog:
[GENERAL] [FIXED] - Animating `filter` no longer forces a Fabric commit on every frame
Pull Request resolved: https://github.com/react/react-native/pull/58071
Test Plan:
Added `directManipulationAllowlistCoversNonLayoutStyles` to `AnimatedNodeTests`. It asserts the allowlist contains every non-layout style the JS file supports, and — so the test cannot be satisfied by simply widening the set — that the layout styles are still absent.
The allowlist header is dependency-free, so the invariant can also be checked directly:
```
$ c++ -std=c++20 -Wall -Wextra -I packages/react-native/ReactCommon allowcheck.cpp -o allowcheck
# before
MISSING from C++ allowlist: filter
checked 34 JS non-layout styles, missing=1 (exit 1)
# after
checked 34 JS non-layout styles, missing=0 (exit 0)
```
```
$ yarn jest packages/react-native/Libraries/Animated
Test Suites: 3 passed, 3 total
Tests: 66 passed, 66 total
$ node ./scripts/clang-format.js <both changed files>
(no changes)
```
`getDirectManipulationAllowlist` appears in the C++ API snapshots, but only by signature — this changes the contents of the static set, not the declaration, so `scripts/cxx-api` is unaffected.
The gtest itself was neither executed locally nor built by the public CI. `react/renderer/animated/tests` is excluded from the iOS build (`React-Fabric.podspec`: `ss.exclude_files = "react/renderer/animated/tests"`) and is not in the Android CMake glob (`react/renderer/animated/CMakeLists.txt` globs `*.cpp drivers/*.cpp event_drivers/*.cpp internal/*.cpp nodes/*.cpp`), so it builds only in the internal build reached at import time. What is verified here: the test body compiles clean against the real header under `-std=c++20 -Wall -Wextra`, and the standalone parity check above exercises the same assertions and fails without the one-line change.
Reviewed By: zeyap
Differential Revision: D117174629
Pulled By: javache
fbshipit-source-id: 5cfab73b61773df1b10ebc38bfb0a6c365e64fc0