Commit Graph
1588 Commits
Author SHA1 Message Date
Gijs Weterings c467843ed0 Fix DOMHighResTimeStamp round-trip truncation in timing primitives (#57975)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57975

`HighResDuration::fromDOMHighResTimeStamp` and `HighResTimeStamp::fromDOMHighResTimeStamp` converted milliseconds back to nanoseconds with `static_cast<int64_t>(units * 1e6)`, which truncates toward zero.

`toDOMHighResTimeStamp()` divides the nanosecond count by 1e6 (one rounding) and multiplying back by 1e6 rounds again, so the product frequently lands a hair below the original integer (e.g. `537648854729249.97`). Truncation then chops off a whole nanosecond, so `fromDOMHighResTimeStamp(toDOMHighResTimeStamp(x)) != x` for roughly 2% of random `now()` values.

That is the source of an intermittent `BridgingTest/highResTimeStampTest` failure, which reported:

```
Expected equality of these values:
  timestamp
    Which is: 8-byte object <22-02 00-21 FD-E8 01-00>
  bridging::fromJs<HighResTimeStamp>( rt, bridging::toJs(rt, timestamp), invoker)
    Which is: 8-byte object <21-02 00-21 FD-E8 01-00>
```

Round to the nearest nanosecond instead of truncating. Nanosecond values below 2^53 are exactly representable in a double, so the round trip is now exact for every value below 2.25e15 ns (26 days of monotonic clock); beyond that the double's ULP exceeds 0.5 ns and residual error is at most 2 ns, which is a floor of the DOM representation itself.

Rounding is also the correct semantic independently of the round trip — truncation gives a systematic downward bias and is asymmetric across zero, which affects the other callers (`RCTHighResTimeStampFromSeconds` for touch timestamps, `RuntimeTargetConsole` `console.timeStamp`, and `PerformanceTracer`).

The rounding is `std::llround`, which costs both overloads their `constexpr`: `<cmath>` rounding functions do not become usable in a constant expression until C++23 (P0533), and this header is compiled as C++20 everywhere (`-std=c++20` in `rn_defs.bzl`, `react-native-flags.cmake`, the podspecs and `Package.swift`). Both carry a `TODO` to restore `constexpr` once the C++23 rollout reaches them.

Dropping it is safe here. All 14 call sites are plain runtime calls — none is in a constant-expression context, none assigns to a `constexpr` variable or feeds a `static_assert` — and both functions are defined inside the class body, so they stay implicitly `inline` and neither linkage nor ABI changes. `fromDOMHighResTimeStamp` converts a `double` arriving from JS, so constant-evaluating it was never meaningful in the first place.

This does narrow the published API surface, so the C++ API snapshots are regenerated: the only change across all nine `.api` files is the `constexpr` keyword dropping off these two declarations, 18 lines in total.

`HighResTimeStamp::fromDOMHighResTimeStamp` now delegates to `HighResDuration`'s so there is a single implementation.

`highResTimeStampTest` previously asserted on `HighResTimeStamp::now()`, whose magnitude is host-uptime-dependent, so it only tripped the bug on about 2% of runs. It now round-trips five fixed nanosecond values (including the exact value from the failing run), which exercises the bug on every run. No test was skipped, disabled, or loosened.

Changelog:
[General][Fixed] - Round instead of truncate when converting a `DOMHighResTimeStamp` back to nanoseconds, so `HighResTimeStamp` and `HighResDuration` round trips are exact

Reviewed By: javache

Differential Revision: D116286868

fbshipit-source-id: 1adafd1b57b1185f51f08fa4dc55d96b88c176cd
2026-08-17 09:21:41 -07:00
Alex Hunt b74adf051f Add idle frame support to Performance timeline (#57952)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57952

Implement Idle frame spans in React Native DevTools, by emitting synthetic `NeedsBeginFrameChanged` + `BeginFrame` events.

**Definition**

An idle frame is emitted whenever the gap between two consecutive frames exceeds one vsync interval, derived from the display's refresh rate (`CADisplayLink.duration` on iOS, `Display.refreshRate` on Android, falling back to 60 Hz).

```
   frame N                  gap > 1 vsync                 frame N+1
+------------+  +--------------------------------+  +------------+
| BeginFrame |  | NeedsBeginFrameChanged         |  | BeginFrame |
| DrawFrame  |  | BeginFrame     (no DrawFrame)  |  | DrawFrame  |
+------------+  +--------------------------------+  +------------+
                    rendered as an "Idle frame"
```

**Implementation notes**

- Drop frames that begin before the recording start — Android `FrameMetrics` can deliver frames from app startup, and the first iOS `CADisplayLink` callback reports the previous vsync.
- Sort frames by begin timestamp before serializing, since async screenshot encoding can deliver them out of order and break gap detection.
- iOS: skip the frame event when the screenshot is unchanged, letting the gap render as an idle frame.

Changelog: [Internal]

Reviewed By: hoxyq

Differential Revision: D97502569

fbshipit-source-id: 7cb19e0a462ad878f0b44b66f6b5de3f76426ffe
2026-08-14 07:54:22 -07:00
artus9033 7bfe32fd33 Add SceneDelegate support (#57700)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57700

Add SceneDelegate lifecycle support to React Native iOS while retaining the AppDelegate path for backwards compatibility.

Update linking, window resolution, bootstrap APIs, RNTester, HelloWorld, and generated API snapshots for scene-based applications.

Changelog:
[iOS][Added] - Add SceneDelegate lifecycle support

Test Plan:
- `buck2 build --flagfile fbsource//fbobjc/mode/buck2/linux --config fbobjc.react_native_debug=development --flagfile fbsource//fbobjc/mode/iphonesimulator-arm64 --flagfile fbsource//fbobjc/mode/jest-coverage --config xplat.available_platforms=CXX,APPLE --config cxx.default_platform=iphonesimulator-arm64 --config user.sandcastle_build_mode=profile --config user.platform_flavor=iphonesimulator-arm64 //xplat/js/react-native-github/packages/rn-tester:RNTesterIOS`
- `xcodebuild -quiet -workspace RNTesterPods.xcworkspace -scheme RNTester -configuration Debug -destination "generic/platform=iOS Simulator" CODE_SIGNING_ALLOWED=NO build`
- `arc lint`
- Evaluate RNTester with the `RNTester` SceneDelegate scheme.
- Evaluate RNTester with the `RNTester (AppDelegate)` legacy scheme.
- Verify HelloWorld bootstrap and deep linking.

Reviewed By: cortinico, javache

Differential Revision: D113758228

Pulled By: cipolleschi

fbshipit-source-id: 31174c03a0936ca397fc1d061650fc0f582bdda7
2026-08-11 03:59:23 -07:00
Sam Zhou 727e87ed26 Fully replace hermes-(estree|parser|eslint|transform) packages with flow-* counterparts in react-native (#57851)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57851

The flow-* packages have support for all latest syntax and is better maintained.

Changelog: [Internal]

Reviewed By: huntie

Differential Revision: D115064040

fbshipit-source-id: 7265eb722910a460c76d0dbde0603cf962fe4e4e
2026-08-10 07:21:52 -07:00
Evan Katz 8415753e21 Add variable font settings support (#57815)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57815

Apply the existing `fontVariationSettings` text style prop when Fabric
constructs fonts on iOS. Parse CSS-compatible axis settings into CoreText
variation dictionaries while preserving absent, explicit-clear, and invalid
value semantics for nested text.

The parser supports quoted four-character OpenType tags and finite numeric
values, rejects malformed settings as a complete unit, and applies normalized
variations after the base font and feature settings are resolved. This shared
attributed-text path covers Fabric `Text` and `TextInput`.

Changelog:
[iOS][Added] - Add `fontVariationSettings` support for Fabric text

Reviewed By: Abbondanzo, christophpurrer

Differential Revision: D114121940

fbshipit-source-id: d2b2fffd4fe723c5205e5279a466a125aa7edd38
2026-08-09 17:09:10 -07:00
Evan Katz 19f7d144b9 Add Android text font variation settings (#57804)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57804

Add a `fontVariationSettings` text style prop and carry it through Fabric text attributes into Android text rendering. Android now deserializes the prop for `<Text>`, applies it to `Paint`, and includes it in text measurement cache identity because variable axes can affect layout.

Preserve the distinction between an absent setting and an explicitly empty setting so nested text can inherit or clear the parent variation axes. Apply high-level font properties before low-level variation settings so explicit axes take precedence, matching CSS font realization order.

Settings syntax is intentionally forwarded unchanged through common text attributes and validated only by the Android font variation parser. This avoids narrowing the grammar Android accepts. As a result, malformed child settings are outside the supported inheritance contract: they replace an inherited value before Android validation and are not guaranteed to fall back to the parent settings. Android also accepts `normal` and the React Native empty-string convention as explicit resets.

Changelog:
[Android][Added] - Add `fontVariationSettings` support for `<Text>`

Reviewed By: Abbondanzo, huntie

Differential Revision: D113580491

fbshipit-source-id: 46cea13ef5f06b33ed9f9d0b28b5c16f84193ea6
2026-08-09 17:09:10 -07:00
Pieter De Baets 85a81818c6 Avoid copying surface props when starting or updating a surface (#57813)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57813

`SurfaceHandler` already takes a throwaway snapshot of its `Parameters` under `parametersMutex_` before handing them to the `UIManager`, but `UIManager::startSurface` and `UIManager::setSurfaceProps` took `moduleName` and `props` by const reference and then copy-captured them into the lambda posted to the `RuntimeExecutor`. That forced a second deep copy of the props tree — which for a real surface holds the initial route params and deep link data — on every surface start, prop update, and display mode change.

Take both by value and move them into the lambda, and move at the `SurfaceHandler` call sites, so the snapshot is handed off instead of duplicated. The snapshot is a local that is dead after the call, so there is nothing left to observe the moved-from state.

Changelog:
[General][Changed] - `UIManager::startSurface` and `UIManager::setSurfaceProps` now take `moduleName` and `props` by value

Reviewed By: zeyap, christophpurrer

Differential Revision: D114730310

fbshipit-source-id: 7891f6ac61abda43ff0da5f4336741af6c329ed2
2026-08-07 06:08:23 -07:00
Tomasz Żelawski e2a4c68449 refactor(iOS): persist bundle as local file on par with Android (#57751)
Summary:
On Android, in development, the JS bundle is downloaded and saved as a file - this is done to avoid passing it through JNI, but iOS could use similar approach for uniform behavior.

This allows libraries to be able to obtain the bundle from the file without re-downloading it from Metro.

It would impact iOS boot slightly, but only in development, so it should be negligible.

## Changelog:

[IOS] [CHANGED] - make iOS preserve dev bundle as a temp file on par with Android implementation

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

Test Plan: rn-tester iOS dev works with this change

Reviewed By: cortinico, christophpurrer

Differential Revision: D114346244

Pulled By: coado

fbshipit-source-id: ebb4264fe8949cd766e71ca0363aa209a61370f7
2026-08-07 04:36:19 -07:00
Kamil Paradowski 5fb3ebce1a ArrayBuffer support to Java TurboModules
Summary:
Changelog:
[ANDROID] [ADDED] - Add ArrayBuffer support to Java TurboModules

- Codegen: ArrayBufferTypeAnnotation → ByteBuffer / ArrayBufferKind / Ljava/nio/ByteBuffer; in GenerateModuleJavaSpec and GenerateModuleJniCpp. Guard in Utils.js rejects Promise<ArrayBuffer> on Android at codegen time — drops async return to avoid CxxCallbackImpl.kt / JCallback / PromiseImpl.kt changes.

- Runtime: New JByteBufferMutableBuffer.h — jsi::MutableBuffer wrapping global_ref<JByteBuffer> direct ByteBuffer, holds Java object alive for JS ArrayBuffer lifetime; dtor uses ThreadScope to attach JNI thread (Hermes GC finalizes off-thread). Zero-copy native→JS return mirrors iOS NSMutableDataBuffer. Args JS→Java always copied into Java-owned direct ByteBuffer via allocateDirect+memcpy (mirrors iOS NSData copy), no sync/async branching — safe to retain/dispatch past GC.

- No changes to CxxCallbackImpl.kt, JCallback, PromiseImpl.kt. Nested ArrayBuffers still via folly::dynamic, deferred like ObjC/C++.

- Samples: NativeSampleTurboModule.js spec, SampleTurboModule.kt (getArrayBuffer/ createNativeBuffer/ processAsyncBuffer), RCTSampleTurboModule.mm. (NSData param / NSMutableData return), RNTester UI SampleTurboModuleExample.js.

X-link: https://github.com/facebook/react-native/pull/57062

Reviewed By: javache

Differential Revision: D107411163

Pulled By: christophpurrer

fbshipit-source-id: 67cc5da796a87f6918f0382debc5c5594f76661b
2026-08-06 12:28:37 -07:00
Christoph Purrer 3f3425e246 Remove unused NativeModalManager spec and all related code (#57806)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57806

Changelog: [INTERNAL]

Remove the dead `NativeModalManager` TurboModule spec and all its dependents — 13 files, 192 deletions across JS spec, Modal.js usage, native registration, CXX API snapshots, blocklist entries, and test mocks. The spec was never implemented and the Modal component no longer needs the event subscription pattern since transitioning to the new renderer.

Reviewed By: cortinico

Differential Revision: D114652881

fbshipit-source-id: af939c002d4d58c662bacb840c805d2dd4f42eb4
2026-08-06 10:20:45 -07:00
Hanno J. Gödecke f535c97904 fix(android): props 2.0 image tintColor=transparent broken (#57668)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57668

When enabling the props 2.0 feature flags I noticed that for an `<Image source={...} style={{ tintColor: 'transparent' }} />` the image is actually still showing, instead of becoming transparent.

### The underlying issue

All color props are defined as `SharedColor`, where a `SharedColor` has a default value of `0`:

https://github.com/facebook/react-native/blob/f3678f51d9873cb19602d7e36a4d8ed71562b9d0/packages/react-native/ReactCommon/react/renderer/graphics/platform/android/react/renderer/graphics/HostPlatformColor.h#L15-L18

https://github.com/facebook/react-native/blob/f3678f51d9873cb19602d7e36a4d8ed71562b9d0/packages/react-native/ReactCommon/react/renderer/graphics/Color.h#L30-L32

> [!NOTE]
> This is a bit confusing to me. `0` is not really an "undefined" color, but its actually "transparent". What we are really saying this way is that all color props have a default value of "transparent". The naming makes me unsure whether this has been intentional.

For other use cases, this seems to make sense. Ie. a user expects their text to have a background color of transparent/"nothing". However, we do not expect our image's tint color to have a default color of "transparent". This would hide all our images.

With props 2.0 we use the `getDiffProp` function, and when we pass `tintColor: 'transparent'` it will be passed to native as `tintColor: 0`. When we then compare the passed prop's value vs the default value here, it will not include the `tintColor`:

https://github.com/facebook/react-native/blob/f3678f51d9873cb19602d7e36a4d8ed71562b9d0/packages/react-native/ReactCommon/react/renderer/components/image/ImageProps.cpp#L249-L251

`tintColor` really is an optional color prop, and should be treated as such. The best fix I found was therefor making it really an `std::optional`. Let me know if you think otherwise!

## 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
-->

[ANDROID] [CHANGED] - ImageProps make `tintColor` an `std::optional` to support color `transparent` (`0`) with props 2.0

X-link: https://github.com/facebook/react-native/pull/55535

Test Plan:
- In the RNTester app change one of the Tint Color image examples to use tintColor of "transparent"
- The image should be invisible now as all visible pixels turned transparent
- Enable the props 2.0 feature flags
- Run the same example, notice that the tintColor has not been applied

Reviewed By: lenaic

Differential Revision: D93140534

Pulled By: coado

fbshipit-source-id: 0d8abf3583d87ad840b3f72603b4c29c775671ca
2026-07-31 13:49:09 -07:00
Rob Hogan fc365f6e72 Flow: Prefer imported types from @babel/types over global BabelNode* types (#57752)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57752

## Rationale
Flow lib defs that declare global types (available anywhere, without an `import`) must be referenced in `.flowconfig` and can't be maintained incrementally.  That's not too bad for very stable APIs and it's necessary for environment/runtime globals, but for 3P libraries it makes the lib defs much more difficult to maintain for little benefit (we have to import the runtime APIs anyway). Secondarily, it's a problem for generating TypeScript types, as TS doesn't declare any 3P library globally.

Babel is one of few cases where a library declares Flow globals - every one has an importable equivalent.

## This diff
Replaces usages of Babel global types across xplat/js with their `babel/types` equivalents

Changelog: [Internal]

Reviewed By: javache

Differential Revision: D113574665

fbshipit-source-id: be668d968345a60e76a3515d19d8eaa002d53274
2026-07-31 09:13:21 -07:00
Sam Zhou 7b5d1bc971 Switch over to flow-parser/babel-plugin for compilation (#57770)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57770

Changelog: [Internal]

Reviewed By: gkz

Differential Revision: D114240152

fbshipit-source-id: 7d292d33f75cf548b89e6427684fc3a5994c4b3f
2026-07-30 17:10:20 -07:00
Kamil Paradowski 55195ca43f Layout event emitter (#57722)
Summary:
> Stack 2/3 — parent: `feat/shadowTreeDidCommit`. Review that first.

`onLayout` events are emitted inline from `ShadowTree::emitLayoutEvents`, which forces `ShadowTree` to depend on `ViewProps` and `BaseViewEventEmitter`.

This moves that logic into a standalone `LayoutEventEmitter` that consumes the `shadowTreeDidCommit` hook (added in the parent PR) and is registered as a commit hook by `Scheduler`. Same filter (nodes with an `onLayout` prop), same timing (during commit), same `BaseViewEventEmitter::onLayout` call — behavior is unchanged.

After this, `ShadowTree` no longer references view props or event emitters, and the per-commit layout-change signal is shared with `ResizeObserver` instead of being duplicated.

## Changelog:

[INTERNAL] [CHANGED] - Emit `onLayout` from a `LayoutEventEmitter` commit hook instead of inline in `ShadowTree`

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

Test Plan: Behavior-preserving refactor. Existing `onLayout` tests pass and `ShadowTree` no longer includes `ViewShadowNode`/`ViewProps`. Verified in rn-tester that `onLayout` still fires on mount and on size changes.

Reviewed By: christophpurrer

Differential Revision: D114045065

Pulled By: javache

fbshipit-source-id: 5b887537ad3e947f3a352fb9dd10b7d124f669df
2026-07-30 11:44:31 -07:00
Kamil Paradowski e55da68478 Add new hook shadowTreeDidCommit (#57721)
Summary:
> Stack 1/3 — parent: `main`. Followed by `LayoutEventEmitter` → `ResizeObserver`.

`ShadowTree` already computes the set of nodes whose layout changed on every commit (`affectedLayoutableNodes`), but today it's only consumed internally by `ShadowTree::emitLayoutEvents`.

This adds a `shadowTreeDidCommit(shadowTree, rootShadowNode, affectedLayoutableNodes)` method to `ShadowTreeDelegate` and `UIManagerCommitHook` so other systems can react to layout changes after a commit. `ShadowTree` calls it once the new revision is installed, and `UIManager` forwards it to the registered commit hooks.

Both declarations have no-op defaults, so nothing observes the hook yet — this is inert on its own. It's the shared signal the next two PRs build on (extracting `onLayout` emission, and `ResizeObserver`), so neither has to re-derive which nodes changed layout.

## Changelog:

[INTERNAL] [ADDED] - Add `shadowTreeDidCommit` commit hook exposing the nodes with layout changes after each commit

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

Test Plan: No behavior change: the hook has no-op defaults and no consumer in this PR. Existing Fabric commit/mounting tests pass.

Reviewed By: mdvacca

Differential Revision: D114044722

Pulled By: javache

fbshipit-source-id: 2a556006f7b66a967aea5559cf10273c61aabcbe
2026-07-30 06:22:41 -07:00
Dawid Małecki 9da1a01153 Wire the Android pull model in C++ behind the feature flag (#57579)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57579

Makes `enableMountingCoordinatorPullModelAndroid` functional. With the flag on, the commit thread only signals transaction availability and the UI thread pulls and applies at mount time (matching iOS/macOS); with the flag off (default), behavior is byte-for-byte identical.
- `schedulerShouldRenderTransactions`: notifies via JNI (`FabricMountingManager::onTransactionAvailable`) instead of pulling and building the batch.
- `schedulerDidFinishTransaction`: no-op under the pull model.
- `FabricUIManagerBinding::pullAndExecuteTransaction` (new JNI method): pulls the surface's transaction on the UI thread and runs `executeMount`.
- `FabricMountingManager::executeMount`: gains a `synchronous` mode that executes the batch directly on the UI thread.
- The accumulation sites remain gated on `enableAccumulatedUpdatesInRawPropsAndroid`; the pull model requires that flag to be co-enabled, since a pull may collapse several commits into one diff and therefore needs complete accumulated rawProps.

## Changelog:
[Android] [Added] - Wire the pull-model mounting path in C++ behind `enableMountingCoordinatorPullModelAndroid`

Reviewed By: christophpurrer

Differential Revision: D112309053

fbshipit-source-id: 6e3ca5b8fbc8db647356ac555890c2e465890100
2026-07-29 08:01:12 -07:00
Nicola Corti a44d68ec6d Split Android build from release publishing (#57714)
Summary:
This should reduce the publishing time needed for `publish_react_native` by parallelizing Android & iOS build

## Changelog:

[INTERNAL] -

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

Test Plan: N/A

Reviewed By: cipolleschi

Differential Revision: D113889729

Pulled By: cortinico

fbshipit-source-id: aaa66a3cb9ce5c22bf15780503cf9a063c4b2725
2026-07-28 14:03:25 -07:00
Peter Abbondanzo 00e27b7322 PlatformColor lazy fallback: honor a raw-color fallback on Android (native) (#57655)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57655

An implementation for the RFC in https://github.com/react-native-community/discussions-and-proposals/pull/1008

Wires up the Android native color resolver (Fabric) to honor the lazy `{fallback}` carried by `PlatformColor(...)`. A later diff adds the JS argument that emits it, so on its own this change is a no-op for existing call sites.

To tell a genuine miss apart from a token that resolves to transparent black (ARGB 0):

- `FabricUIManager.getColor` now returns a boxed `Nullable Integer` — `null` means no resource path resolved. The Fabric C++ `PlatformColorParser.h` reads that boxed result over JNI, caches the explicit-miss signal, and on a miss parses the raw fallback string with the shared CSS color parser (`parseCSSProperty<CSSColor>`), matching the iOS Fabric path. The color object is now read as a `map<string, RawValue>` because it mixes an array (`resource_paths`) with an optional string (`fallback`).
- `NativeDrawable` carries an optional `colorFallback` alongside `resource_paths` so ripple drawables degrade to the fallback too.

Generated files (`ReactAndroid.api` and the `ReactAndroid*Cxx.api` snapshots) are regenerated to match the new public signatures.

Changelog:
[Internal] - PlatformColor: Android native support for a lazy raw-color fallback

Reviewed By: mdvacca, javache

Differential Revision: D113329136

fbshipit-source-id: ee15aea8dfed66364e99d427825e1b9ebcbdc483
2026-07-28 13:05:49 -07:00
Devan Buggay 2b992a0d4b Flush created animated nodes before handling events (#57656)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57656

Changelog: [Internal]

View event handlers can run synchronously before NativeAnimated nodes created on the async path have been flushed into the active graph. Flush pending async-created nodes on the render thread before evaluating view-driven animation events, so focus-driven animations can resolve their value nodes on the first native focus event instead of needing another runloop/event.

Reviewed By: zeyap

Differential Revision: D111257551

fbshipit-source-id: d5b7322cfce90b820ccf06422f1c830255bea3b3
2026-07-24 13:56:48 -07:00
Alex Hunt 0fc76bb527 Fix TS exactOptionalPropertyTypes compatibility for generated types (#57628)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57628

NOTE: Patches over a `flow-api-translator` bug, which I'll fix upstream later. We need to pick this to `0.87-stable` to resolve user integration issues.

**Context**

TypeScript's `exactOptionalPropertyTypes` flag (strict mode) creates a distinction between `foo?: T` and `foo?: T | undefined`.

```js
// Flow's semantics

interface Props {
  onRefresh?: () => void;
}
const a: Props = { onRefresh: undefined }; // ✅ ok
```
```ts
// TypeScript with exactOptionalPropertyTypes: true (i.e. strict mode)

interface Props {
  onRefresh?: () => void;
}
const a: Props = { onRefresh: undefined }; // ❌ error

interface PropsFixed {
  onRefresh?: (() => void) | undefined;
}
const b: PropsFixed = { onRefresh: undefined }; // ✅ ok
```

With this added strictness in TypeScript, our generated types via `flow-api-translator` could create downstream type incompatibility in apps.

**This diff**

Patches the above issue in React Native's Flow → TS `types_generated/` pipeline. We transform all instances to the wider `foo?: T | undefined` format, for maximum compatibility.

**Notes**

`foo?: T [| undefined]` **remains stripped** in the API snapshot (existing transform with the aim of a concise format). There is a net, nonfunctional snapshot diff around function members, which (as a positive result) are re-ordered.

Changelog:
[General][Fixed] - **Strict TypeScript API**: Optional property types are now widened to explicitly include `| undefined` for `exactOptionalPropertyTypes` compatibility

Reviewed By: cipolleschi

Differential Revision: D113030161

fbshipit-source-id: 3ab005edab6b80b18fbb9ae7125ba56e3bd94195
2026-07-22 04:50:50 -07:00
Riccardo Cipolleschi 60fac2e14d Fix post-release workflow failures (#57627)
Summary:
Fixes the three post-release failures from the [0.87.0-rc.2 publish run](https://github.com/react/react-native/actions/runs/29775529785/):

- Keep Flow annotations in `verifyArtifactsAreOnMaven.js` as comments so `actions/github-script` can load the file with plain Node.
- Pin the Podfile lock workflow to `macos-15`, which provides the configured Xcode 16.4 version.
- Use the canonical `react/react-native` owner for release asset API operations so upload POST requests are not redirected from the former owner.

## Changelog:

[INTERNAL] [FIXED] - Fix post-release Maven verification, Podfile lock, and release asset jobs

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

Test Plan:
```sh
node --check .github/workflow-scripts/verifyArtifactsAreOnMaven.js
node --check scripts/releases/upload-release-assets-for-dotslash.js
yarn jest .github/workflow-scripts/__tests__/verifyArtifactsAreOnMaven-test.js scripts/releases/__tests__/upload-release-assets-for-dotslash-test.js --runInBand
```

13 tests and 15 snapshots pass.

Reviewed By: zeyap

Differential Revision: D113032768

Pulled By: cipolleschi

fbshipit-source-id: df5f493603e6c25157fd7660b54aa409dcb742e7
2026-07-21 09:31:58 -07:00
Alex Hunt 89300acb9c Migrate Node.js builtin imports to node: scheme (#57611)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57611

Directly follows D112733139 (Metro).

**Motivation**

- New Node builtins are *only* available under the prefix (e.g. `node:sqlite`), as this allows Node to introduce them without ecosystem-breaking changes, so this is the direction of travel and the only choice that'll allow consistency.
- Encouraging them and grouping them separately makes it easier to reason about a module's 3rd party dependencies.

Changelog: [Internal]

Reviewed By: robhogan

Differential Revision: D112803684

fbshipit-source-id: 40668d746a7151b3aa4800ff8af997902a18d198
2026-07-21 09:01:41 -07:00
Christian Falch 38611186f5 fix(iOS): make jsinspector-modern tracing state types move-only for Swift C++ interop (#57605)
Summary:
The nightly-tests job `[ios] react-native-unistyles` fails on Xcode 26.3 with:

```
error: no matching function for call to '__construct_at'
note: in instantiation of member function 'std::vector<...RuntimeSamplingProfile>::vector' requested here
note: in implicit copy constructor for 'facebook::react::jsinspector_modern::tracing::TraceRecordingState' first required here
```

while compiling the **Swift** files of the Unistyles pod. The same failure hits any library built with Swift C++ interop (`-cxx-interoperability-mode=default`) — in practice, every Nitro-based library — against the prebuilt React Native core.

### The error

`TraceRecordingState` and `HostTracingProfile` hold `std::vector`s of move-only types (`RuntimeSamplingProfile` and `FrameTimingSequence` explicitly delete their copy constructors). Here's the C++ subtlety: `std::vector<T>`'s copy constructor is **declared for every `T`** — it only becomes ill-formed when *instantiated*. So the implicit copy constructors of these two structs are not implicitly deleted; they exist as declared-but-broken constructors that hard-error the moment anything asks for a copy.

### Why React Native compiles fine today

Nothing in RN ever asks. Every usage passes these types by reference; the single constructions move. A pure C++ (or ObjC++) build never instantiates the implicit copy constructors, so this code has always compiled — and always would, no matter how much C++ CI you throw at it. The defect is unobservable from within C++.

### What fails, and why now

The prebuilt-core headers now ship as real clang modules. A Swift target with C++ interop imports them (directly or transitively — e.g. via a module member whose `#ifdef __cplusplus` body opens because interop builds modules with C++ enabled), and Swift's ClangImporter surfaces the C++ value types to Swift as copyable. When the consumer's generated interop code then uses such a type as a Swift value — for a Nitro-based library, the nitrogen-generated `*_cxx.swift` bridging does exactly this — the compiler **synthesizes a copy of the type, instantiating the ill-formed implicit copy constructor**. That is the "ask" that plain C++ never makes; on Xcode 26.3 it hard-errors the entire module import, killing every Swift file in the consumer. (Newer Swift toolchains treat such types as non-copyable instead of failing.)

Before the prebuilt-modules work there was no Swift-visible module containing these headers, so no interop consumer ever imported these types — which is why this surfaces now despite the C++ being unchanged.

We deliberately did **not** fix this by removing headers from the module maps: the guarded-C++-in-modules pattern is shared by ~30 legitimately modular headers and is benign in all but this one shape, and experiments showed the type is reachable through multiple independent module surfaces (removing one member just moved the error to the next path).

### The fix

Declare the truth: make both types explicitly move-only.

```cpp
TraceRecordingState(const TraceRecordingState &) = delete;
TraceRecordingState &operator=(const TraceRecordingState &) = delete;
TraceRecordingState(TraceRecordingState &&) = default;
TraceRecordingState &operator=(TraceRecordingState &&) = default;
```

With the copy constructor explicitly deleted, Swift's importer sees a non-copyable type and imports it as such instead of instantiating a broken copy. It is also simply more correct C++: these types were never copyable in practice, and the explicit deletion turns any future accidental copy into a clear compile error at the call site instead of a template backtrace.

Declaring special members makes `HostTracingProfile` a non-aggregate, so its one designated-initializer construction site (`HostTargetTraceRecording.cpp`) is converted to member-wise assignment.

A sweep of the affected header surface (`std::vector`/`std::map`/`std::deque` of move-only element types) found exactly these two types; a follow-up adds a `headers-verify.js` gate that imports the shipped modules under Swift C++ interop at prebuild time, so the next type with this shape fails RN's own CI instead of community nightlies.

## Changelog:

[IOS] [FIXED] - Fix Swift C++-interop build failure (implicit copy constructor of TraceRecordingState/HostTracingProfile) for libraries using cxx interop with prebuilt React Native core

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

Test Plan:
On a fresh RN-nightly app with stock `react-native-unistyles@3.3.0` + `react-native-nitro-modules`, prebuilt core (`RCT_USE_RN_DEP=1 RCT_USE_PREBUILT_RNCORE=1`), Xcode 26.3:

- **Red**: stock headers reproduce the CI failure exactly (`__construct_at` → `TraceRecordingState`). Fixing only `TraceRecordingState` then surfaces the identical failure on `HostTracingProfile` — confirming the shape, not the type, is the bug.
- **Green**: with both headers fixed (stock module maps, nothing else changed): BUILD SUCCEEDED — zero `__construct_at`, zero `shadowNodeFromValue`, zero module errors.
- All RN-internal usages audited: references and moves only; no behavior change. Plain C++/ObjC++ compilation unaffected by construction.

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

Reviewed By: fabriziocucci

Differential Revision: D112802806

Pulled By: cipolleschi

fbshipit-source-id: d2ae201c1fbb4de040f51ebc88263c7347b5979b
2026-07-21 03:45:29 -07:00
artus9033 566c7ac2d1 fix: stabilize CXX API generator on MacOS, make parser indempotent for nested enums (#57536)
Summary:
Fixes C++ API snapshot generation failures for nested enums and macOS/Linux output drift due to platform-dependent behavior, in the CXX API generator.

### Problems

1. Duplicate enums: Doxygen parses codegen `EventEmitters.h` twice (direct codegen input + again via `.mm` includes). The parser raised `RuntimeError: Identifier OnOrientationChangeOrientation already exists in scope ModalHostViewEventEmitter` on `ReactApple*` views.

2. Inconsistent behaviour on MacOS vs Linux:
  - for codegen component aliases (`ConcreteComponentDescriptor`, `ConcreteViewShadowNode`), macOS Doxygen emits hybrid XML definitions (`typedef Type Name = Type`) while Linux CI emits `using Name = Type`. The parser keyed off `definition.startswith("typedef")`, so identical source produced different `.api` output per platform.
  - `CASE_SENSE_NAMES = SYSTEM` follows the host OS default (case-insensitive on macOS, case-sensitive on Linux), causing inconsistent symbol resolution.

### Resolution

- `.doxygen.config.template` files: set `CASE_SENSE_NAMES = YES` for deterministic name matching across macOS and Linux.
- `snapshot.py`: `create_enum()` returns an existing enum scope instead of raising when the enum is already registered.
- `builders.py`: `create_enum_scope()` to skip enums that already exist; `get_typedef_member()` to normalize Doxygen’s `typedef ... = ...` form to `using` so the output format is unified.

## Changelog:

[INTERNAL] [FIXED] - Fix C++ API snapshot generation crash on duplicate codegen enums
[INTERNAL] [FIXED] - Fix platform-dependent inconsistent CXX API generator output

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

Test Plan:
- [x] `yarn cxx-api-build` completes on macOS (tested locally)
- [x] `yarn cxx-api-validate` passes (tested locally on MacOS & on the Linux CI)
- [x] `validate-cxx-api-snapshots` passes on Linux (tested on CI)

Reviewed By: j-piasecki

Differential Revision: D112793182

Pulled By: coado

fbshipit-source-id: ada818451fb1207d965c1bed4fb5ce23ee2fe00f
2026-07-20 05:01:24 -07:00
Alex Hunt 9f7af3e088 Clean up network inspection feature flags (#57577)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57577

Network Inspection has been Stage 4 / rolled out since 0.83. Circle back to remove feature flags from the codebase.

**Changes**

- Remove `enableNetworkEventReporting` and `fuseboxNetworkInspectionEnabled` flag definitions.
- Remove all feature guards in code.
- Update tests (add mocks).
- (fbsource) Remove all overrides.

Changelog: [Internal]

Reviewed By: cortinico

Differential Revision: D111696522

fbshipit-source-id: 4c6ba9a6d5abf2770b9b485556602059d1c24b59
2026-07-16 10:17:17 -07:00
Christian Falch 6aa147f6c9 feat(iOS): ReactNativeDependenciesHeaders sidecar + pure-RN ReactNativeHeaders, published to Maven (#57442)
Summary:
Step 2 of the prebuilt-deps roadmap: ship the deps headers as a **SwiftPM-ready, self-contained artifact** and make every header namespace have exactly **one physical home**.

1. **New artifact: `ReactNativeDependenciesHeaders.xcframework`** — the binary `ReactNativeDependencies.xcframework` is framework-type, so its root `Headers/` is invisible to SwiftPM binaryTargets (`HeadersPath` is rejected on framework entries; verified empirically). The deps prebuild now emits a headers-only library-type sidecar (stub archives + per-slice `Headers/` + `HeadersPath` — the exact `ReactNativeHeaders` recipe, factored into a shared `headers-xcframework.js` emitter) carrying all seven deps namespaces incl. SocketRocket, with slice parity derived from the binary artifact's Info.plist. Ships inside the deps tarball *and* standalone.

2. **`ReactNativeHeaders` goes pure-RN** — the R2 relocation of deps namespaces (and the `DEPS_NAMESPACES_NOT_RELOCATED` SocketRocket exclusion list) is deleted. Relocated copies are what enabled the SocketRocket dual-copy regression (duplicate `interface` / poisoned module graph under `use_frameworks!`); that bug class is now structurally impossible. Headers gate flipped: deps namespaces must be **absent** from RNH; the sidecar emitter enforces set-equality with `DEPS_NAMESPACES` fail-closed in both directions. On the CocoaPods side, a new `ReactNativeDependenciesUtils.configure_aggregate_xcconfig` injects the deps pod's `Headers/` globally (aggregate + every pod target), mirroring the rncore injection — this replaces the folly/glog resolution pods previously got via the flattened `React-Core-prebuilt/Headers`.

3. **CI: prebuilt + dynamic-frameworks lane** — the regression's exact config had no coverage (the `test-ios-rntester` action hard-coupled `use-frameworks:true` to source builds). New `use-prebuilds` input; `test_ios_rntester`'s dynamic cells now consume the workflow-built prebuilt artifacts.

4. **Maven publishing** — `ReactNativeHeaders` and `ReactNativeDependenciesHeaders` publish standalone on `react-native-artifacts` (classifiers `reactnative-headers-*`, `reactnative-dependencies-headers-*`); `verifyArtifactsAreOnMaven` now HEAD-checks every classifier tarball instead of only the POM.

Stacked on https://github.com/react/react-native/issues/57440. The SwiftPM preview (https://github.com/react/react-native/issues/57332) rebases on top and wires the sidecar as its 5th binaryTarget.

## Changelog:

[IOS] [CHANGED] - Prebuilt artifacts: ReactNativeHeaders is pure-RN; third-party deps headers ship in the new ReactNativeDependenciesHeaders.xcframework sidecar (and the ReactNativeDependencies pod), published standalone to Maven

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

Test Plan:
- Headers gate: include-health, structural (deps absent from RNH, byte-matched module maps), and compile smokes (React module + 14 namespace modules + Expo-shape ObjC++/Swift fixtures vs the deps include path) — ALL PASSED
- jest: 33/33 (`scripts/ios-prebuild/__tests__`, incl. new sidecar set-equality tests)
- ESLint (`--max-warnings 0`), Prettier, Flow (`yarn flow-check`): clean
- E2E (locally built artifacts): rn-tester prebuilt static ✅, prebuilt `USE_FRAMEWORKS=dynamic` ✅ (the regression config — verified `React-Core-prebuilt/Headers` contains no deps namespaces and the deps pod serves all seven), helloworld static ✅, source-core + prebuilt-deps ✅ (React compiled from source resolves folly via the deps pod), source-mode control with unchanged dependency graph ✅
- Sidecar inspected: per-slice `HeadersPath`, 7 namespaces, slice parity with the binary
- Publication validated end-to-end with `publishReleasePublicationToMavenLocal`: all 12 files + POM land with the expected classifier names

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

Reviewed By: fabriziocucci

Differential Revision: D111449462

Pulled By: cipolleschi

fbshipit-source-id: e1217d14c0588d00a207622d346c9e6f4705a95d
2026-07-15 05:08:52 -07:00
Christian Falch a8156acf8b feat(iOS): serve third-party deps from the prebuilt ReactNativeDependencies pod via dependency-only facades (#57440)
Summary:
Step 1 of making the prebuilt `ReactNativeDependencies` pod the **single header authority** for the third-party C/C++ deps (RCT-Folly, glog, boost, DoubleConversion, fmt, fast_float, SocketRocket) in prebuilt-deps mode.

Today the deps **binary** replaces the source pods' code, but the pod still `s.dependency`'s the real source pods and borrows their headers via `$(PODS_ROOT)/<pod>` search paths. That split header authority is the dual-copy bug class behind the 2026-07-03 SocketRocket regression (`duplicate interface` under `use_frameworks!` — SocketRocket's ObjC headers have no include guards).

Three commits:

1. **fix(cocoapods): harden prebuilt-deps header search paths and artifact handling** — `rndependencies.rb`'s `||= [] << path` only added the deps header search path when `HEADER_SEARCH_PATHS` was unset (silently dropped otherwise); normalize and always append, and point at the pod-local flattened `Headers/`. `ReactNativeDependencies.podspec` `prepare_command` now fails closed (`exit 1`) instead of silently producing a no-link pod. `reactNativeDependencies.js` no longer deletes + re-downloads a locally staged artifact that lacks a version marker.

2. **feat(cocoapods): dependency-only facades for third-party pods in prebuilt-deps mode** — in prebuilt-deps mode the real source pods are not declared, so a community podspec's hardcoded `s.dependency "RCT-Folly"` would resolve from trunk and compile from source next to the prebuilt binary. `RNDepsFacades` generates dependency-only local facade podspecs (no sources, no headers, a single dependency on `ReactNativeDependencies`); versions/subspecs are derived from the real podspecs in `third-party-podspecs/` (SocketRocket synthesized fail-closed from `socket_rocket_config`). Full contract documented in `scripts/cocoapods/__docs__/prebuilt-deps.md`.

3. **feat(ios-prebuild): SocketRocket privacy manifest + Xcode 26 header layout** — embed an RN-authored, accurate-empty `PrivacyInfo.xcprivacy` for SocketRocket (upstream ships none), and stage flat public headers into `include/` so Xcode 26's SwiftPM accepts the header layout.

Stacked on https://github.com/react/react-native/issues/57305 (base: `chrfalch/prebuilt-resources`); the SwiftPM preview (https://github.com/react/react-native/issues/57332) rebases on top of this. Follow-up (separate PR): headers-only `ReactNativeDependenciesHeaders.xcframework` sidecar so SPM auto-serves the deps namespaces and `ReactNativeHeaders` goes pure-RN.

## Changelog:

[IOS][CHANGED] - Prebuilt-deps mode: serve third-party headers from the ReactNativeDependencies pod itself and resolve community `s.dependency` on RCT-Folly/glog/boost/etc. via dependency-only facade pods

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

Test Plan:
E2E matrix (2026-07-06, locally built deps artifact via `prepare-ios-prebuilds.js`):

- rn-tester, prebuilt core + prebuilt deps, static linkage — builds
- rn-tester, prebuilt core + prebuilt deps, `USE_FRAMEWORKS=dynamic` — builds (the SocketRocket-regression config)
- helloworld (private), prebuilt core + prebuilt deps, static — builds
- source-mode control: no facades generated, `Podfile.lock` identical to baseline

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

Reviewed By: fabriziocucci

Differential Revision: D111449257

Pulled By: cipolleschi

fbshipit-source-id: ace5716868d126a08721200efd640e903b191658
2026-07-15 05:08:52 -07:00
Alex Hunt cfd0e359a6 Add CDP support for WebSocket events (Android) (#57541)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57541

**Context**

This stack implements WebSocket event debugging for the Network panel in React Native DevTools.

**This diff**

Follows the iOS implementation: reports the same six `Network.webSocket*` CDP events through the shared `NetworkReporter` C++ core, gated behind the same `fuseboxWebSocketEventsEnabled` feature flag.

**Changes**

- `InspectorNetworkReporter` + `JInspectorNetworkReporter`: New JNI-backed `reportWebSocket*` methods bridging to the shared `NetworkReporter` C++ core. Payload conversion costs (base64) are deferred until a debugger is attached.
- `WebSocketModule`: Reports connection lifecycle, real handshake headers (from the OkHttp `Request`/`Response`), and sent/received messages, gated behind the same feature flags as iOS.

Changelog: [Internal]

Reviewed By: GijsWeterings

Differential Revision: D111561994

fbshipit-source-id: 735ad0e47fc4e9e943b1092fbc23846ff9baf963
2026-07-15 03:50:39 -07:00
Alex Hunt 020512bf15 Add CDP support for WebSocket events (iOS) (#57543)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57543

**Context**

This stack implements WebSocket event debugging for the Network panel in React Native DevTools.

Discussed with Expo earlier this year, we want upstream parity before Expo adopts the 1P Network panel. This is a comparatively small surface: 6 CDP events, no CDP methods.

**Minimum goal**: Parity with Expo's current WS event coverage. We improve on this with Request Initiator support in D111561995.

**This diff**

Adds first-party reporting for six of the seven WebSocket CDP events (`webSocketCreated`, `webSocketWillSendHandshakeRequest`, `webSocketHandshakeResponseReceived`, `webSocketFrameSent`, `webSocketFrameReceived`, `webSocketClosed`), mirroring the layering of the existing HTTP pipeline:

- **C++ core**: WebSocket CDP types and reporting APIs through `CdpNetwork` → `NetworkHandler` → `NetworkReporter`. Compiled to no-ops in production builds; inert unless the Network domain is enabled.
- **iOS**: A new `RCTInspectorWebSocketReporter` bridges `RCTWebSocketModule` to `NetworkReporter`, reporting connection lifecycle, real handshake headers, and sent/received messages. Android follows separately.
- **Gating**: A new `fuseboxWebSocketEventsEnabled` feature flag (experimentation, default off), checked alongside `enableNetworkEventReporting`.

**Notes**

- **Omitted**: [`Network.webSocketFrameError`](https://chromedevtools.github.io/devtools-protocol/tot/Network/#event-webSocketFrameError). Neither SocketRocket nor OkHttp exposes a frame-scoped error; connection failures are terminal and already reported via `webSocketClosed`. Cheap to bolt on once a genuine per-message error source exists (e.g. OkHttp `send()` returning false).
- **Omitted**: Optional [`WebSocketResponse`](https://chromedevtools.github.io/devtools-protocol/tot/Network/#type-WebSocketResponse) fields (`headersText`, `requestHeaders`, `requestHeadersText`) — we report structured headers only; raw handshake text isn't available from OkHttp on Android.
- No `performance-timeline` integration — WebSocket events report to CDP only; unlike HTTP, there is no `PerformanceResourceTiming` counterpart.

**Rollout plan** (New `enableNetworkEventReporting` flag)

- 0.88 - Canary channel
- 0.89 - Stable channel

Changelog: [Internal]

Reviewed By: GijsWeterings, javache

Differential Revision: D111561998

fbshipit-source-id: ecd46ddb6baa91f1c1d77598ee62b2e410b45bd9
2026-07-15 03:50:39 -07:00
Zeya Peng 2dfdcbf082 Fix local release testing: publish with --tag for prerelease versions (#57552)
Summary:
`scripts/e2e/init-project-e2e.js` publishes in-repo packages to the local Verdaccio proxy with `npm publish`, but omits `--tag`. **npm ≥ 11** (bundled with Node 24+) refuses to publish a prerelease version (e.g. `0.87.0-rc.0`) without an explicit tag:

```
npm error You must specify a tag using --tag when publishing a prerelease version.
```

This breaks `yarn test-release-local` immediately at the publish step on any machine using npm ≥ 11.

## Fix

Pass an explicit `--tag react-native-e2e`. This is a throwaway local registry and the install step pins the **exact** version, so the dist-tag value is not significant for resolution.

## Changelog

[Internal] - Fix `test-release-local` publishing on npm ≥ 11

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

Test Plan: `yarn test-release-local -t RNTestProject -p iOS` now gets past the publish step on npm 11 (previously failed immediately at `npm publish`).

Reviewed By: christophpurrer

Differential Revision: D111995913

Pulled By: zeyap

fbshipit-source-id: 107a96d5c4317129228f783ad52bffe1578d1138
2026-07-15 00:33:49 -07:00
Alex Hunt 042833e699 Extend check-packages-test to validate additional required fields (#57510)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57510

Extend `check-packages-test.js` to catch two more classes of manifest drift: published packages missing required fields, and packages under `private/` missing the `private` flag.

**Motivation**

Inspired by https://github.com/react-native-community/template/pull/241 — avoid a missing field blocking a future RN package publish.

**Other changes**

- To satisfy the new `files` requirement, add an explicit `files` allowlist to the four config packages that lacked one. As a side effect, this saves some `__tests__`  files from being distributed.

Changelog: [Internal]

Reviewed By: cortinico

Differential Revision: D111471314

fbshipit-source-id: e13082d2282128936e22e3a7580b5e434c3b41b2
2026-07-10 12:27:14 -07:00
Alex Hunt 0ed6c560da Consolidate package checks into one Jest test (#57509)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57509

Simplify/unify various mechanisms for the monorepo's package invariants.

These checks were previously scattered:
- `private/monorepo-tests` package (manifest field checks)
- `.github/workflow-scripts/lint_files.sh` (`.npmignore` ban)
- `react-native/eslint-plugin-monorepo` (manifest field checks — duplicated)

This folds everything into `scripts/monorepo-tests/__tests__/check-packages-test.js`. A plain Jest test is the most extensible home for future checks.

Changelog: [Internal]

Reviewed By: cortinico

Differential Revision: D111471313

fbshipit-source-id: ea50abd8148d92e70605dd7f809654348e3c0080
2026-07-10 12:27:14 -07:00
Alex Hunt c948b61c05 Enable Strict TS API by default (#57490)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57490

See [**RFC0894: Removing deep imports from react-native**](https://github.com/react-native-community/discussions-and-proposals/pull/894)

This is the **big switch** to enable the Strict TypeScript API (generated types + single index entry point) by default in React Native.

**Opt-in → opt-out**

After this change, the main `react-native` package resolves its `"types"` entry points only to `types_generated/index.d.ts` — with no other subpaths available.

The new `"react-native-legacy-deep-imports"` condition maps to legacy `types/` and `Libraries/*.d.ts` sources.

**Impact limitation**: For this stage of rollout, the `"default"` condition continues to resolve to source files. Only TypeScript is affected.

**How to opt out**

Opposite of today's opt-in, which we will update in [the docs](https://reactnative.dev/docs/strict-typescript-api). Again, the only impact area today is **TypeScript**.

```json5
// tsconfig.json
{
  "extends": "react-native/typescript-config",
  "compilerOptions": {
    ...
    "customConditions": ["react-native-legacy-deep-imports"]
  }
}
```

**Other changes**

- Drop `react-native/typescript-config/strict` entry point, update README.
- Update `__typetests__`.

**Rollout plan**

**Target release: 0.87**. This and the contributing stack will be cherry picked for RC1.

- We've conducted testing against 100+ real Expo codebases, giving us the confidence that we've reduced breaking changes enough that the vast majority of RN codebases can migrate.
- The Strict API includes a number of **intentional breaking changes**, and docs have been kept up to date.
- We're shipping a `/migrate-to-strict-api` skill to migrate via agents, see https://github.com/react-native-community/skills/pull/3.

**What's improved since 0.80?**

Since the initial opt-in launch of the Strict API in 0.80, we've been making continuous improvements over the last year to get our generated types into a widely launchable state.

Most notably:

- 21+ new/updated root APIs and fixes due to community feedback ([discussion](https://github.com/react-native-community/discussions-and-proposals/discussions/893), [PRs](https://github.com/react/react-native/pulls?q=is%3Apr%20label%3A%22JS%20API%20stabilization%20(1.0)%22%20is%3Aclosed)).
- Upstream encapsulation blocker in TypeScript, fixed in 6.0 (https://github.com/react/react-native/issues/53565).
- Tailwind/Uniwind compatibility (`interface` types for props).
- `*Instance` ref type exports for all built-in components (https://github.com/react-native-community/discussions-and-proposals/pull/1003).
- Fixes to previously mistyped, high impact APIs, such as `Appearance`.
- New subpath entry points for `asset-registry`, `setup-env`, and others.
- Refinements to doc comments/type translation build.

**Rollback plan**

Revert this diff.

IMPORTANT: We'll adopt a policy of **super-eager rollback**, if there are any unsolvable issues during the RC phase.

Changelog:
[General][Breaking] - React Native's default JavaScript API is now the [Strict TypeScript API](https://reactnative.dev/docs/strict-typescript-api). Use `customConditions: ["react-native-legacy-deep-imports"]` to opt out.

Reviewed By: cortinico

Differential Revision: D110458670

fbshipit-source-id: 4b0e0b458a5f895f783d6d936e7b11ccff2df076
2026-07-10 09:28:17 -07:00
Alex Hunt 6cfde8f296 Move AssetRegistry implementation into main package, expose as public API (#57369)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57369

**Problem**

The separate `react-native/assets-registry` package includes a longstanding ecosystem footgun.

`registry.js` holds asset state in a module-scoped variable, which makes the package a stateful singleton: exactly one instance must exist per JS runtime, or registration and lookup diverge.

We provide no guarantee that this singleton requirement holds:

- The install layout — how the package manager dedupes packages in `node_modules` — decides how many copies exist, and `react-native`'s exact-version pin means third-party ranges never dedupe against it.

Effects:

- **Consumers silently break**: `expo-asset` and `expo-image` can land on a second copy: assets register in one, resolve as `undefined` from the other. Expo neutralizes this with a shim in `expo/cli` that redirects every registry import to a single virtual module — bare React Native + Metro has no such protection.
- **This blocks 1.0**: The ecosystem can't move from exact-version lockstep to semver ranges until stateful packages like the asset registry are safe to duplicate. Today, relaxing the pin would turn a latent footgun into a common one.

**To solve this**, move towards (but not quite yet) deleting `react-native/assets-registry`, in favour of a replacement `AssetRegistry` API offered directly by `react-native`.

**Key changes**

NOTE: **Reviewer note**: Browsing file changes on GitHub may be more focused — https://github.com/react/react-native/pull/57369/changes

NOTE: Squash of https://github.com/react/react-native/pull/57233 (D108750302) and https://github.com/react/react-native/pull/57232 (D108750303)

`'react-native'`:
- Add new `AssetRegistry` API, along with the `PackagerAsset` and `AssetDestPathResolver` root type exports in `react-native`.
- Add a new `'react-native/asset-registry'` secondary entry point — intended for Metro's `transformer.assetRegistryPath` config contract.

`react-native/assets-registry`:
- Update to source from this relocated implementation — fixing the duplicate install layout bug (where apps/frameworks enforce a single copy of `react-native`).

**Impact**

- **✅ Fixed**: Imports from either `react-native` or `react-native/assets-registry` in RN 0.87+ will be durable to duplicate package installs — Expo can remove their virtual module shim.
- **✅ Fixed**: Deep import `'react-native/Libraries/Image/AssetRegistry'` dependency removed (migrated in `react-native/metro-config`).

Changelog:
- [General][Fixed] - **assets-registry**: `react-native/assets-registry` now shares state across duplicate installs, sourcing from a relocated implementation in the `react-native` package
- [General][Added] - Add `AssetRegistry` API (replaces `react-native/assets-registry/registry`)
- [General][Breaking] - `react-native/Libraries/Image/AssetRegistry` is removed. Please use the `AssetRegistry` API (apps/library code) and/or the `react-native/asset-registry` entrypoint (Metro/build configs).

Reviewed By: robhogan

Differential Revision: D109019622

fbshipit-source-id: 75599a94a9aba084a1266f2128c448379d1596cd
2026-07-06 10:32:14 -07:00
Pieter De Baets 07816cba56 Move ErrorUtils from cxxreact to jserrorhandler (#57236)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57236

Move `handleJSError` from `cxxreact/ErrorUtils.h` (header-inline) to `jserrorhandler/ErrorUtils.{h,cpp}` (declared + linked). Inverts the cyclic dep so `jserrorhandler` becomes a standalone leaf and `cxxreact:bridge` can be narrowed out of more consumers in follow-ups.

The old `<cxxreact/ErrorUtils.h>` include path continues to work via a deprecated `#warning` forwarder header that includes the new location. `cxxreact:bridge` now depends on `jserrorhandler:jserrorhandler` so existing consumers of the deprecated path still link cleanly. `jserrorhandler/BUCK` drops its `cxxreact:bridge` dep (and the matching `React-cxxreact` podspec entry).

Changelog:
[Internal]

Reviewed By: christophpurrer

Differential Revision: D108786498

fbshipit-source-id: 6a34ec47665558ac9c91343253e027ed1df70e93
2026-07-06 07:43:37 -07:00
Pieter De Baets c1d8ae970d Route enableCppPropsIteratorSetter through a copy ctor + RawProps::forEachItem (#57328)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57328

Today the iterator-setter path in `ConcreteComponentDescriptor::cloneProps` runs three sequential walks over the input — `RawProps::parse(parser)` (builds `keyIndexToValueIndex_` for `convertRawProp`), `static_cast<folly::dynamic>(rawProps)` (materializes a `folly::dynamic` via `jsi::dynamicFromValue` in JSI mode), and then `dynamic.items()` to dispatch `setProp`. Only the third is actually used: `convertRawProp` is never called on the iterator-setter branch, and the `folly::dynamic` materialization exists only as iteration scaffolding.

Restructure so the runtime flag picks one of two construction paths up front:

- **Iterator-setter** — copy-construct from `sourceProps` via the (re-enabled) `Props` copy ctor, then walk `rawProps` in-place via the new `RawProps::forEachItem` helper and route each entry through `setProp`. `parse()` is skipped entirely; the `folly::dynamic` materialization is skipped in `Mode::JSI`.
- **Classic** — unchanged: `parse()` + 3-arg `convertRawProp`-driven ctor.

`forEachItem` switches on `RawProps::Mode`:
- `Mode::JSI` — walks `value_.asObject(*runtime_).getPropertyNames(...)` and constructs `RawValue` from each `jsi::Value` directly, no `folly::dynamic` in between.
- `Mode::Dynamic` — iterates `dynamic_.items()` (same as today).
- `Mode::Empty` — no-op.

A new `HasIteratorSetterCtor<T>` concept (`std::copy_constructible<T>`) documents the contract and feeds a `static_assert` in `cloneProps`, so a future Props type that deletes its copy ctor fails at compile time rather than silently diverging at runtime between the two flag states.

The `RN_SERIALIZABLE_STATE` Props 2.0 accumulation branch keeps its existing dynamic-iteration shape — when `fallbackToDynamicRawPropsAccumulation` is true, `initializeDynamicProps` has already merged the source's rawProps with the input onto `shadowNodeProps->rawProps`, so we iterate that merged dynamic rather than the raw input.

The per-field `flag ? sourceProps.X : convertRawProp(...)` ternaries across every Props .cpp file become dead in the flag-on path (the copy ctor handles those fields) but are still functional in the flag-off path. They get removed in a follow-up cleanup; this diff is structurally non-breaking on either flag state.

Changelog:
[Internal]

Reviewed By: zeyap

Differential Revision: D109568749

fbshipit-source-id: eae20478418a7dbf7364c73d85d7694d99f1e8f1
2026-07-06 06:52:39 -07:00
Pieter De Baets 803456d699 Optimize MapBuffer representation (#57361)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57361

Broadens the former header-shrink change into a single representation-optimization commit for MapBuffer. It bundles three layout optimizations that were previously split: (1) the header is reduced to a single 2-byte `count` field; (2) multi-byte values are read via `memcpy` so unaligned access is well-defined on all platforms; (3) every dynamic-data entry (`String`, `Map`, `MapBufferList`, `IntBuffer`, `DoubleBuffer`) packs its `[offset][byteLength]` into the bucket's 8-byte value instead of writing an in-band length prefix into the dynamic data section.

Net effect: 4 fewer bytes per dynamic entry, one fewer indirection on read (the length is already in the bucket), and every dynamic entry becomes self-delimiting from its bucket alone. No public API change — only the internal serialized representation.

Changelog: [Internal]

landed-with-radar-review

Reviewed By: lenaic, zeyap

Differential Revision: D109848478

fbshipit-source-id: 30749aaa1c2d9fc9b1f8684a3b67815ef44632e8
2026-07-03 01:41:41 -07:00
Pieter De Baets 6a957746f6 Add MapBufferList entry type to MapBuffer (#57360)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57360

Introduces a dedicated `MapBufferList` `DataType` for an ordered array of nested MapBuffers, instead of overloading the `Map` type for lists. This makes a list of MapBuffers self-describing and distinguishable from a single nested `Map` (they were byte-distinct in payload but previously shared the `Map` type tag). Updates the C++ builder (`putMapBufferList`), the Kotlin `MapBuffer` interface, `ReadableMapBuffer`, and `WritableMapBuffer`, and adds cross-language JNI round-trip coverage in the serialization instrumentation test.

Changelog:
[Android][Added] - Add a dedicated `MapBufferList` type to `MapBuffer` for ordered lists of nested `MapBuffer`s

landed-with-radar-review

Reviewed By: zeyap

Differential Revision: D109848477

fbshipit-source-id: 7f590d5999d0cc4ee2d9d28cc34ae9220e442e18
2026-07-03 01:41:41 -07:00
Pieter De Baets e7cadaf9f3 Add IntBuffer and DoubleBuffer entry types to MapBuffer (#57359)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57359

Adds two new MapBuffer entry types, `IntBuffer` and `DoubleBuffer`, for storing homogeneous arrays of ints and doubles compactly in the dynamic data section. Unlike `Map` / map lists, these carry no per-element key/type overhead: a batch of N values costs ~N*elementSize bytes plus a single 4-byte count prefix instead of N 12-byte buckets. The bucket value holds the offset of the array within the dynamic data section.

Covers the full surface: the C++ reader (`MapBuffer::getIntBuffer` / `getDoubleBuffer`), the C++ builder (`MapBufferBuilder::putIntBuffer` / `putDoubleBuffer`), and the Kotlin reader API (`MapBuffer.getIntBuffer` / `getDoubleBuffer`, `Entry.intBufferValue` / `doubleBufferValue`). The `DataType` enum gains `IntBuffer = 6` and `DoubleBuffer = 7`, kept in sync across C++ and Kotlin.

Changelog:
[General][Added] - Add `IntBuffer` and `DoubleBuffer` entry types to MapBuffer for compact homogeneous int/double arrays

landed-with-radar-review

Reviewed By: zeyap

Differential Revision: D109848476

fbshipit-source-id: f9e86b7c094dea796d9a8b725e53eb948c1390ca
2026-07-03 01:41:41 -07:00
Mathieu Acthernoene 6b45e579d6 Remove StatusBar deprecated props / methods (#57392)
Summary:
Removes long-deprecated `StatusBar` APIs that no longer do anything:

- Android: `backgroundColor` / `translucent` props and `setBackgroundColor()` / `setTranslucent()` (no effect under edge-to-edge, deprecated since 0.76).
- iOS: `networkActivityIndicatorVisible` prop and `setNetworkActivityIndicatorVisible()` (unsupported since iOS 13, deprecated since 0.77).

Also removes the now-unused native backing (`setColor`/`setTranslucent` Android, `setNetworkActivityIndicatorVisible` iOS, Android `DEFAULT_BACKGROUND_COLOR`).

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

## Changelog:

[GENERAL] [BREAKING] - Remove deprecated `StatusBar` `backgroundColor` / `translucent` / `networkActivityIndicatorVisible` props and `setBackgroundColor` / `setTranslucent` / `setNetworkActivityIndicatorVisible` methods

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

Test Plan:
- `yarn flow check` — passes
- `yarn jest StatusBar` — passes
- `yarn test-typescript` — passes

Reviewed By: Abbondanzo, javache

Differential Revision: D110304943

Pulled By: cortinico

fbshipit-source-id: f7383c6bbbf8fd40042195ef7064b32692940499
2026-07-02 05:41:55 -07:00
Alex Hunt 642273788b Improve preservation of doc comments during type translation (#57389)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57389

**Context**

Strict TypeScript API readiness: High quality inline docs should reach users via TypeScript in their IDEs.

**This diff**

Prior iterations of our Flow → TS translation stack dropped doc comments for default-exported values, and/or identifiers which change shape after type transformation (e.g. Flow `component` syntax), meaning many root APIs (`View`, `ScrollView`, `Pressable`, and others) showed no documentation on hover.

This diff extends the existing `reattachDocComments` transform to handle doc comment repositioning (suitable for the TS lang server) from a greater set of source positions:

- the exported declaration
- a `.displayName` assignment
- a HOC-wrapped inner component
- a renamed wrapper's public-named component
- a `declare const` / `declare export default typeof X` stub

**Impact**

(With the source code JSDoc improvements earlier in this stack.)

| Before (legacy types) | After (Strict API) |
| -- |
|  {F1991869487}  | {F1991869472}  |
| ⚠️ No inline docs for many symbols | ✅ New, detailed inline docs reach the TS server 🎉 |

Changelog:
[General][Fixed] - Preserve doc comments on root API symbols in the generated TypeScript types

Reviewed By: rubennorte

Differential Revision: D109316361

fbshipit-source-id: 8a83455fcf317f355bd7c5a67712d322248d8b00
2026-07-02 03:09:52 -07:00
Gang Zhao f482ab61d9 Implement IEventLoopControl in RuntimeScheduler (#57403)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57403

Make `RuntimeScheduler` implement `IEventLoopControl`.
Wire `ReactInstance` to register that scheduler on Hermes
runtimes that expose `ISetEventLoopControl`.
Clear the pointer during teardown before `RuntimeScheduler`
is destroyed.
Regenerate React Native C++ API snapshots for the public
header change.

Only the modern scheduler have the actual implementation, it's no-op
in the legacy scheduler.

Changelog: [Internal]

Reviewed By: javache

Differential Revision: D106744175

fbshipit-source-id: 90eb17ce8dbc929b5f2474e019de07ad28d9c21d
2026-07-01 16:39:48 -07:00
Bartlomiej Bloniarz 721b1cfcac Drive shared animation backend from Fabric frame callback (#57400)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57400

In this diff we drop the custom choreographer for the backend on Android and instead plug into the one in `FabricUIManager`. This reduces the area for possible mistakes, makes it clearer how Fabric interacts with animation on a per-frame basis, and simplifies the flow around invalidation and cleanup of the React instance.

The crash this is meant to avoid comes from having two separate frame callback lifecycles. The old `AnimationBackendChoreographer` owned a self-reposting callback that could keep driving `FabricUIManagerBinding.driveAnimationBackend` independently from Fabric's own lifecycle. During React instance teardown, `FabricUIManager.invalidate()` pauses Fabric's frame callback and then unregisters the native binding. If a separate backend callback survives that sequence, it can invoke the binding after the native side has been uninstalled.

The shared animation backend is now driven from Fabric's existing `DISPATCH_UI` frame callback after mount items are dispatched. The Android `AnimationChoreographer` implementation only owns backend pause/resume state and conditionally forwards active frames to the shared backend.

Threading-wise:
- If invalidation happens before a frame starts, `mDestroyed` makes the frame no-op.
- If invalidation races with an already-running frame, `ReactChoreographer.removeFrameCallback` is serialized with callback execution via the `callbackQueues` monitor, so `onHostPause()` waits for the current `DISPATCH_UI` callback to finish before `unregister()` tears down the native binding.
- If the frame reposts itself in `schedule()`, the blocked removal observes and removes that callback before teardown continues.

Changelog:
[Android][Fixed] - Drive the shared animation backend from Fabric's frame callback during React instance teardown

Reviewed By: javache, zeyap

Differential Revision: D110321362

fbshipit-source-id: 77c462ee30aeec2d3af0dcd48b8eed15846ae5da
2026-07-01 14:44:05 -07:00
OrfeasZ 923e7ddcaf Add guards around nativeProps usage to prevent race conditions (#52646)
Summary:
Some third-party libraries, like react-native-reanimated, can clone nodes in a different thread while react-native is calling `setNativeProps_DEPRECATED`. This results in a race condition, where a stale pointer to `nativeProps_DEPRECATED` can be accessed, resulting in a crash. This usually manifests as a `EXC_BAD_ACCESS` crash on iOS. On Android it seems more rare. We've added a lock around accesses to nativeProps_DEPRECATED, but alternative options of fixing this can be considered too.

For more information see https://github.com/software-mansion/react-native-reanimated/issues/7666

## Changelog:

[INTERNAL] [FIXED] - Fixed crashes caused by race conditions when third-party libraries clone the shadow dom from a different thread

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

Test Plan:
Due to this being a race condition that only manifests in rare circumstances, it's very difficult to create a reliable reproduction case. The issue mentioned above contains ThreadSanitizer logs that demonstrate this issue. TSan no longer complains with this patch applied, and we've not seen any additional issues from it after deploying it in production over the past week.

Added unit test covering the `nativeProps_DEPRECATED` merge logic in `UIManager::cloneNode` and `ShadowNode::clone`:

```
buck2 test //xplat/js/react-native-github/packages/react-native/ReactCommon/react/renderer/uimanager:tests -- --regex FabricUIManagerTest
```

Reviewed By: zeyap

Differential Revision: D110169424

Pulled By: javache

fbshipit-source-id: 6139253dcc2c33348a0c1a3bd01e695d15aa83bc
2026-07-01 13:01:48 -07:00
Graham Campbell d1c5ee0388 Fix native animated mount flash (#57391)
Summary:
The C++ native animated backend (`cxxNativeAnimatedEnabled`) prevents the `useNativeDriver` first-frame flash by having `AnimatedMountingOverrideDelegate` re-merge a view's live animated props (`getManagedProps`) onto mount `Update` mutations, so a stale JS re-render can't reach the screen. There is a residual at connect time: `connectAnimatedNodeToView` registers the view (the override starts overriding it) but never runs the props node, so `getManagedProps()` returns an empty object until the next animation frame. If a Fabric mount transaction is pulled in that window the override has nothing to merge and the un-driven default value flashes for one frame, most visibly when a brand-new view is connected to an already mid-flight shared `Animated.Value`.

This seeds the props node with `node->update()` at the end of `connectAnimatedNodeToView` so `getManagedProps()` is live the instant the view becomes managed. No manager mutex is held at that point and `update()` takes only the node-local props mutex, so it is lock-safe; it is idempotent with the per-frame update and adds no extra Fabric commit because it only stages. It closes the connect-while-`Update`-in-flight case and mitigates the brand-new-view (`Insert`) first-paint case; the override only rewrites `Update`/`Delete` mutations today, so fully closing `Insert` is a follow-up. It also adds the missing unit coverage for the `getManagedProps` / `hasManagedProps` seam the override depends on.

## Changelog:

[INTERNAL] [FIXED] - Seed managed props when a view connects to the native animated backend so they are live before the first frame, shrinking the useNativeDriver mount flash

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

Test Plan: Adds `ManagedPropsMountingOverrideTests.cpp` to the ReactCommon animated unit tests. `getManagedPropsReflectsLiveValueAcrossFrames`, `getManagedPropsNullForUnconnectedView`, `hasManagedPropsTracksConnectAndDisconnect` and `getManagedPropsIsolatedPerView` pin the seam and pass regardless of the change. `getManagedPropsLiveImmediatelyOnConnect` and `getManagedPropsLiveOnConnectWhileValueMidFlight` are the regression cases: they fail without the seed (empty props at connect) and pass with it. Run via the animated C++ unit test target. On-device verification (iOS and Android with `cxxNativeAnimatedEnabled` on, frame-stepped capture of a popover/menu open) is still recommended for the user-visible flash.

Reviewed By: sammy-SC

Differential Revision: D110323404

Pulled By: zeyap

fbshipit-source-id: 485e31e1c874548da1ee7339481164faa763b2d9
2026-07-01 12:53:55 -07:00
Rubén Norte 2bb7dbb499 Add an interactive REPL for Fantom (yarn fantom-cli) (#57387)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57387

Adds `yarn fantom-cli`, an interactive REPL that evaluates JavaScript against the same native tester binary and Hermes runtime that Fantom tests run in. State persists across lines, input goes through Metro/Babel (so `import`, JSX and Flow all work), and the environment is set up the same way tests set it up — `React`, `ReactNative` and the `Fantom` API are available globally, so you can render surfaces and drive them interactively from the prompt.

The native tester gains an `--interactive` mode that loads a warm-up bundle without running tests and then evaluates length-prefixed snippets read from stdin, reporting results, console output and errors back as newline-delimited JSON. A Node driver hosts a Metro server, builds the warm-up bundle, spawns the binary, and bridges each line of input into the live runtime (top-level declarations persist across evaluations).

Features:

- Console-style output: results are printed with an inspector similar to the Chrome DevTools / Node.js consoles (nested objects/arrays up to a depth limit, quoted strings, functions/classes, `Map`/`Set`/`RegExp`/`Date`/`Error`, class instances, circular references, multi-line wrapping), colorized by type when stdout is a terminal. Inspecting a property never aborts the result or leaks into later evaluations: a property whose getter fails renders as `[Thrown: <error>]`, including getters that fail asynchronously through the runtime's global error handler (e.g. accessing a `react-native` export backed by a TurboModule that isn't registered).
- Autocompletion: pressing Tab completes global identifiers, in-scope bindings and object properties (property names are listed without invoking getters).
- Node-like CLI: with no arguments it starts the REPL; `-e <code>` evaluates a snippet and exits; a filename runs that script and exits. In the non-interactive modes the value of a trailing expression is not printed (use `console.log`) and a thrown error exits with a non-zero status code.

Also documents the REPL in the Fantom README.

Changelog: [Internal]

Reviewed By: javache, sammy-SC

Differential Revision: D110187712

fbshipit-source-id: 3e76c498ae04b8b1ce9e0e27e5ce6b6a0cd11e09
2026-07-01 08:18:34 -07:00
Bartlomiej Bloniarz d9d2502b61 Fix AnimatedPropsRegistry surface-stop resurrection race (#57376)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57376

AnimatedPropsRegistry::update() runs on the UI thread every animation frame and
created a surface's entry via operator[]. clearOnSurfaceStop() (run on the JS
thread when a surface stops) erases that entry, but an in-flight animation frame
landing after the stop re-created it via operator[] -- and since the surface is
gone, nothing ever cleans it up again. The resurrected entry leaks its
PropsSnapshot and ShadowNodeFamily for the lifetime of the registry.

A surface's entry is legitimately created by getMap(), which
AnimationBackendCommitHook calls on every React commit. stopSurface drains
in-flight commits before unregistering the ShadowTree
(ShadowTreeRegistry::remove takes the registry's unique lock, which excludes the
shared-locked commit visits), so getMap() can never run for a stopped surface.
That leaves update()'s operator[] as the only thing that can resurrect one.

Fix: update() now only refines surfaces that already exist (find instead of
operator[]) and never creates an entry; getMap() remains the sole creator. A
stopped surface can no longer be resurrected, and there is no extra bookkeeping
that could grow over time.

Changelog: [General][Fixed] - Fix a surface-stop race in the C++ Animated shared backend that could permanently leak per-surface animated state

Reviewed By: javache

Differential Revision: D109156094

fbshipit-source-id: 4684ca51d372023e3b082427a225de7d84d14889
2026-07-01 07:13:13 -07:00
Pieter De Baets 2468e3c867 Remove unused ViewShadowNodeProps subclass (#57377)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57377

ViewShadowNodeProps was a thin subclass of ViewProps that only forwarded its constructor. After the feature flag propagation logic was removed, the subclass serves no purpose.

Changelog:
[Internal]

Reviewed By: lenaic

Differential Revision: D110095190

fbshipit-source-id: a2555c4ba455e51116c73be3b5c9a71788895ffd
2026-07-01 04:00:49 -07:00
SJLIM ca29d38537 fix(text): support start and end text alignment (#57201)
Summary:
Closes https://github.com/react/react-native/issues/45255.

Adds `textAlign: 'start' | 'end'` support for Text and TextInput across the JS types, Android, iOS, and Fabric text conversion paths.

- Android legacy Text and TextInput now accept logical `start`/`end` alignment values.
- Fabric preserves `start`/`end` as distinct `TextAlignment` values and resolves them against layout direction for iOS paragraph layout.
- Existing `left`/`right` behavior is left unchanged to avoid changing current RTL semantics.

This replaces https://github.com/react/react-native/issues/57007 because the original fork became locked and could not be updated after the upstream conflict.

## Changelog:

[GENERAL] [ADDED] - Add support for `textAlign: 'start'` and `textAlign: 'end'`.

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

Test Plan:
- `yarn build-types`
- `yarn test-typescript`
- `yarn flow-check`
- `./node_modules/.bin/prettier --check packages/react-native/Libraries/Components/TextInput/TextInput.d.ts packages/react-native/Libraries/Components/TextInput/TextInput.flow.js packages/react-native/Libraries/StyleSheet/StyleSheetTypes.d.ts packages/react-native/Libraries/StyleSheet/StyleSheetTypes.js packages/react-native/types/__typetests__/index.tsx packages/react-native/ReactNativeApi.d.ts`
- `./gradlew ktfmtCheck -Preact.internal.useHermesStable=true --no-daemon`
- `./gradlew :packages:react-native:ReactAndroid:testDebugUnitTest --tests com.facebook.react.views.textinput.ReactTextInputPropertyTest.testTextAlign --tests com.facebook.react.views.text.TextAttributePropsTest -Preact.internal.useHermesStable=true --no-daemon`
- `./gradlew ':packages:react-native:ReactAndroid:buildCMakeDebug[arm64-v8a][hermestooling,jsi,etc]' -Preact.internal.useHermesStable=true --no-daemon`
- `git diff --check`

The Android unit test and CMake checks were run from an ASCII-only temporary worktree because Kotlin unit test compilation in my main checkout fails before running these tests when the workspace path contains non-ASCII characters.

Reviewed By: christophpurrer

Differential Revision: D108628602

Pulled By: javache

fbshipit-source-id: 28111d0553451d7de0424a07e956f71bda8787ca
2026-07-01 03:43:49 -07:00
Mathieu Acthernoene fd10410d51 Remove Modal animated prop (#57385)
Summary:
Removes the deprecated `animated` prop from `Modal`. It was a no-op everywhere. Use `animationType` instead.

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

## Changelog:

[GENERAL] [REMOVED] - Remove deprecated `Modal` `animated` prop

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

Test Plan:
- `yarn jest packages/react-native/Libraries/Modal`
- `yarn flow` and `tsc` pass with the prop removed from `Modal.js` / `Modal.d.ts`.

Reviewed By: huntie

Differential Revision: D110205204

Pulled By: cortinico

fbshipit-source-id: 8e5b4d7dc8811d7270de3776476e7f868eafddd5
2026-06-30 14:08:11 -07:00