Summary:
Replaces https://github.com/react/react-native/issues/57352.
Self-register commands from the `community-cli-plugin` package via `react-native.config.js` — meaning we can remove the redirect within `packages/react-native/react-native.config.js`.
Progress towards removing `community-cli-plugin` as a direct dep of `react-native`, and paired with https://github.com/react-native-community/template/pull/235.
RNTester and HelloWorld list `react-native/community-cli-plugin` in `devDependencies`, as the template now does (react-native-community/template#235).
Changelog:
[General][Breaking] - `react-native/community-cli-plugin` will no longer be auto-detected from `react-native`. It must now be specified in `devDependencies`.
Pull Request resolved: https://github.com/react/react-native/pull/58670
Test Plan:
Compared `react-native config` output with `react-native-community/cli` 20.2.0.
**RNTester**
- ✅ Commands, platforms, and project config are unchanged from `main`
- ✅ Removing the new `react-native/community-cli-plugin` devDependency drops `bundle`, `start`, `spm`, and `codegen`, so they are registered by plugin discovery
**Template-shaped app** (plugin in `devDependencies`, no project `react-native.config.js`)
- ✅ `bundle`, `start`, `spm`, and `codegen` are registered
Reviewed By: christophpurrer, cortinico
Differential Revision: D121634885
Pulled By: Abbondanzo
fbshipit-source-id: e97c9f820d3c597233ef4a7ddaaf1b752f1f7688
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58631
Fantom's CI retries use Jest's `--onlyFailures` mode. Jest 29's default sequencer caches suite-level runtime errors as passing because they contain no failed test cases, so retries select no suites.
See https://github.com/react/react-native/actions/runs/35630015753/job/106440689782?pr=58624 of an example of this, where retries didn't actually do anything
Add a Fantom-specific sequencer that marks runtime-error suites as failed only for cache bookkeeping. This preserves the original test reporting while ensuring targeted retries rerun the crashed suite.
Changelog: [Internal]
Reviewed By: cipolleschi
Differential Revision: D121063351
fbshipit-source-id: e24737cc247ea0e11aa04dac74d557a3f41f9db6
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58605
Use global DOM APIs, supported React Native entry points, and package-relative implementation imports throughout Fantom. Use the renderer-only private interface for the existing public-instance conversion helpers instead of importing Node internals.
Changelog: [Internal]
Reviewed By: cipolleschi
Differential Revision: D120717572
fbshipit-source-id: 1aae11b7b9434c783d42ca289e2c6edd17aa887c
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58603
Generate view configs and Codegen fixtures using supported React Native entry points or values derived from their exports. Generated view config modules can be emitted into arbitrary consumer package locations, so they cannot use a package-relative path back into React Native. Keep `ConditionallyIgnoredEventHandlers` centralized and expose it from the explicitly unstable compatibility entry point instead of duplicating its platform-specific semantics in generated output.
Changelog: [Internal]
Reviewed By: cipolleschi
Differential Revision: D120717571
fbshipit-source-id: 9f3ea06d393eb8702bbb3ef2767c2d7c5fde1315
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58573
Migrate the remaining Flow-visible deep imports in React Native tests. Use public DOM globals where their types are sufficient, and use relative imports for implementation-specific helpers, observer types, and native specs that are not publicly exported.
Changelog: [Internal]
Reviewed By: javache
Differential Revision: D120537585
fbshipit-source-id: ea494dd65c68cbd556ec31bea58aee22e5cc06b3
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58569
Replace Fantom test imports of internal Event, EventTarget, AbortController, and feature flag modules with supported exports and global DOM APIs. Add the missing static Event phase constants to the DOM Flow declarations so constructor constants remain typed, and route trusted-event coverage through `dispatchNativeEvent`.
Changelog: [Internal]
Reviewed By: mdvacca
Differential Revision: D120528709
fbshipit-source-id: 9d991904dbe1f4cb061a9629026a6fc3cbc3dd16
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58567
Replace eligible React Native deep imports in Fantom tests with package exports, Fantom APIs, DOM globals, and types derived from exported symbols. Keep implementation-specific imports where the public surface does not expose equivalent behavior or compatible Flow types.
Changelog: [Internal]
___
Reviewed By: cipolleschi
Differential Revision: D120517166
fbshipit-source-id: 6ba6ec2c6159cca6309f558ccf478c49220e85fc
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58554
Generate component descriptor headers through the public <React/ComponentRegistry.h> umbrella instead of directly including ComponentDescriptorProviderRegistry.h. Refresh codegen snapshots and the checked-in popup-menu binding, and export the ComponentRegistry dependency needed by that public generated header.
Changelog:
[Internal].
Reviewed By: cipolleschi
Differential Revision: D120317127
fbshipit-source-id: fedea53bbe65e22ae53ed00a7fde787b2581bfab
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58468
Reformat the Kotlin and Kotlin Gradle sources with the npm-backed ktfmt 0.59.0 command after Arcanist formatting has been disabled for OSS-exported sources.
Changelog: [Internal]
Reviewed By: javache
Differential Revision: D119504762
fbshipit-source-id: 8a594f04ad72bd2d42baa49e578a4b0fa926b6bf
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58469
TurboModules, Fabric and bridgeless are all unconditionally enabled in the New
Architecture, so every remaining flag on `DefaultNewArchitectureEntryPoint` was
dead configuration. Reduce it to the one thing it still selects: the release
level.
Removes the deprecated parameterized `load(...)` overloads, the `fabricEnabled`,
`turboModulesEnabled` and `concurrentReactEnabled` getters, and
`isConfigurationValid`. Call sites that passed `fabricEnabled` to
`DefaultReactActivityDelegate` now use its two-argument constructor, which
already ignored the flag.
Changelog:
[Android][Breaking] - Remove the deprecated `DefaultNewArchitectureEntryPoint.load(turboModulesEnabled, fabricEnabled)` overloads; use `load()` instead
[Android][Breaking] - Remove `DefaultNewArchitectureEntryPoint.fabricEnabled`, `turboModulesEnabled`, `concurrentReactEnabled` and `isConfigurationValid`
Reviewed By: javache
Differential Revision: D119370657
fbshipit-source-id: 4964d5163af9bc1a74e3a4b9ae6933df98683e5f
Summary:
> Stack 3/3 — parent: `feat/LayoutEventEmitter`. Review the two parents first.
Implements the [`ResizeObserver`](https://drafts.csswg.org/resize-observer/) Web API for the New Architecture, behind the `enableResizeObserverByDefault` flag (off by default).
The motivation is Web compatibility, and it's more capable than `onLayout`: callers pick which box to observe (`content-box`, `border-box`, `device-pixel-content-box`) and the sizes for those boxes are delivered in the notification.
The design is as follows: JS `ResizeObserver`/`ResizeObserverEntry`/`ResizeObserverSize` on top of a manager singleton and the `NativeResizeObserver` TurboModule, using the same notify + `takeRecords` pull model. In C++, `ResizeObserverManager` collects observed targets whose layout changed at commit time (via `shadowTreeDidCommit`) and then computes and delivers observations in the event loop's "update the rendering" step (`RuntimeSchedulerResizeObserverDelegate::runResizeObservations`), as the spec requires. Requires bridgeless + the modern event loop; the legacy scheduler gets a no-op delegate.
`runResizeObservations` implements the spec's depth-increasing gather/broadcast loop: each round gathers observations deeper than the shallowest target delivered in the previous round, so a callback that synchronously resizes or observes a shallower node is still delivered within the same tick.
Known deviations from the spec (each pinned by a test):
- Resizes triggered from a callback via a React state update are delivered on the next tick rather than within the current loop, because RN has no synchronous re-layout. Callbacks that resize or `observe()` synchronously do run further rounds in the same tick, and report `ResizeObserver loop completed with undelivered notifications` when an observation is left undelivered.
- The loop carries a hard cap of 100 iterations on top of the spec's depth rule. Reaching the cap reports the loop error and stops, so a pathological callback degrades to a log line instead of a frozen app.
- Re-observing a target with the same box is a no-op and does not re-deliver. This matches browsers, not the literal `observe()` algorithm.
- Callback order across observers follows first-`observe()` order rather than construction order.
## Changelog:
[INTERNAL] [ADDED] - Add the `ResizeObserver` API, behind the `enableResizeObserverByDefault` feature flag
Pull Request resolved: https://github.com/react/react-native/pull/57723
Test Plan:
- Fantom `ResizeObserver-itest.js` covers many test scenarios.
- rn-tester has `ResizeObserver` examples (box sizes, text, visibility); verified initial, resize, and animation-driven delivery there.
- `RuntimeSchedulerTest.cpp` new test scenarios for update rendering loop.
Reviewed By: christophpurrer
Differential Revision: D114045415
Pulled By: javache
fbshipit-source-id: a561d5321ba45adb35f46ffb0cf26ad78eb3bae6
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57936
`react/cxxstableapi` is a header-only module — the stable API guards are pure
preprocessor headers with no compilable source. Under `use_frameworks!`,
CocoaPods emits a `PBXAggregateTarget` for a pod with no compilable sources, and
an aggregate target produces no `.framework`, so pods depending on
`React-cxxstableapi` cannot resolve the guard headers.
Add an anchor translation unit so the pod has one source and CocoaPods emits a
real framework target instead, and widen the podspec's build-from-source glob to
pick it up. The prebuilt glob stays headers-only, since prebuilt pods do not
generate frameworks. This mirrors the existing `CSSDummy.cpp` anchor for the
header-only `React-renderercss` pod.
Also register `react/cxxstableapi` as a subdirectory of the Fantom tester CMake
build so the guard headers resolve there.
Changelog: [Internal]
Reviewed By: cortinico
Differential Revision: D115859623
fbshipit-source-id: 47e63560e1478ad507d1f28f053b925438232ea4
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57783
# Changelog: [Internal]
Adds the `enableConditionalUseWarning` dynamic React feature flag, which the React renderer reads from `ReactNativeInternalFeatureFlags`. The flag gates the new warning for conditional use of `use()` based on cache state: https://react.dev/warnings/conditional-use-of-use
This is a dev-only warning, I don't see any reasons to control this via gk.
Reviewed By: antonk52
Differential Revision: D114407789
fbshipit-source-id: d63dd09180e6560a82d178610c7ae24b9e31b65e
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57718
**Context**
Replaces https://github.com/react/react-native/pull/57709, which identified a real bug in 0.87 from the combination of:
- https://github.com/react/react-native/pull/57276
- https://github.com/react/react-native/pull/57652
```
$ npx react-native spm add
error Cannot find module '.../node_modules/react-native/scripts/setup-apple-spm'
$ npx react-native codegen
error Cannot find module '.../node_modules/react-native/scripts/codegen/generate-artifacts-executor'
```
**This diff**
- Fix — and exclusively switch to — extensionless imports rather than requiring `.js`.
- Update in-repo consumers.
The previous single mapping is now an extension-aware mapping:
- `./scripts/*` now appends `.js`, so `react-native/scripts/foo` resolves to `foo.js`.
- `.sh` and `.rb` stay reachable via explicit `./scripts/*.sh` and `./scripts/*.rb` passthrough patterns.
**Impact**
- Explicit `react-native/scripts/*.js` specifiers no longer resolve, so JavaScript paths must be imported without an extension.
- Files under `scripts/` with extensions other than `.js`, `.sh`, or `.rb` are no longer exposed through `./scripts/*`.
- These have no open source consumers.
Changelog:
[General][Fixed] - (RC4 only, drop for main changelog): `react-native/scripts/*` imports once again expand `.js` extensions
[General][Breaking] - Extensionless `react-native/scripts/*` imports are now **mandated**; explicit `.js` import specifiers are rejected.
Reviewed By: rubennorte
Differential Revision: D113898792
fbshipit-source-id: d72f60be2c08ab97871e336645856c9029e74ae2
Summary:
Use an asset catalog for images on iOS. At build time, `react-native-xcode.sh` has the bundler emit packager image assets into a staging asset catalog (`--asset-catalog-dest`, already in `react-native/community-cli-plugin`), compiles it with `actool` into an `RNAssets.bundle` inside the app, and the native image loader resolves images by name from that bundle's `Assets.car` with `[UIImage imageNamed:inBundle:]` instead of reading loose files.
Properties worth calling out:
- **One opt-in switch, no project changes.** The feature is gated on the `RCTUseAssetCatalog` key in the app's Info.plist, and that key is the single source of truth: the native loader reads it (a build-time constant, read once), and `react-native-xcode.sh` reads the same key to decide whether to bundle images into the catalog — so the build and the runtime cannot disagree on where image assets live. Because the script owns the catalog end to end (staged in derived files, compiled into the app's resources next to `main.jsbundle`), **migration is adding one Info.plist key** — no `.xcassets` to create, no build-phase or project changes.
- **No fallback.** The catalog path is a single lookup with no filesystem fallback — a mis-bundled asset logs an `RCTLogError` (instead of silently rendering nothing) rather than adding an `fs` stat to the hot path.
- **Parity with the CLI, OTA-safe.** The native side resolves a catalog name only for what the CLI actually emits into the catalog: png/jpg/jpeg under main-bundle `assets/…` (mirroring `isCatalogAsset`). Everything else — gif/webp packager assets, `.bundle` sub-bundles, OTA assets outside the main bundle — falls through to the existing loader. (This also adds `jpeg` to `RCTIsImageAssetsPath`, which previously listed only `png`/`jpg` — an oversight, since `.jpeg` is the same kind of bundled image; it is now treated like `png`/`jpg` regardless of the catalog.)
- **No interference with Xcode's own asset pipeline.** The app's `Images.xcassets`, asset symbol generation (`UIImage(resource:)`), and `CompileAssetCatalog` are untouched: the RN catalog never enters the Xcode project, so there are no build-phase ordering constraints and nothing to disable.
## Changelog:
[iOS] [Added] - Use asset catalog for ios images
## Performance
**What was measured:** the time to *resolve* an asset to a `UIImage` inside `RCTImageFromLocalAssetURL` — a compiled-catalog name lookup vs. the legacy `imageNamed:` search + `imageWithContentsOfFile:` on loose files. Decode is deferred in both paths (and costs the same), so this is resolve latency, not end-to-end render time. It matters because `RCTLocalAssetImageLoader` loads local assets synchronously to avoid flicker, so this time sits on the critical path once per distinct image. Setup: RNTester, Release, new arch, iOS simulator, first load of each distinct image (UIKit caches repeats — repeat loads are ~10 µs in both builds).
Raw per-load numbers (final implementation, `RNAssets.bundle`), in load order:
| # | image | catalog (µs) | filesystem (µs) |
|---|---|---:|---:|
| 1 | `searchicon` ¹ | 1,081 | 4,497 |
| 2 | `bottomnavcomponentsicondark` | 320 | 710 |
| 3 | `bottomnavplaygroundsiconlight` | 147 | 422 |
| 4 | `bottomnavapisiconlight` | 29 | 352 |
| 5 | `bottomnavcomponentsiconlight` | 320 | 1,410 |
| 6 | `uie_thumb_normal` | 67 | 667 |
| 7 | `uie_thumb_selected` | 32 | 468 |
| 8 | `uie_comment_normal` | 26 | 454 |
| 9 | `uie_comment_highlighted` | 31 | 671 |
| 10 | `verylargeimage` ² | 30 | 1,855 |
| 11 | `alphahotdog` | 171 | 592 |
¹ First load in each build pays one-time costs: mapping `Assets.car` on the catalog side, ImageIO/framework warm-up + first disk touch on the filesystem side.
² Resolve only — the large image's decode cost is unchanged, so its end-to-end win is much smaller than this row suggests.
Every image is faster from the catalog: median 67 µs vs 667 µs (**10×**; an earlier run of the same benchmark measured 47 µs vs 719 µs, ~15× — run-to-run variance, same order either way). The mechanism: the catalog is a single memory-mapped, indexed archive (one name lookup, no per-image syscalls), while the loose-file path does an `imageNamed:` search over several filename permutations plus a per-image file open.
The URL→catalog-name derivation on the native side is a single character pass with no regex; benchmarked against a straightforward regex-based implementation of the same transform it measures 4.9 µs vs 11.0 µs per call (2.2×, Debug build, including the shared URL→bundle-path resolution both share), so the name mapping is a negligible part of the lookup.
**App thinning:** verified that App Store slicing thins the `Assets.car` inside `RNAssets.bundle` exactly like the app's own catalog. Test: a fixture app with a 1x/2x/3x imageset in both its main `Images.xcassets` and an actool-compiled `RNAssets.bundle`, archived and exported with `thinning` for a 3x device — both cars were sliced to 3x-only. So unused scales are stripped per device (unlike today's loose packager files, which ship every scale to every device).
## Migration
To opt an app in, add to its `Info.plist`:
```xml
<key>RCTUseAssetCatalog</key>
<true/>
```
That's the entire migration — no `.xcassets` to create, no build-phase or project changes. Notes:
- **Do a clean build after changing the key.** Incremental builds don't remove image assets a previous build placed with the other setting (unused, but dead weight in local builds; archives are unaffected).
- The key must be a literal value in the app's source Info.plist: the build script reads it with PlistBuddy (accepting the same value forms the runtime `boolValue` check accepts), so build-setting substitution or fully generated Info.plists (`GENERATE_INFOPLIST_FILE`) aren't seen by the script and stay on the legacy path. If bundling happens outside `react-native-xcode.sh` (custom CI calling `react-native bundle` directly) while the key is enabled, the native side detects the missing `RNAssets.bundle` and logs an actionable error instead of silently rendering nothing.
- Incomplete but valid scale sets degrade gracefully: an imageset with, say, only a `2x` (no `3x`) is kept for a 3x device by App Store slicing and used at runtime — verified with a thinned export. Only a *non-integer*-only asset (e.g. an Android-density `1.5x` with no `1x`/`2x`/`3x` variant, which iOS asset catalogs cannot represent) is unsupported: `actool` drops it with an `Unknown scale value` warning in the build log and the runtime logs an error. That's a rare antipattern; a `community-cli-plugin` follow-up will turn it into a clear build-time error at the source (it has the scale and asset path), rather than this repo re-parsing actool output.
- OTA updates keep working: assets delivered outside the main bundle never resolve to the catalog and use the regular loader.
- Docs follow-up: a section on the website's Images page (`react-native-website`) and the one-line opt-in in `react-native-community/template` will be separate PRs, timed with the release that ships this.
Pull Request resolved: https://github.com/react/react-native/pull/30129
Test Plan:
RNTester and `private/helloworld` both opt in (`RCTUseAssetCatalog=YES` in their Info.plists — the only change an app needs), so CI covers the catalog path on both app shapes. The new-project template lives in `react-native-community/template` and will get the same one-line opt-in in a follow-up PR there. To test locally with RNTester:
1. In Xcode, edit the RNTester scheme → set Build Configuration to Release.
2. Build & run. Local images render, served from `RNAssets.bundle/Assets.car`; the app contains no loose packager png/jpg files.
Unit coverage in `RCTURLUtilsTests` (`testAssetCatalogNameForURL`), asserting the identifiers the CLI generates: scale-suffix stripping (including non-integer `1.5x`), folder encoding, illegal-char removal, jpeg vs. non-catalog types (gif), out-of-project-root assets, query strings, non-packager paths, and nil.
Mac Catalyst: verified end-to-end by building rn-tester as a Mac Catalyst app — the catalog compiles (via the Catalyst-specific `--platform macosx --ui-framework-family uikit` actool invocation) into `RNTester.app/Contents/Resources/RNAssets.bundle` with all packager images and no loose files, and the runtime uses the same `imageNamed:inBundle:` mechanism CocoaPods resource bundles use on Catalyst. (rn-tester doesn't ship a Catalyst config, so this isn't in CI, but the build is clean.)
Reviewed By: cipolleschi
Differential Revision: D40095766
Pulled By: javache
fbshipit-source-id: 18dfcb47ae5185ef279b20dd0087de9a31e930b4
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
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57587
Adds rethrow in catch blocks when `startJSSamplingProfiler()` fails, preventing the `finally` block from attempting to stop a profiler that was never started.
Changelog: [Internal]
Reviewed By: thegreatercurve
Differential Revision: D112405579
fbshipit-source-id: 4b1cc6746d8ba29df99be57e583ee06ac742c12c
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57355
Changelog: [INTERNAL] Fix Dependabot security update for concurrent-ruby in react-native
The Dependabot GitHub Action on `react/react-native` `main` has been failing repeatedly because of `concurrent-ruby`. A security advisory marks `concurrent-ruby < 1.3.7` as affected (patched in `1.3.7`), but all three RN Gemfiles pin `gem 'concurrent-ruby', '<= 1.3.4'`. Dependabot cannot satisfy the advisory under that pin, so it opens a security PR to bump to `1.3.7` and then, on every subsequent run, reports `pull_request_exists_for_latest_version` as a hard error — failing the check and regenerating the internal CI task.
The `<= 1.3.4` upper bound was originally added because `concurrent-ruby 1.3.5` dropped its `logger` dependency, which broke older `activesupport`/CocoaPods setups. That cause is already mitigated: every Gemfile now explicitly lists `gem 'logger'`. The upper-bound pin is therefore obsolete.
This change relaxes the constraint from `<= 1.3.4` to `>= 1.3.7` in all three Gemfiles (root, `private/helloworld`, `packages/rn-tester`) and updates the two corresponding `Gemfile.lock` files to resolve `concurrent-ruby 1.3.7`. `1.3.7` introduces no new transitive dependencies over `1.3.4`, so no other lockfile entries change. With the advisory satisfied on `main`, Dependabot stops recreating the security PR and the recurring check failure stops.
Reviewed By: javache
Differential Revision: D109967250
fbshipit-source-id: 88f702bc6677053456557591cfd703776bb6c018
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
Summary:
https://github.com/react/react-native/issues/57481 removed the `react-native/jest-preset.js` redirect module (and the `react-native/jest-preset` public export), but the in-repo `private/helloworld` app still referenced `preset: 'react-native'` in its Jest config. This breaks `yarn test` in the `test_ios_helloworld` CI job (which cascade-cancels the rest of the iOS matrix and turns the e2e retry `report` jobs red):
```
● Validation Error:
Module react-native should have "jest-preset.js" or "jest-preset.json" file at the root.
```
This migrates HelloWorld to the standalone `react-native/jest-preset` package — the documented migration path (see `packages/jest-preset/README.md`).
## Changes
- `private/helloworld/jest.config.js`: `preset: 'react-native'` → `preset: 'react-native/jest-preset'`
- `private/helloworld/package.json`: add `react-native/jest-preset` devDependency (`0.87.0-main`, matching the sibling `react-native/*` packages)
## Changelog:
[Internal] [Fixed] - Fix HelloWorld Jest preset after `react-native/jest-preset` removal
Pull Request resolved: https://github.com/react/react-native/pull/57491
Test Plan:
- `cd private/helloworld && yarn test` resolves the preset and runs (previously failed with the validation error above).
- CI `test_ios_helloworld` job.
Reviewed By: cortinico
Differential Revision: D111215532
Pulled By: cipolleschi
fbshipit-source-id: 2d60de619060e384b4a5b662a6f588ea3e368433
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57486
`prettier --list-different` (run via `yarn format-check`) flagged the react-native-fantom `__docs__/README.md` as unformatted. Re-wrap the two affected prose lines to prettier's print width so the docs pass the formatting check.
No content changes; formatting only.
Changelog: [Internal]
___
Differential Revision: D111041556
fbshipit-source-id: cab15f502e941d908503e0873fe8cba12b48686f
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57467
Adds a convention to the Fantom README recommending that tests exercise React Native through its public API (importing from `react-native`) whenever possible, rather than reaching into internal modules. Exercising the public surface also drives the underlying native (Fabric/TurboModules) code, so tests stay close to real usage and are more resilient to internal refactors.
Changelog:
[Internal]
Reviewed By: christophpurrer
Differential Revision: D110918650
fbshipit-source-id: b19dc4b4a380030196a4e83890aae6720a64c77f
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
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57368
**Context**
This stack intends to relocate the `AssetRegistry` API from `react-native/assets-registry` into `react-native` — addressing runtime safety and public deep imports issues (1.0 and JS Stable API blockers).
**This diff**
Create a new `react-native/asset-utils` package, intended for internal/framework use (read: **will not be an end user concern**). This re-houses `react-native/assets-registry/path-support.js`.
Stacked with the next two diffs, this contributes to the 0.87 objective to delete `react-native/assets-registry` towards install-layout-safe behaviour and JS deep import removal.
- (Temporarily, this leaves two copies of `path-support.js` until I enact the package removal down the stack.)
This change also enables us to de-duplicate `assetPathUtils.js` inside `community-cli-plugin` and use one source of truth.
- Additionally, we have fbsource consumers of this util that cannot have a circular Buck dep on `react-native`, so the main package was not a suitable relocation point (secondarily to not adding an awkward new public API here).
**Changes**
- Add `react-native/asset-utils` (`packages/asset-utils/`): `src/AssetPathUtils.js` containing Android path helpers and tests.
- De-duplicate usages in `community-cli-plugin`: delete `src/commands/bundle/assetPathUtils.js`.
Changelog:
[General][Added] - Introduce `react-native/asset-utils` package (relocates Android path utils for libraries/frameworks)
Reviewed By: robhogan
Differential Revision: D110045272
fbshipit-source-id: 781e75c58ae9ce7f0fa860e66beca3b9990d26ea
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57443
The Fantom REPL (`yarn fantom-cli`) crashed on startup with `TypeError: Cannot read properties of undefined (reading 'loadConfig')`. `metro` is a CommonJS module that only provides named exports, so the default import `import Metro from 'metro'` resolves to `undefined` under the Babel interop used to run the REPL, and any access such as `Metro.loadConfig` throws.
Switch to a namespace import (`import * as Metro from 'metro'`), matching how metro is already imported in the Fantom global setup.
Changelog: [Internal]
___
Reviewed By: javache
Differential Revision: D110754395
fbshipit-source-id: f1c7c415f96a6adeb6dde12919983aa9a5a819a4
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57401
The `FANTOM_ENABLE_CPP_DEBUGGING` environment variable was kept only as a legacy alias for `FANTOM_DEBUG_CPP`. Remove it from Fantom so `FANTOM_DEBUG_CPP` is the single supported way to enable the C++ debugger.
Changelog: [Internal]
Reviewed By: sammy-SC
Differential Revision: D110324557
fbshipit-source-id: 2cbde4736137db792b8b99d1806c146e3094ca4b
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
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57378
Refactor Metro imports to:
- Remove use of deprecated default object export, prefer named/namespace exports.
- Prefer imports from `metro`, remove public dependencies on `metro-core` and `metro-config` from `react-native/community-cli-plugin`.
Changelog: [Internal]
Reviewed By: javache
Differential Revision: D110177050
fbshipit-source-id: f21a561d40d13f354bc56cdc50d6e6d6843877cc
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57358
The `enableEagerAlternateStateNodeCleanup` flag is no longer read by the renderer, so the feature-flag definition and the two prelude overrides that forced it on become dead code.
[Internal]
Reviewed By: lenaic
Differential Revision: D110043719
fbshipit-source-id: 24a7e2b85ec60da1cb1855f444bba5e1e6fc4288
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57288https://github.com/facebook/react-native/pull/56922 intended to prevent this package publishing to npm but didn't - we've been continuing to publish it in nightlies.
`scripts/shared/monorepoUtils.js` filters with `packageJson.private !== true || includePrivate`, i.e. the `private` field is load-bearing, not the path. All other packages in `private/` have `package.json#private: true`.
Changelog: [Internal] - the breaking change is already noted in https://github.com/react/react-native/pull/56922 , no release / cut since.
Reviewed By: cortinico
Differential Revision: D109153641
fbshipit-source-id: f86ed921dbc7a6b020c57e7d18e6cae5c57b5f1e
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57274
Fantom could not deterministically fire delayed JS timers: the timer registry it used scheduled timers on a real background thread with real wall-clock delays, so `setTimeout(fn, 100)`/`setInterval` callbacks never fired within a synchronous test. This adds a mockable timer registry and a public Fantom API to control it from JS, similar to `installHighResTimeStampMock`.
- New `Fantom.installTimerMock()` returns a controller with `advanceTimersByTime(ms)`, `runAllTimers()`, `getPendingTimerCount()`, and `uninstall()` (jest fake-timer style). While installed, `setTimeout`/`setInterval` callbacks only fire when the virtual clock is advanced.
- New deterministic `FantomTimerRegistry` (no background thread) keyed off a virtual clock, injected via a new optional `platformTimerRegistryFactory` seam on `ReactInstanceConfig` (the default registry is unchanged for all other consumers).
- `PlatformTimerRegistry` gains a virtual `setTimerManager` (default no-op) so the registry can be wired polymorphically.
- Control flows from JS through new `NativeFantom` methods, the same way the high-res timestamp mock works.
Default (non-mock) behavior is preserved: zero-delay `setTimeout` still fires on the next work loop, and existing tests are unaffected.
Changelog: [Internal]
Reviewed By: christophpurrer
Differential Revision: D109017304
fbshipit-source-id: 8afe6fb2a39f470ae293038f6592c46535442dc2
Summary:
This package is published to npm, despite being under `private` - so I missed adding `repository` metadata to it as requried by trusted publish.
Changelog: [Internal]
Reviewed By: cortinico
Differential Revision: D109031681
fbshipit-source-id: 19ec7fbc63a50d13fbebf8e3c42f439038399ea5
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57272
Fantom integration tests declared with `fantom_mode dev` rely on debug-only native APIs (e.g. timer mocking via `installHighResTimeStampMock`) that are only compiled when the native tester is built in debug mode.
Under some build configurations the active platform pins the core build mode to optimized, so the preprocessor flag that gates those debug-only APIs is not defined and the tester is compiled in optimized mode. As a result, dev-mode tests that depend on those APIs throw at runtime (e.g. "Mocking timers is not supported in optimized builds").
A previous attempt stacked a build-mode constraint on the Hermes build mode setting, which the native preprocessor flags never read, so it had no effect. Stack the constraint on the core build mode setting that actually gates the flag instead, so the tester is compiled in the test's intended dev/opt mode.
Changelog: [Internal]
Reviewed By: ellemac123
Differential Revision: D109014401
fbshipit-source-id: a04d75d299e3d2a0d1ccabcc2629833ac7a9dbd6