## Summary:
Bump minimum Metro version to 0.87.1, within the same semver range, to ensure upgraders get the same version as fresh projects would.
Mostly fixes, including a couple of `Platform` inlining corrections. It also replaces the `image-size` dependency to clear CVE alerts.
Metro release notes: https://github.com/react/metro/releases/tag/v0.87.1
## Changelog:
[General] [Changed] - Bump Metro minimum to 0.87.1
## Test Plan:
```
yarn install --frozen-lockfile --ignore-scripts
yarn flow-check
yarn test packages/metro-config packages/community-cli-plugin packages/dev-middleware
```
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58353
Fixes https://github.com/react/react-native/issues/57787.
Supersedes https://github.com/react/react-native/pull/57788.
## Context
On Android, `Image.getSize()` and `Image.getSizeWithHeaders()` reject for every `data:` URI.
Both resolve dimensions through Fresco's encoded-image pipeline. That pipeline has producer
sequences only for network, local-file and local-content URIs; every other scheme falls through to
a throw:
Unsupported uri scheme for encoded image fetch! Uri is: data:image/jpg;base64,...
Fresco's decoded-image pipeline does handle the scheme (`SOURCE_TYPE_DATA -> dataFetchSequence`), so
the capability exists — the encoded entry point simply does not expose it. A previous change added a
fast path for `res://` URIs for exactly this reason; `data:` was never given one.
Any app that gates rendering on `getSize` therefore cannot display an inline base64 image on
Android at all, while iOS is unaffected.
## This Diff
- Adds a `data:` fast path to `getSize` and `getSizeWithHeaders`, mirroring the existing
resource-drawable fast path, routed through `fetchDecodedImage` rather than `fetchEncodedImage`.
- Pins the request to auto-rotate so it produces the same Fresco bitmap cache key that
`ReactImageView` builds for the same URI. Rotation options are part of that key, so a mismatch
here would decode into a key nothing reads and force a second decode at render time.
- Sets `DownsampleMode.NEVER` so the reported dimensions stay intrinsic rather than
post-downsample, preserving the behaviour the encoded path was originally adopted for. That
option is absent from the bitmap cache key, so it does not disturb the parity above.
- Reads the visible dimensions straight off the decoded image, which has already had its EXIF
rotation applied, rather than repeating the axis swap the encoded subscriber performs by hand.
`BaseCloseableStaticBitmap` applies that same predicate internally, so repeating it here would
double-apply it.
- Adds unit coverage for the `data:` scheme, which had none: decoded-pipeline routing, cache-key
parity with `ReactImageView`, intrinsic dimensions, the headers variant, and both failure paths.
- Adds two `data:` rows to the RNTester `Image.getSize` platform test — one plain, one tagged EXIF
orientation 6 — so a real decode, rather than a mocked pipeline, proves the reported dimensions
are the visible ones. Both are inline base64, so they need no network.
Because the decode now warms the bitmap memory cache under the key the `<Image>` subsequently
reads, a caller that sets its image source from the `getSize` success callback paints from cache
instead of decoding at render time.
## Alternatives Considered
**Parse the dimensions out of the base64 header.** Satisfies the `getSize` contract and is cheaper,
but warms nothing. Callers that relied on the decode side effect for smooth playback would keep
re-decoding every frame at render time — it fixes the rejection without fixing the regression that
accompanied it.
**Add a `data:` arm to Fresco's encoded producer sequence.** Pushes a behavioural change into shared
image infrastructure used by every app, to serve a caller that wants a decoded result anyway. The
narrower fix belongs on this side.
**Have callers stop gating rendering on `getSize`.** Makes the image appear, but permanently
discards the decode-then-render ordering, leaving the surface visibly flickering.
Changelog:
[Android][Fixed] - Fix `Image.getSize()` and `Image.getSizeWithHeaders()` rejecting `data:` URIs
Reviewed By: Abbondanzo, javache, cortinico
Differential Revision: D118657320
fbshipit-source-id: 576ce8458c921b199d717161c2113a7d4f99221b
Summary:
When `crossOrigin="use-credentials"` or `referrerPolicy` is used on an `Image`, `getImageSourcesFromImageProps` currently fully replaces `source.headers`, removing custom headers such as `Authorization`.
This fix merges the generated headers with the user-provided source headers instead (user-provided headers take precedence).
## Changelog:
[GENERAL] [FIXED] - Preserve Image source headers when using crossOrigin or referrerPolicy
Pull Request resolved: https://github.com/react/react-native/pull/58319
Test Plan: Confirmed existing tests are unchanged & added a regression test
Reviewed By: christophpurrer
Differential Revision: D118797893
Pulled By: javache
fbshipit-source-id: 8018846647232f97cb9e12d6095774826999c89b
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58313
In bridgeless, native reaches JS by two routes that end in the same
`RuntimeScheduler` queue but get there differently. `callFunctionOnModule` goes
through the instance's `BufferedRuntimeExecutor`; the `CallInvoker` goes
straight to `scheduleTask`. The CallInvoker therefore skips the buffer entirely
and can reach the runtime while a module call issued earlier is still parked,
unflushed, because the bundle is mid-evaluation. Native code that issues both
cannot rely on the order it issued them in, and `Task` is a min-heap on
`now() + timeout(priority)` with no insertion tiebreak, so equal priorities do
not settle it either.
Gives the two channels the same buffering. `BufferedRuntimeExecutor` gains a
priority-carrying `execute`, so work routed through it keeps the scheduler
priority it was submitted with instead of collapsing to the executor default,
and buffered work from both overloads stays in one submission-ordered stream.
`BufferedCallInvoker` sits on that executor and becomes the bridgeless
`jsCallInvoker` on Android, iOS and macOS.
`invokeSync` deliberately keeps going straight to the scheduler: a synchronous
call cannot wait for a flush that only happens once the bundle has run.
Behind `enableBufferedCallInvoker`, default true. `ReactInstance` picks between
the buffered invoker and the existing `RuntimeSchedulerCallInvoker` in one
place, so the platform call sites are identical either way and the change is
revertible at runtime — it moves when native-issued async work first reaches JS
during startup, which is the intended contract but affects every native module.
One lifetime hazard this surfaces, worth knowing about beyond this diff:
`BufferedRuntimeExecutor` reaches the scheduler through a raw pointer captured
at construction, which is safe only while the owning instance is alive. A
CallInvoker is routinely held across instance teardown, so `BufferedCallInvoker`
guards every async dispatch on a weak reference to the scheduler and drops the
work when it has expired — the same contract `RuntimeSchedulerCallInvoker` has.
Without that guard this reliably segfaults on a reload.
Changelog:
[General][Changed] - Async `CallInvoker` work is now buffered alongside callable module calls, so it no longer runs before the JS bundle has finished evaluating
Reviewed By: rubennorte
Differential Revision: D118456662
fbshipit-source-id: 7c6ccb595d69595721092eeb84b4724809140496
Summary:
When `accessibilityState.disabled` conflicts with an explicit `disabled` prop, the `Text` component currently updates `accessibilityState` in place. This mutates an object owned by the caller, which can cause issues when other code uses that same object.
This fix creates a new object instead, while retaining existing behavior (giving priority to the explicit prop).
## Changelog:
[GENERAL] [FIXED] - Prevent Text from mutating the accessibilityState prop
Pull Request resolved: https://github.com/react/react-native/pull/58318
Test Plan: Unchanged tests pass + added a regression test
Reviewed By: Abbondanzo
Differential Revision: D118788803
Pulled By: javache
fbshipit-source-id: 77f69e851d06250aa27e20912a2c2fc91394b81d
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58307
Classifies `react/renderer/imagemanager:imagemanager` 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.
`React-Fabric` already depended on `React-cxxstableapi` from an earlier migration in the same pod, so the module's subspec needs no change.
Changelog: [Internal]
Reviewed By: rubennorte
Differential Revision: D118621752
fbshipit-source-id: ecf701cc3377904088a7bd56bf39b2b924850ca2
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58323
Restore `paperComponentName: 'RCTSwitch'` in `SwitchNativeComponent.js` and regenerate affected snapshots to fix test breakages introduced by D117877024.
`testing-library/react-native` 13.3.3 hardcodes `HOST_SWITCH_NAMES = ['RCTSwitch']`, so renaming the component to `Switch` broke `getByRole('switch')` queries and `toBeChecked()` assertions. This was the only xplat/js-wide breakage from that diff—only bare `<Switch>` renders without explicit `accessible` props failed, and only in `TWInternBoolSettingComponent-test.js`.
Add an inline comment documenting the `testing-library/react-native` constraint to prevent future regressions. The four other component renames in D117877024 have no RNTL special-casing and remain as landed.
Changelog: [iOS][Fixed] Restore `paperComponentName: 'RCTSwitch'` to fix `testing-library/react-native` queries
Reviewed By: javache
Differential Revision: D118743290
fbshipit-source-id: 0fbd5e99fb1dfd7f0b1a307b0ed058f0d2082b77
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57733
Upgrade several remaining Libraries modules (WebSocket, PanResponder, RCTEventEmitter, and Flow type tests) from `flow` to `flow strict-local` with accurate types. WebSocket exposes spec-mandated getters/setters and opts out of the `unsafe-getters-setters` lint with a scoped directive. Behavior is unchanged.
Changelog: [Internal]
Reviewed By: javache
Differential Revision: D113763779
fbshipit-source-id: 86827a975e996a4c85dd92344d36746e61887dde
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57741
Upgrade the element inspector dev support modules from `flow` to `flow strict-local`, replacing loose `Object`/`Function` types with the accurate types already used by their callers and dependencies.
Changelog: [Internal]
Reviewed By: javache
Differential Revision: D113763787
fbshipit-source-id: 114d12cb02e244431d59b18e3b3c6cfa363bd25f
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57735
Upgrade `AppRegistry` (and its Flow type companion) and several Core timer modules from `flow` to `flow strict-local` with accurate types. Behavior is unchanged.
Changelog: [Internal]
Reviewed By: javache
Differential Revision: D113763781
fbshipit-source-id: 48936dbc898c9d409818fb23794711e7bb6c66ed
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57729
Upgrade assorted Utilities modules from `flow` to `flow strict-local` with accurate types. `insetsDiffer` uses local variables instead of reassigning its function parameters. Behavior is unchanged.
Changelog: [Internal]
Reviewed By: javache
Differential Revision: D113763792
fbshipit-source-id: 4c7672439ae5af27f4298c04dc5606ced5509888
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57728
Upgrade the Blob-related modules (`File`, `FileReader`, `URL`, `URLSearchParams`) from `flow` to `flow strict-local`. These expose spec-mandated getters/setters, so they opt out of the `unsafe-getters-setters` lint with a scoped `// flowlint unsafe-getters-setters:off` directive. `URL` also received small behavior-preserving refactors (local variables instead of parameter reassignment, explicit null/empty checks).
Changelog: [Internal]
Reviewed By: javache
Differential Revision: D113763778
fbshipit-source-id: 1e0ceb02270d458fae6b89886ae41d9893ae7329
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57724
Upgrade the legacy native module spec files from `flow` to `flow strict-local` to enforce stricter local type checking. Loose `Object` types were replaced with the codegen-equivalent `UnsafeObject`, and `Array<any>` parameters with `Array<unknown>`, both of which are codegen-identical so the generated native interfaces are unchanged.
Changelog: [Internal]
Reviewed By: javache
Differential Revision: D113763785
fbshipit-source-id: 085a0a570246eeda27b3c22a56a2696b04821fd5
Summary:
The source-optimized preset enables native component codegen only when `codegenNativeComponent` is immediately followed by `<`. Valid Flow syntax permits comments or whitespace before the type arguments, so `codegenNativeComponent /* comment */ <NativeProps>(...)` bypasses codegen and emits an ordinary runtime call instead of the generated `__INTERNAL_VIEW_CONFIG` produced by the full preset path.
Use the stable `codegenNativeComponent` identifier token as the cheap source prefilter while retaining the existing null/undefined full-scan path. Formatting no longer changes build output; false-positive tokens only enable the codegen visitor, which remains a no-op without a matching call.
## Changelog:
[GENERAL] [FIXED] - Run native component codegen when Flow type arguments are separated by trivia.
Pull Request resolved: https://github.com/react/react-native/pull/58257
Test Plan:
- Added a valid Flow native-component spec containing a comment before `<NativeProps>`.
- Exact optimized baseline emits the ordinary call without `__INTERNAL_VIEW_CONFIG`; the fixed transform generates the static view config.
- Full preset Jest passes: 4/4 suites, 111/111 tests, 16 snapshots.
- Fresh Flow check reports 0 errors.
- Targeted no-ignore ESLint, Prettier, and `git diff --check` pass.
No public API or breaking behavior change; optimized and full preset paths now agree for valid formatting.
Reviewed By: GijsWeterings
Differential Revision: D118266389
Pulled By: javache
fbshipit-source-id: 0b4279eed9f831e1e8f4669bd522645023dfdeac
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58311
# Why
Currently, grid style properties are stored in yoga style (`gridTemplateRows_`, `gridAutoColumns_` etc). These properties increase the size of style object from `152` bytes to `280` bytes (84% increase). The cost is added even when a node is not a grid container or a grid item.
# How
Move grid style properties behind a pointer that is lazily allocated, on the first grid property set. A node that doesn't use grid only adds the cost of this pointer (8 bytes). So style now costs 160 bytes (5% increase). The public API remains unchanged.
# Tests
A test is added to catch the style size regression and `tests/GridStyleTest.cpp` includes additional cases to assert unset style, copy and move behaviour.
Changelog: [Internal]
X-link: https://github.com/react/yoga/pull/2018
Reviewed By: rubennorte
Differential Revision: D118628661
Pulled By: javache
fbshipit-source-id: 185370e93bcf5b277b48c436ba3d06dada5a66fe
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58304
Classifies `react/renderer/animationbackend:animationbackend` 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.
`React-Fabric` already depended on `React-cxxstableapi` from an earlier migration in the same pod, so the module's subspec needs no change.
Changelog: [Internal]
Reviewed By: rubennorte
Differential Revision: D118616103
fbshipit-source-id: dbe574a524c8a29e204792ca2193c4c8238d1c20
Summary:
`npx react-native spm add` writes `HERMES_CLI_PATH` into the app's committed `project.pbxproj` — the absolute path of `hermesc` in the `hermes-compiler` npm package, as resolved on whichever machine ran the command. So every SwiftPM-converted app commits one developer's disk layout.
Nothing needs it: `react-native-xcode.sh` already resolves `hermesc` at build time through react-native's own dependency graph when the current value is not a file. A relative setting can't replace it either — `$(REACT_NATIVE_PATH)/../hermes-compiler` breaks on a symlinked `react-native`, and `$(SRCROOT)/../node_modules/…` breaks on hoisted monorepos.
So this deletes `resolveHermesCliPathSetting()`, along with the `hermesCliPath` parameter it fed on `injectSpmIntoPbxproj` and `mergeReactBuildSettings`. Already-injected projects self-clean on the next `spm add`/`update`, which strips every scalar recorded in `.spm-injected.json` before re-injecting.
### Scope: SwiftPM only
Both pieces involved arrived with SwiftPM in https://github.com/react/react-native/issues/57332 and first shipped in 0.87.0 — `scripts/spm/generate-spm-xcodeproj.js` (the whole file, including the write) and the `NODE_HERMESC` build-time fallback in `react-native-xcode.sh`.
Everything CocoaPods relies on is older and untouched, all present in 0.86.0: the pod-derived `HERMES_CLI_PATH` default, the "hermesc could not be found" error, and the `hermesc -emit-binary` call. **A CocoaPods build cannot be affected by this change.**
That parameter shipped in 0.87.0 and 0.87.1, but SwiftPM is Preview-labelled, so removing it is in scope. Nothing in the repo passed it except the deleted resolver.
## Known limitation
The fallback is gated on `PODS_ROOT` being absent, so a SwiftPM app that keeps side-by-side non-RN pods skips it and needs an explicit `HERMES_CLI_PATH`. Evaluating that gate verbatim out of the unchanged script:
| app | gate | hermesc |
| --- | --- | --- |
| no `Pods/` (normal SwiftPM app) | fires | from `node_modules` |
| `Pods/`, non-RN pods only | skipped | pod path — absent |
| `Pods/` with `hermes-engine` | skipped | the pod's, unchanged |
Set it in an xcconfig, not the pbxproj: `createdScalars` cleanup removes by key, so it would drop a hand-edited value too. Keying the gate on the `hermes-engine` directory would close this — left as a follow-up so this PR doesn't touch the bundling script.
## Changelog:
[IOS] [FIXED] - SwiftPM: stop baking an absolute, machine-specific HERMES_CLI_PATH into the app's pbxproj; resolve hermesc at build time instead
Pull Request resolved: https://github.com/react/react-native/pull/58292
Test Plan:
Red first — with the source reverted, the new entry-point test fails on a seeded `hermes-compiler` fixture: `✕ writes no HERMES_CLI_PATH, in any configuration or the marker` (1 failed, 76 passed).
```
yarn jest packages/react-native/scripts/spm --no-cache -i
Test Suites: 18 passed, 18 total
Tests: 835 passed, 835 total
```
`yarn flow-check` (0 errors), plus `yarn eslint --max-warnings 0` and `yarn prettier --check` on the four changed files.
End to end: a 0.87.1 SwiftPM app (`shopify/react-native-skia` example, no Pods) with the `HERMES_CLI_PATH` lines removed from its pbxproj builds in Release, the fallback resolving `hermesc` from `node_modules/hermes-compiler`. That build ran against an earlier revision of this branch which also widened the shell gate; with no `Pods/` it is row 1, where both conditions behave identically. There is no shell test harness, and the script is unchanged here.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Reviewed By: cortinico
Differential Revision: D118624244
Pulled By: cipolleschi
fbshipit-source-id: 5784a2de69af0c50c82129d96423801b0f5b0eba
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58274
`ReadableNativeMap` materialization copied keys and created temporary JNI references for every imported type. Cache pointers to the stable native values and reuse global `ReadableType` references so importing maps and arrays does less allocation and lookup work.
Writable maps can continue mutating after materialization because `folly::dynamic` stores object entries in reference-stable `F14NodeMap` nodes.
Changelog: [Internal]
Reviewed By: christophpurrer, rubennorte
Differential Revision: D118277119
fbshipit-source-id: 955a60ef7f1eb4cb7549d64caa1238416e90b223
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58167
Classifies `react/runtime:runtime` and `react/runtime:runtime-platform` as "for frameworks" targets under the three-tier C++ stable API visibility model. Consumers that opt into `RN_STRICT_API` now get a warning if they include their headers directly, which they can acknowledge with `RN_ALLOW_FRAMEWORKS`; without that flag the guards are inert, so no existing build changes behaviour.
The Apple platform layer is covered alongside the core runtime, so `RCTHost.h` and `RCTInstance.h` are in scope. `React-RuntimeCore` already depended on `React-cxxstableapi` from an earlier migration in the same pod; `React-RuntimeApple` gains the dependency here.
Changelog: [Internal]
Reviewed By: cipolleschi
Differential Revision: D117690303
fbshipit-source-id: 5e80284eefe6be4b556aacf4415c8c8ba228471e
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58303
Classifies `react/renderer/mounting:mounting` as a "for frameworks" target under the C++ stable API three-tier visibility model. Adds `#include <react/cxxstableapi/FrameworksGuard.h>` to the module's 15 non-test headers, and wires the guard dependency into BUCK and CMake. No CocoaPods change is needed: the module ships as a subspec of `React-Fabric`, whose parent spec already declares `React-cxxstableapi` and calls `mark_as_react_native_build`.
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: rubennorte
Differential Revision: D118612708
fbshipit-source-id: d6cd27d55bd7ca86a70a837919a78a24426176d7
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58301
Classifies `react/renderer/telemetry:telemetry` as a "for frameworks" target under the C++ stable API three-tier visibility model. Adds `#include <react/cxxstableapi/FrameworksGuard.h>` to the module's 2 non-test headers, and wires the guard dependency into BUCK and CMake. No CocoaPods change is needed: the module ships as a subspec of `React-Fabric`, whose parent spec already declares `React-cxxstableapi` and calls `mark_as_react_native_build`.
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: rubennorte
Differential Revision: D118612692
fbshipit-source-id: ef8f9ab90699f272d0592d56dd68550ae3b6f84f
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58321
`SchedulerDelegateInvalidationTest.DelegateDestroyedWithoutError_PendingRenderingUpdateIsUAF`
asserted a real use-after-free through `EXPECT_DEATH`: it destroyed the
`RecordingDelegate`, then drained `pendingRenderingUpdates_` so the queued lambda
dereferenced the freed object, and expected the process to die. Undefined behaviour
is not a reliable process-termination signal, without a sanitizer the freed read
can simply succeed, and gtest then reports `Result: failed to die.` The death test
also has to `fork()` a multi-threaded process.
This replaces the death test with a deterministic assertion on the same property.
Instead of destroying the delegate, the test detaches it via
`Scheduler::setDelegate(nullptr)` and keeps it alive, then drains the pending
rendering update and asserts that the drained lambda still invokes
`schedulerShouldRenderTransactions` on the detached delegate.
That pins exactly the coverage the death test was after: `Scheduler::setDelegate` is
a plain assignment, so a lambda already queued by `uiManagerDidFinishTransaction`
keeps the raw delegate pointer it captured, and draining it after the delegate has
been detached still calls through that pointer, which is a use-after-free when the
delegate has been destroyed rather than merely detached. Same property, no undefined
behaviour and no `fork()`. It matches the shape of the existing
`UnregisterSurface_DoesNotDrainPendingRenderingUpdates` test in the same file.
The underlying window is unchanged: nothing in `Scheduler::setDelegate` cancels
rendering updates that are already queued, so closing it needs a shutdown signal at
the runtime-scheduler level. That is a design decision for the owners rather than a
test fix.
Changelog: [Internal]
Reviewed By: fkgozali
Differential Revision: D118205636
fbshipit-source-id: 87cefd8db0d0ebf55025bb60fcdfd1e4cda46e35
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57984
`hash_combine` mixes each field into the previous seed, so it forms a dependency chain the CPU
cannot overlap and an unset optional still costs a full link. `hash_combine_optionals` folds a run
of optionals into one presence-mask link plus the engaged values, so a further optional costs a bit
in the mask rather than a link. The mask is what keeps it collision-free: skipping disengaged
fields alone would make the same value in two different slots hash identically.
Equality moves from `std::tie` to a short-circuit chain ordered cheapest first, with the string and
vector fields last, because the dominant caller is a successful cache lookup where the keys are
equal and every field has to be examined.
Changelog: [Internal]
Reviewed By: javache
Differential Revision: D115621401
fbshipit-source-id: f164c24f6b085ef8d32cafbeb2b61636eec3d0cf
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58188
`paperComponentName` is a `codegenNativeComponent` option that makes the generated
view config announce the old-architecture (Paper) `RCT`-prefixed ViewManager name
instead of the component's own name. We no longer support the old architecture, so
core components should announce their real Fabric names.
Removes the option from the five core specs where it is provably redundant:
| Spec | Name in view config |
|---|---|
| `ActivityIndicatorViewNativeComponent.js` | `RCTActivityIndicatorView` -> `ActivityIndicatorView` |
| `RCTModalHostViewNativeComponent.js` | `RCTModalHostView` -> `ModalHostView` |
| `PullToRefreshViewNativeComponent.js` | `RCTRefreshControl` -> `PullToRefreshView` |
| `RCTSafeAreaViewNativeComponent.js` | `RCTSafeAreaView` -> `SafeAreaView` |
| `SwitchNativeComponent.js` | `RCTSwitch` -> `Switch` |
Each new name already resolves natively, so this is a no-op at runtime:
- **iOS Fabric** — the plugin keys in `RCTFabricComponentsPlugins.mm` and the
`react_fabric_component_plugin_provider` entries in `BUCK` are all unprefixed and
match the spec names exactly. Previously the `RCT` prefix was simply stripped again
by `componentNameByReactViewName()`, which exists only to undo this legacy prefixing.
- **Android Fabric** — mount items carry the C++ descriptor name, not the JS name
(`IntBufferBatchMountItem`), so Android is unaffected. `ModalHostView` still maps via
`FabricNameComponentMapping`, and `SafeAreaView` still resolves to
`ReactSafeAreaViewManager` through the generic `"RCT$className"` fallback in
`ViewManagerRegistry`. `PullToRefreshView` and `Switch` are Android-excluded.
Deliberately out of scope:
- **The codegen option itself is retained.** 24 Meta-internal specs outside
`react-native-github` still pass `paperComponentName` (`RCTMapNativeComponent.js`,
`SliderNativeComponent.js`, the `AdsLWI` previews, MagicIsland, ...), as do
third-party OSS libraries. `getOptions()` does not validate keys, so removing support
would silently resolve those components to an unregistered name instead of erroring.
- **`RCTInputAccessoryViewNativeComponent.js` keeps the option**, where it is
load-bearing: the spec name is `InputAccessory` but the C++ `ComponentName` is
`InputAccessoryView`, so dropping it would fall through to
`RCTUnimplementedViewComponentView`. Aligning those needs a rename of the codegen'd
`InputAccessoryProps`/`InputAccessoryEventEmitter` symbols in handwritten C++/ObjC.
- **`paperComponentNameDeprecated`**, which still has 6 internal users.
- **Documentation.** The `paperComponentName` section of the `name_mapping.md` docs is
refreshed in a separate diff, so this one touches no Markdown.
Also updates the `RCTSwitch` fiber-type checks in `ReactTreeSerializer.js` to accept
`Switch`, mirroring the existing check in its sibling `DebugInteractions.js`.
Snapshot churn is the renamed element names only. The `RCTRefreshControl` entries in
the `VirtualizedList`/`RelayPaginationView` snapshots are unchanged because they come
from the hardcoded `packages/jest-preset/jest/mocks/RefreshControl.js` mock, not from
the view config.
## Changelog:
[General][Changed] - Core components (`ActivityIndicatorView`, `ModalHostView`, `PullToRefreshView`, `SafeAreaView`, `Switch`) no longer report legacy `RCT`-prefixed names in their view configs
## Facebook:
https://www.internalfb.com/agent-home?session_id=dmh-e2936545-b7bf-43e3-b1a8-4b95325fd16a
Reviewed By: GijsWeterings
Differential Revision: D117877024
fbshipit-source-id: a738157ec4ffa5c042891b26eb4c358cd5bb2248
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58083
Classifies `react/featureflags:featureflags` as a public target under the C++ stable API three-tier visibility model and introduces the module umbrella `React/FeatureFlags.h` as its public entry point.
This module's headers are generated, so the `UmbrellaGuard.h` include is added to the templates in `scripts/featureflags/templates/common-cxx/` rather than to the headers themselves. `ReactNativeFeatureFlagsOverridesOSSStable.h` is the module's one hand-written header and is edited directly. The umbrella is not generated, and re-exports all eight of the module's headers.
The sibling `react/nativemodule/featureflags:featureflags` target is private under the same model.
The guards are inert unless a consumer defines `RN_STRICT_API`, so there is no behavior change.
Changelog:
[General][Added] - Add `<React/FeatureFlags.h>` umbrella header as the public entry point for `react/featureflags`
Reviewed By: cortinico
Differential Revision: D117172757
fbshipit-source-id: 9cc66e3d9e88842d2caba919c2dd941f1e602da3
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58286
Reclassifies `react/renderer/bridging:bridging` from public to "for frameworks" under the C++ stable API three-tier visibility model.
Consumers that opt into `RN_STRICT_API` now get a suppressible warning where they previously got an error pointing at the umbrella, and can acknowledge it with `RN_ALLOW_FRAMEWORKS`; without that flag the guards are inert, so no existing build changes behaviour.
Changelog: [Internal]
Reviewed By: christophpurrer
Differential Revision: D118440441
fbshipit-source-id: edf9691028506b7016f32d3a3cff41d905abca41
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58287
Reclassifies `react/renderer/components/scrollview:scrollview` from public to "for frameworks" under the C++ stable API three-tier visibility model.
Consumers that opt into `RN_STRICT_API` now get a suppressible warning where they previously got an error pointing at the umbrella, and can acknowledge it with `RN_ALLOW_FRAMEWORKS`; without that flag the guards are inert, so no existing build changes behaviour.
Changelog: [Internal]
Reviewed By: christophpurrer
Differential Revision: D118440409
fbshipit-source-id: 1c2895ed0b59e24bb06396a23af227726a1b7406
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58282
Reclassifies `react/renderer/components/root:root` from public to "for frameworks" under the C++ stable API three-tier visibility model.
Consumers that opt into `RN_STRICT_API` now get a suppressible warning where they previously got an error pointing at the umbrella, and can acknowledge it with `RN_ALLOW_FRAMEWORKS`; without that flag the guards are inert, so no existing build changes behaviour.
Changelog: [Internal]
Reviewed By: christophpurrer
Differential Revision: D118440376
fbshipit-source-id: 2f6b74a8e1ead890bc2d8832370cda5384332bcf
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58284
Reclassifies `react/renderer/components/text:text` from public to "for frameworks" under the C++ stable API three-tier visibility model.
Consumers that opt into `RN_STRICT_API` now get a suppressible warning where they previously got an error pointing at the umbrella, and can acknowledge it with `RN_ALLOW_FRAMEWORKS`; without that flag the guards are inert, so no existing build changes behaviour.
Changelog: [Internal]
Reviewed By: christophpurrer
Differential Revision: D118440348
fbshipit-source-id: 0ec6c4304a81466766d0353bc4aec3d29c958f76
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58285
Reclassifies `react/renderer/components/modal:modal` from public to "for frameworks" under the C++ stable API three-tier visibility model.
Consumers that opt into `RN_STRICT_API` now get a suppressible warning where they previously got an error pointing at the umbrella, and can acknowledge it with `RN_ALLOW_FRAMEWORKS`; without that flag the guards are inert, so no existing build changes behaviour.
Changelog: [Internal]
Reviewed By: christophpurrer
Differential Revision: D118440328
fbshipit-source-id: f337645c846cfc669b1e0d03cf83b9c59affe657
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58269
Classifies `react/renderer/animated:animated` as a "for frameworks" target under the C++ stable API three-tier visibility model. Adds `#include <react/cxxstableapi/FrameworksGuard.h>` to the module's 30 non-test headers, and wires the guard dependency into BUCK and CMake. No CocoaPods change is needed: the module ships as a subspec of `React-Fabric`, whose parent spec already declares `React-cxxstableapi` and calls `mark_as_react_native_build`.
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: christophpurrer
Differential Revision: D118256232
fbshipit-source-id: 5ec898e99858980ff1e69a4a1eac6515740d06f1
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58264
When an ObjC TurboModule method raises an `NSException`, what happens next depends on how it was
called. A sync call converts it into a JSError via `convertNSExceptionToJSError`, which builds
`<module>.<method> raised an exception: <reason>`. The async and void paths cannot do that — they
run on the module's method queue with no JS runtime to attach the error to — so they rethrow.
Both rethrow sites discarded `moduleName` and `methodNameStr`, even though both are captured in the
enclosing block and in scope at the throw site. Because void and async methods are dispatched onto
the method queue, the rethrown exception is uncaught and terminates the process, and by then every
module frame has unwound: the reported stack bottoms out in `objc_exception_rethrow` followed by a
libdispatch queue drain. Nothing in the resulting crash says which module or method failed.
The practical effect is that all such crashes — regardless of which module raised them, and
regardless of whether the underlying bug is a null argument, a wrong-typed argument, or anything
else — collapse into a single crash bucket with no owner attached, and cannot be split or routed.
This adds an `addModuleIdentityToException` helper next to `convertNSExceptionToJSError` and applies
it at both rethrow sites. It preserves the exception's `name` and its existing `userInfo` entries so
any predicate-based handling is unaffected, and prefixes `reason` with `<module>.<method>` to match
the sync path's wording. A freshly constructed `NSException` captures its call stack at `throw`
rather than at the original raise, so the raise-site return addresses are carried across in
`userInfo` and nothing is lost.
Behaviour is otherwise unchanged: the exception is still thrown, on the same thread, at the same
point, with the same name. Nothing is caught, swallowed, logged away, or downgraded.
Reviewers should expect the crash grouping to change: the existing aggregate bucket will drain and
be replaced by per-module buckets. That is the point of the change, but it is worth knowing before
it happens.
Changelog:
[iOS][Fixed] - Include the module and method name in exceptions rethrown from async and void TurboModule calls
Reviewed By: javache
Differential Revision: D118144605
fbshipit-source-id: fb51936e73c7705ae4e23f650834d2c66e66a50e
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58295
This is to investigate a crash on ios in C++ Animated rollout.
On iOS, Native Animated drives frames from a `CADisplayLink` on the main run
loop. While the app is inactive — which includes the whole
`UIApplicationWillEnterForeground` → `UIApplicationDidBecomeActive` transition
— it is not presenting, so a frame rendered then is never seen. Its commit and
synchronous per-view updates still run on the main thread though, competing
with the work the app must complete to become responsive.
Adds `initWithSkipFramesDuringForegroundTransition:` to
`RCTAnimatedModuleProvider`, declared in a new
`RCTAnimatedModuleProvider+Private.h`. When YES, `_onDisplayLinkTick` returns
early while `applicationState == UIApplicationStateInactive`.
**The public API is unchanged.** `RCTAnimatedModuleProvider.h` is untouched and
the C++ API snapshots have no delta — `+Private.h` is in the ReactApple
`exclude_patterns`. Plain `init` still exists and defaults to NO, so every
existing caller is unaffected; only hosts that opt in via the private header see
different behaviour.
Two properties worth being explicit about:
- **The clock is not stopped, only the frame is skipped.** `AnimationDriver`
computes progress from a timestamp
(`timeDeltaMs = frameTimeMs - startFrameTimeMs_`), so the first frame after
activation resolves to the value the animation should have reached rather
than resuming from where it was suspended.
- **Frames are not skipped while backgrounded** — `Background` is not
`Inactive`. Completion handlers, and any app logic they drive, are therefore
delayed by at most the length of the transition, not by the time spent in the
background.
Reading `applicationState` rather than tracking lifecycle notifications also
avoids a failure mode: a mirrored flag must be cleared on every path out of the
transition, including an abandoned foregrounding (a `willEnterForeground` with
no following `didBecomeActive`), or frames are skipped indefinitely. There is no
such state to get stuck here.
`UIApplicationStateInactive` also covers other non-presenting moments — Control
Center, the app switcher, an incoming call banner. Skipping frames there is
harmless for the same reason: the clock keeps running and the first frame after
activation is correct.
The check sits inside the file's existing `TARGET_OS_OSX` guard, since
`UIApplication` is iOS-only and this translation unit also builds for macOS.
Changelog:
[Internal]
Reviewed By: javache, christophpurrer
Differential Revision: D118188111
fbshipit-source-id: c9f19fafd7bc6f07649a7160fd71b02de888f879
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58283
Reclassifies `react/renderer/components/image:image` from public to "for frameworks" under the C++ stable API three-tier visibility model.
Consumers that opt into `RN_STRICT_API` now get a suppressible warning where they previously got an error pointing at the umbrella, and can acknowledge it with `RN_ALLOW_FRAMEWORKS`; without that flag the guards are inert, so no existing build changes behaviour.
Changelog: [Internal]
Reviewed By: christophpurrer, javache
Differential Revision: D118440296
fbshipit-source-id: 45faf64ef36d3c3c596b1b8c06408fc43d3b59f8
Summary:
`customTransformOptions.unstable_preserveClassPrivate` currently disables private-field and private-method transforms for every profile. With `hermes-legacy`, the preset still lowers the surrounding class syntax, and Babel then aborts because its class transform requires the private transforms.
Only preserve private syntax when the selected profile also preserves class syntax. Stable and canary Hermes profiles keep their existing experimental behavior; legacy profiles continue lowering private fields and methods together with classes instead of crashing.
## Changelog:
[GENERAL] [FIXED] - Keep private class transforms enabled for profiles that lower classes.
Pull Request resolved: https://github.com/react/react-native/pull/58253
Test Plan:
- Added a focused `hermes-legacy` regression containing both a private field and private method with the preservation option enabled.
- Exact baseline throws Babel's private-method transform error; the fixed preset compiles and emits the normal private-field helpers.
- Full preset Jest passes: 4/4 suites, 111/111 tests, 16 snapshots.
- Fresh Flow check reports 0 errors.
- Targeted no-ignore ESLint, Prettier, and `git diff --check` pass.
No breaking change: stable/canary preservation is unchanged, while an invalid legacy configuration now compiles correctly.
Reviewed By: javache
Differential Revision: D118438778
Pulled By: vzaidman
fbshipit-source-id: 650a70d8759b135cb06f9bd3f2b45b0ee766762b
Summary:
The React Native Babel preset statically replaces `Platform.select({...})` for the target platform. Its property scan currently stops at the first matching key, while JavaScript object-literal evaluation keeps the last duplicate definition. For example, `Platform.select({ios: 1, ios: 2})` runs as `2` but the preset compiles it to `1`.
Scan the already-validated static properties from the end so compiled output matches runtime semantics while preserving O(n), allocation-free lookup. Metro has a parallel transform that can run first; companion [Metro PR https://github.com/react/react-native/issues/1889](https://github.com/react/metro/pull/1889) applies the same correction so output remains transform-order independent.
## Changelog:
[GENERAL] [FIXED] - Inline the last duplicate key from static Platform.select object literals.
Pull Request resolved: https://github.com/react/react-native/pull/58249
Test Plan:
- Added a focused preset regression; pristine main emits `const value=1`, while the fix emits `const value=2`.
- Full preset Jest passes: 4/4 suites, 111/111 tests, 16 snapshots.
- Fresh Flow check reports 0 errors.
- Targeted no-ignore ESLint, Prettier, and `git diff --check` pass.
No behavior changes for object literals without duplicate static keys; no UI change.
Reviewed By: christophpurrer
Differential Revision: D118499490
Pulled By: vzaidman
fbshipit-source-id: 3bd58c44c70415c57ed02266a5af2eea242471e4
Summary:
Replace the immediate template-app startup assertion with `extendedWaitUntil` and a 60-second timeout.
The Android ARM64 debug app occasionally becomes accessibility-visible just after the existing assertion times out under native translation. This failed all three attempts in [run 33609361836](https://github.com/react/react-native/actions/runs/33609361836/job/100196578829) and [run 33540863593](https://github.com/react/react-native/actions/runs/33540863593/job/99984608541). In the captured failure artifact, both the screenshot and XML hierarchy contain `Welcome to React Native`, indicating a startup/accessibility timing race rather than an app failure.
Release runs remain fast because `extendedWaitUntil` returns as soon as the element is visible.
## Changelog:
[INTERNAL] [FIXED] - Wait for the template app to become visible in Maestro E2E tests.
Pull Request resolved: https://github.com/react/react-native/pull/58289
Test Plan:
- `MAESTRO_CLI_NO_ANALYTICS=1 maestro check-syntax scripts/e2e/.maestro/start.yml` — passed (`OK`)
- `./node_modules/.bin/prettier --check scripts/e2e/.maestro/start.yml` — passed
- `git diff --check` — passed
- Inspected the failing Android debug artifact: the expected text is present in both the final screenshot and accessibility hierarchy.
Reviewed By: christophpurrer
Differential Revision: D118457123
Pulled By: cortinico
fbshipit-source-id: d2f5232482933e1decb13a9b2dac7911b205db4f
Summary:
Run the RNTester Image flow keyboard dismissal only on Android.
Android needs this step because the keyboard obscures the platform test results control. On iOS, the keyboard can dismiss automatically before Maestro reaches `hideKeyboard`, causing the flow to fail with `Could not hide the keyboard`. This has occurred repeatedly in Maestro Cloud since https://github.com/react/react-native/issues/58272 landed; for example, [run 33517266090](https://github.com/react/react-native/actions/runs/33517266090/job/99902026553).
The flow passed in Maestro Cloud iOS while the dismissal was absent, and the existing platform condition syntax is already used by the neighboring Image flows.
## Changelog:
[INTERNAL] [FIXED] - Avoid dismissing an already-hidden keyboard in the iOS Maestro Image flow.
Pull Request resolved: https://github.com/react/react-native/pull/58288
Test Plan:
- `MAESTRO_CLI_NO_ANALYTICS=1 maestro check-syntax packages/rn-tester/.maestro/image.yml` — passed (`OK`)
- `./node_modules/.bin/prettier --check packages/rn-tester/.maestro/image.yml` — passed
- `git diff --check` — passed
- Confirmed the Android dismissal remains present behind `platform: Android`.
Reviewed By: christophpurrer
Differential Revision: D118457013
Pulled By: cortinico
fbshipit-source-id: a8cb212004be0d9eeeff40e148f5d5f7ebee393a
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58297
`PointerEvent.createW3CPointerEvent` built its payload map, then read one field
straight back out of that same half-built map to compute another field:
```
pointerEvent.putInt("buttons", getButtons(_eventName, pointerType, buttonState))
...
getPressure(pointerEvent.getInt("buttons"), _eventName)
```
Reading from a `WritableNativeMap` while still writing to it is not free and not
safe:
- `ReadableNativeMap.getInt` materialises the *whole* map across JNI
(`importKeys` + `importValues`) and memoises the result in `keysStorage` /
`localMapStorage`. Every subsequent `put*` on the same instance then leaves
those caches stale, so a later Kotlin-side read of the map (`hasKey`,
`toHashMap`) does not see `pressure`, `tangentialPressure`,
`hitPathForEventListener` or the modifier keys.
- It happens on the pointer-event hot path, once per pointer index per dispatch,
purely to recover a value the caller already has in hand.
Keep the value in a local and pass it to `getPressure` directly. The payload is
byte-for-byte identical: `getInt` returns exactly the `Int` that `putInt` stored,
so `getPressure` receives the same argument as before.
Changelog:
[Internal]
Reviewed By: christophpurrer
Differential Revision: D118471070
fbshipit-source-id: 79b06256e8e6e245bcd050a5faa666202fa7a068