191 Commits
Author SHA1 Message Date
Peter Abbondanzo 88b9c3fb7c Retry suite-level runtime failures (#58631)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58631

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

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

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

Changelog: [Internal]

Reviewed By: cipolleschi

Differential Revision: D121063351

fbshipit-source-id: e24737cc247ea0e11aa04dac74d557a3f41f9db6
2026-09-24 06:58:58 -07:00
Rubén Norte d6adb9f48a Remove React Native deep imports from Fantom (#58605)
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
2026-09-21 11:31:38 -07:00
Rubén Norte 4d4bb50786 Remove remaining test deep imports (#58573)
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
2026-09-18 07:27:28 -07:00
Rubén Norte 652d50111c Use global DOM types in Fantom tests (#58569)
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
2026-09-18 07:27:28 -07:00
Rubén Norte 7a6314090d Use public APIs in Fantom tests (#58567)
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
2026-09-18 07:27:28 -07:00
Dawid Małecki 271111c2bb Use ComponentRegistry umbrella in generated descriptors (#58554)
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
2026-09-17 12:06:33 -07:00
Nicola Corti d302be5aef Apply ktfmt 0.59.0 (#58468)
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
2026-09-15 11:23:27 -07:00
Jakub Piasecki 25b6fd57ff Add RN_BUILDING to fantom (#58392)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58392

Update Fantom build config to compile with `RN_BUILDING` defined, allowing all includes within Fantom.

Changelog: [Internal]

___

Differential Revision: D117860963

fbshipit-source-id: d83eb7e3d6d3d8e45efd3b1b49e68894c1c63b09
2026-09-08 02:04:52 -07:00
Sam Zhou fdcce4f673 Turn on experimental.new_this_typing in xplat (#58293)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58293

Changelog: [Internal]

Reviewed By: vzaidman

Differential Revision: D118513884

fbshipit-source-id: a33a81eab930ac29663410cf04163aebb87062ad
2026-09-02 13:03:29 -07:00
generatedunixname1026736676487289 2fa055f6a7 Upgrade Flow in fbsource (#58192)
Summary: Pull Request resolved: https://github.com/react/react-native/pull/58192

Reviewed By: SamChou19815

Differential Revision: D117992492

fbshipit-source-id: bc3a32b4420243b6675439e0840559b85507c3dd
2026-08-29 11:23:04 -07:00
Kamil Paradowski b03652af78 ResizeObserver Web API implementation (#57723)
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
2026-08-19 02:42:37 -07:00
Dawid Małecki b7f0baf8f9 Emit a real framework for React-cxxstableapi under use_frameworks! (#57936)
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
2026-08-13 08:20:05 -07:00
Ruslan Lesiutin 2bb56dc94b Add enableConditionalUseWarning React feature flag (#57783)
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
2026-08-03 05:40:14 -07:00
Sam Zhou e6fd1a3e7c Replace hermes-{parser,eslint} with flow-{parser,eslint} in OSS projects (#57772)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57772

Changelog: [Internal]

Reviewed By: gkz

Differential Revision: D114245899

fbshipit-source-id: fa42b5276a5f6fe0d22e301a4cfc438122d70e6d
2026-07-30 18:23:59 -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
Pieter De Baets 2bc248c535 Propage startJSSamplingProfiler error (#57587)
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
2026-07-17 02:43:24 -07:00
Sam Zhou a016e94b59 Redo D111190630: Stop using prettier-plugin-hermes-parser for formatting (#57537)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57537

Changelog: [Internal]

Reviewed By: gkz

Differential Revision: D111829105

fbshipit-source-id: 3309a22e737f68aca2d8d19f49e56bad955e5377
2026-07-13 17:48:27 -07:00
generatedunixname89002005232357 65af886291 Revert D111190630: Stop using prettier-plugin-hermes-parser for formatting
Differential Revision:
D111190630

Original commit changeset: e7ed7ee6f057

Original Phabricator Diff: D111190630

fbshipit-source-id: 49e33587fa084c181d64d35ac6bcf6ab73edfa5f
2026-07-13 16:42:37 -07:00
Sam Zhou 2235b8ec3f Stop using prettier-plugin-hermes-parser for formatting (#57505)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57505

Changelog: [Internal]

Reviewed By: gkz

Differential Revision: D111190630

fbshipit-source-id: e7ed7ee6f05701fbdaad1c8fad58c47f48344487
2026-07-13 15:57:35 -07:00
Nivaldo Bondança b31ba29d2d Update ktfmt component on FBS:master
Reviewed By: cortinico

Differential Revision: D110624565

fbshipit-source-id: c18b2b2fc22a8b060a30ae9bd2bc18af862e08f2
2026-07-12 14:57:47 -07:00
Rubén Norte 0df0be24ef Fix markdown formatting in react-native-fantom docs README (#57486)
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
2026-07-08 08:48:48 -07:00
Sam Zhou 537d867316 Bump to latest prettier (#57473)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57473

Changelog: [Internal]

Reviewed By: gkz

Differential Revision: D110952668

fbshipit-source-id: a2278dbe978b42d42f57ddea10a947703a181797
2026-07-08 05:24:04 -07:00
Rubén Norte 7a5ab34451 Document Fantom convention: prefer testing through the public API (#57467)
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
2026-07-08 00:45:28 -07:00
Rubén Norte af3a6519b3 Fix Fantom REPL crash from metro default import (#57443)
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
2026-07-06 04:29:55 -07:00
Rubén Norte 0fae86d0c7 Remove deprecated FANTOM_ENABLE_CPP_DEBUGGING environment variable (#57401)
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
2026-07-01 08:18:34 -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
Rob Hogan 014fe8b520 Refactor imports from Metro to avoid deprecated styles and prefer main package (#57378)
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
2026-06-30 09:42:04 -07:00
Pieter De Baets 610192ed9b Clean up enableEagerAlternateStateNodeCleanup (#57358)
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
2026-06-29 06:40:21 -07:00
Rubén Norte 2d491c0c75 Add deterministic timer mock to Fantom (#57274)
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
2026-06-19 05:13:56 -07:00
Rubén Norte e1b0c77507 Fix Fantom dev-mode tests when the tester is built in optimized mode (#57272)
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
2026-06-18 07:20:47 -07:00
Samuel Susla 79adce3942 Remove offscreen image request downgrading feature flag (#57226)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57226

This removes the experimental `enableImageRequestDowngradingForNonVisibleImages` feature flag and backs out the behavior it gated. When enabled, `ImageShadowNode` downgraded image requests to prefetch priority for images that layout determined did not intersect the viewport — threading an `ImageRequestPriority` through `ImageRequestParams` and the Apple image managers, and propagating per-node viewport frames during Yoga layout via `experimental_layoutOrigin`/`experimental_layoutFrame` on `LayoutContext`.

The flag defaulted to off and was never enabled in a release, and the gated behavior did not deliver the expected improvement, so the feature is removed entirely: `<Image>` once again always requests at immediate priority. This deletes the feature flag, the `ImageRequestPriority` enum and the `ImageRequestParams::priority` field, the priority parameter on `RCTImageManager`/`RCTSyncImageManager`/`RCTImageManagerProtocol`, the `experimental_layout*` `LayoutContext` fields and their Yoga propagation, the iOS request-priority debug overlay, and the associated Fantom test scaffolding. The generated feature-flag sources and the C++ API snapshots are regenerated accordingly.

Changelog: [Internal]

Reviewed By: javache

Differential Revision: D108411690

fbshipit-source-id: 1538ec699ed2857f3d3154d666fac43a1dc64cd1
2026-06-17 05:26:37 -07:00
Sam Zhou e0ed406590 Redo modern syntax rollout in react-native (#57034)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/57034

With D107165685, it should work this time.

Changelog: [Internal]

Reviewed By: gkz

Differential Revision: D107111468

fbshipit-source-id: 326b2911088d7c87c3564a578125eeaab9d0b8cc
2026-06-03 07:21:54 -07:00
Rubén Norte 833144fcec Revert recent Flow syntax codemods in react-native-github (#56998)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56998

Reverts the recent Flow syntax codemods applied across `packages/`, `private/`, and `scripts/` in react-native-github. Specifically restores the previous form for:

- `+T` / `+Instance` style variance annotations on generic type parameters that had been converted to the newer `out T` / `in T` keyword form.
- `+field:` covariant object/interface properties that had been converted to the `readonly field:` modifier form.
- `+[K in keyof T]:` mapped-type covariance that had been converted to `readonly [K in keyof T]:`.

These are purely Flow type-annotation changes with no runtime behavior impact, restoring the form that the rest of the toolchain (in particular Fantom) already supports.

Changelog: [Internal]

Reviewed By: christophpurrer

Differential Revision: D106813102

fbshipit-source-id: 6bf915d530e130eba9c9d96a2b6c3dc8853594d1
2026-05-29 14:09:58 -07:00
Rubén Norte 9199b3933a Add Fantom.getHostPlatform() to expose test runner host OS (#56990)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56990

Adds a new `Fantom.getHostPlatform()` API that returns the host
operating system where the Fantom test runner is running (e.g. 'linux',
'macos', 'windows', 'android'). This is different from React Native's
`Platform.OS`, which always reflects the React Native target platform
being tested.

The value is determined by the Node.js Jest runner (via
`process.platform`) and baked into the JS bundle through the existing
`setConstants(...)` pipeline, so no native changes are needed.

- Add `HostPlatform` type and `hostPlatform` field to
  `FantomRuntimeConstants`.
- Populate `hostPlatform` from the host platform in the entrypoint
  template (maps darwin -> macos, win32 -> windows, etc.).
- Expose `getHostPlatform()` from the public Fantom API.

Changelog: [Internal]

Reviewed By: javache

Differential Revision: D106669673

fbshipit-source-id: 6948e0c1eb0075131211d8c5099da96a87306b0a
2026-05-29 08:02:57 -07:00
Samuel Susla 5fbcc6bf89 Downgrade offscreen Fabric image requests to prefetch (#56976)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56976

changelog: [internal]

Use Fabric layout data to classify image shadow nodes as visible or offscreen on Apple platforms. Offscreen image requests now use `ImageRequestPriority::Prefetch`, which is bridged to the existing `RCTImageLoaderPriorityPrefetch` API, while visible images stay at `Immediate`. The new React Native feature flag defaults to `false` until app-specific gating wires it up.

Reviewed By: javache

Differential Revision: D106074485

fbshipit-source-id: 80ece75cf0d639be1fdbfdd5f19b838b7b64aba6
2026-05-27 07:09:25 -07:00
Marco Wang 09fc0432d1 Fix a few readonly 10/n (#56948)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56948

```
js1 flow-runner codemod flow/transformAllVariance --variance readonly --format-files=false
```

drop-conflicts

landed-with-radar-review

Reviewed By: SamChou19815

Differential Revision: D106144499

fbshipit-source-id: 85493334eae630d3dec7e5920633c076f8f09729
2026-05-22 22:27:46 -07:00
Riccardo Cipolleschi 0a5c8c6b4b Remove hermesV1Enabled Gradle property and simplify Hermes version resolution (#56733)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56733

  - Remove `hermesV1Enabled` / `react.hermesV1Enabled` Gradle property and all branching it controls
  - Rename `HERMES_V1_VERSION_NAME` to `HERMES_VERSION_NAME` in `version.properties`
  - Remove `hermesV1Enabled` from `PrivateReactExtension`, `ProjectUtils`, `PropertyUtils`, `ReactPlugin`
  - Simplify `DependencyUtils.Coordinates` to single Hermes version
  - Make `-DHERMESVM_HEAP_HV_MODE=HEAP_HV_PREFER32` CMake flag unconditional
  - Remove `-DHERMES_V1_ENABLED=1` CMake argument from `ReactAndroid` and Fantom builds
  - Delete `hermesV1Enabled=true` from `gradle.properties`
  - Update all Gradle plugin tests

## Changelog:
[Android][Removed] - Remove hermesV1Enabled and simplify the code

  ## Test plan
  - [x] Gradle plugin: `./gradlew -p packages/gradle-plugin build` — BUILD SUCCESSFUL, all tests pass
  - [x] Android: `./gradlew :packages:rn-tester:android:app:assembleDebug` — BUILD SUCCESSFUL

Reviewed By: cortinico

Differential Revision: D104244582

fbshipit-source-id: 7d12af5b934aac9d431e89d9a2eac41213c997a1
2026-05-11 12:55:12 -07:00
Rubén Norte 29d8405850 Improve Fantom documentation in __docs__/README.md (#56660)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56660

Expand `private/react-native-fantom/__docs__/README.md` so it's the single source of truth for Fantom usage.

Added sections:
- Updated the Usage example to import `setUpDefaultReactNativeEnvironment` and explicitly warn against `InitializeCore` (which installs LogBox and breaks Fantom's error handling). All real `-itest.js` files use this import.
- New `### Conventions` section: `__tests__` placement, `-benchmark-itest.js` suffix, using `Fantom.runTask()` for rendering, the `ensureInstance` helper, component-specific instance types, ref-based element access, testing imperative APIs / method timing / edge cases, `takeMountingManagerLogs` for command verification, and "don't oversimplify assertions" / "avoid trivial tests" guidance.
- New `### Assertions` section: prefer `.toEqual()` + inline JSX over `.toMatchSnapshot()`, full examples for `getRenderedOutput().toJSX()` with `includeLayoutMetrics` and the `props` filter, plus an element-level assertion example covering `tagName`, `getBoundingClientRect`, and child structure.
- New `### Limitations` section: cannot nest `runTask()`, subset of Jest API, tests must live under `packages/react-native`.
- New `#### C++ sampling profiler` subsection under Profiling, documenting `FANTOM_PROFILE_CPP` (parallel to the existing JS profiler section).

Pure API references (`setLogBoxCheckEnabled`, `dispatchNativeEvent`, `scheduleTask`, `enqueueNativeEvent`, `runOnUIThread`, `runWorkLoop`, `scrollTo`, `takeJSMemoryHeapSnapshot`, `createRoot` options, etc.) are not duplicated — they continue to live in the inline source docs in `src/index.js`, which the README points to.

Changelog: [Internal]

Reviewed By: mdvacca, cipolleschi

Differential Revision: D103217408

fbshipit-source-id: ff01523682961914d795ef400954bcb3ded19dc1
2026-04-30 10:15:37 -07:00
Christoph Purrer f41364d11d Fix unused parameter warnings in StubWebSocketClient.h (#56527)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56527

Removed parameter names from unused parameters in StubWebSocketClient stub implementation to fix clang-diagnostic-unused-parameter warnings. This stub class implements IWebSocketClient interface with empty method bodies, so all parameters were unused.

Changelog: [Internal]

Reviewed By: philIip

Differential Revision: D101110612

fbshipit-source-id: 859d7e630b6f0fd1836c5706a81f05ffd72471f7
2026-04-22 12:27:28 -07:00
Rubén Norte 5c55a61c1f Set hermes_build_mode constraint when building tester with coverage (#56541)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56541

The Fantom test runner spawns native `fantom-tester` binaries built in
either dev or opt mode based on each test's `fantom_mode` pragma. When
collecting C++ code coverage of the tester binary, however, the build
may switch to a coverage-instrumented build configuration that does not
define `REACT_NATIVE_DEBUG`.

That breaks dev-mode tests that rely on debug-only native APIs. For
example, `installHighResTimeStampMock` in
`private/react-native-fantom/tester/src/NativeFantom.cpp` is gated on
`#ifdef REACT_NATIVE_DEBUG` and throws "Mocking timers is not supported
in optimized builds" otherwise. Tests like `LongTasksAPI-itest.js` (no
`fantom_mode` pragma → defaults to dev) fail in CI coverage runs with
that error.

When invoking buck with coverage enabled, layer the `hermes_build_mode`
constraint on top of the build platform so `rn_build_mode()` (in
`tools/build_defs/oss/rn_defs.bzl`) picks up the right value and adds
`-DREACT_NATIVE_DEBUG` for dev tests.

Reviewed By: fkgozali

Differential Revision: D101832028

fbshipit-source-id: cfb5269dea846f41d9d1f9af1c5ff8bd5828085c
2026-04-21 11:15:04 -07:00
Rubén Norte dbd3255194 Build both coverage and non-coverage tester binaries in CI (#56538)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56538

The Fantom Jest `globalSetup` builds the `fantom-tester` native binaries
upfront, using `globalConfig.collectCoverage` to decide whether to build
the `-coverage` flavor.

However, `runner/coverageUtils.js`'s `shouldCollectCoverage()` returns
`false` for some tests even when `globalConfig.collectCoverage` is true:

- All benchmarks (filename matches `*Benchmark-itest.*`)
- Tests with the `fantom_disable_coverage` pragma

In CI coverage runs, those tests resolve their tester binary path with
`enableCoverage=false` (e.g. `fantom-tester-statichermesstable-opt`),
but `globalSetup` only built the `-coverage` variants, so spawn fails
with `ENOENT` and the test fails with an empty stdout/stderr and exit
code `-2`.

When `enableCoverage` is true, also build the non-coverage tester
variants so coverage-opt-out tests can find their binary.

Changelog: [Internal]

Reviewed By: javache

Differential Revision: D101819861

fbshipit-source-id: e82f7c8c548c9477d214e9265c813bf9b54ab141
2026-04-21 09:24:25 -07:00
Rubén Norte 5f69a91186 Document FANTOM_FORCE_CI_MODE for full local runs (#56531)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56531

Add a section to the Fantom `__docs__/README.md` that recommends running the full suite locally with `FANTOM_FORCE_CI_MODE=1`. In CI mode, `globalSetup` pre-builds the entire `(hermesVariant × enableOptimized)` binary matrix once up-front and per-test buck2 invocations are skipped, which eliminates buck2 daemon contention from the worker pool — a common source of sporadic build failures when many workers race to build different binary variants at the same time.

CI environments (`SANDCASTLE`, `GITHUB_ACTIONS`) already auto-detect this mode; this just documents it for local use.

Changelog: [Internal]

Reviewed By: andrewdacenko

Differential Revision: D101795648

fbshipit-source-id: 984bc8bfd034347b5aee0ff438b037e5eb9d41a8
2026-04-21 06:49:06 -07:00
Rubén Norte c1ffe9f2a0 Harden Metro bundle retry against file-watcher races (#56530)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56530

Each Fantom test writes a unique `\-<test>.js` entrypoint into
`.out/js-builds/` and then asks Metro to bundle it. Metro's file watcher
(metro-file-map's `FallbackWatcher` on Linux, debounced 100 ms) does not
always observe the new entrypoint by the time the HTTP request arrives,
especially when multiple workers are writing entrypoints concurrently.
The previous retry logic was too narrow:

- Only HTTP 404 was treated as retryable. Metro returns 404 only when the
  entry file path itself can't be resolved; an unresolved transitive
  dep (e.g. `setUpDefaultReactNativeEnvironment`) returns HTTP 500 with
  `{type: 'UnableToResolveError'}` — we'd throw immediately on that.
- Only 3 attempts with a flat 500 ms wait (~1 s total), which is not
  enough on a busy host with 8 workers writing entrypoints at once.

This results in ~30 spurious "Failed to request bundle from Metro: Unable
to resolve module ..." failures per run.

Refactor `createBundle` into a focused `fetchBundleWithRetry` helper that:

- Parses Metro's JSON error envelope (`{type, message, ...}` from
  `formatBundlingError`) once per response and uses `type` to decide
  whether to retry. Retries on HTTP 404, on HTTP 500 with
  `UnableToResolveError` or `ResourceNotFoundError`, and on transient
  `fetch` network errors. All other failures (transform errors, syntax
  errors, real config issues) throw immediately so we don't waste seconds
  on them.
- Uses exponential backoff (100 ms → 200 → 400 → 800 → 1.6 s, capped at
  2 s) with up to 10 attempts (~11 s total worst case).
- Surfaces a clean error message (parsed from the JSON envelope) when
  retries are exhausted.

Changelog: [Internal]

Reviewed By: andrewdacenko

Differential Revision: D101791796

fbshipit-source-id: 805ef9bc6e58fce7c1dc10d0cbbb7fdfa1fa24a5
2026-04-21 06:03:40 -07:00
Rubén Norte 0f9b8e4a62 Cap maxWorkers and bump heap to bound Fantom Metro memory (#56529)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56529

Fantom runs every test through a single shared Metro server (started in
`globalSetup`). Jest's default `maxWorkers` is `numCpus - 1`, so on a
high-core box (e.g. 176 CPUs) ~175 workers fire bundle requests at Metro
concurrently. Each in-flight request makes Metro materialize a full
dependency `Graph` (transformed modules, source maps, inverse-deps,
file-watcher subscription), which is hundreds of MB.

The per-test `DELETE` eviction added in D101652820 only releases that
memory after the bundle response completes, so the simultaneous in-flight
set still blows past the previous Node `--max-old-space-size=8192` ceiling
in `scripts/fantom.sh` — the Metro process aborts with
`FATAL ERROR: Ineffective mark-compacts near heap limit` after just a
handful of test suites.

Two coordinated changes that balance throughput and safety:

- `scripts/fantom.sh`: bump the Node heap from 8 GB to 16 GB so we have
  headroom over the observed steady-state peak.
- `private/react-native-fantom/config/jest.config.js`: cap `maxWorkers`
  at `min(numCpus - 1, 16)`. With 8 workers the heap peaked at ~3 GB
  (~400 MB / worker), so 16 workers fits comfortably under a 16 GB cap
  with ~40% headroom.

This is intentionally a balance rather than a hard worker cap — bumping
the heap alone would still leave 100+ in-flight graphs racing GC, and
capping workers alone leaves throughput on the table on big machines.

Changelog: [Internal]

Reviewed By: andrewdacenko

Differential Revision: D101791795

fbshipit-source-id: 035c7235c32303f7b7f1eb05698b2a5cba90edc9
2026-04-21 06:01:11 -07:00
Rubén Norte fd082b938b Re-throw errors from tasks and microtasks synchronously (#56513)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56513

Changelog: [internal]

Fantom previously did not propagate errors thrown inside `runTask` callbacks
(or microtasks queued by them) to Jest, so failing assertions inside tasks
were silently swallowed and only logged via `console.error`. Tests had to
work around this with manual `try`/`catch` blocks and a couple of
`it.skip`s with TODOs.

This installs a Fantom-specific global error handler (via `ErrorUtils.setGlobalHandler`)
that captures the first error reported during the current work loop into
`pendingError`. After `flushMessageQueue()` returns, `runWorkLoop()`
re-throws the captured error so it becomes observable as a Jest failure.

Only the first error in a work loop is re-thrown (subsequent ones are
typically follow-on noise), and `pendingError` is cleared at the start of
each work loop so errors captured during module setup do not spuriously
fail later loops. The post-loop `runLogBoxCheck()` continues to take
precedence, since LogBox diagnostics are more actionable.

With this in place:
- The 'should throw when running a task inside another task' test can use
  `expect(...).toThrow(...)` directly instead of manual try/catch.
- The two previously-skipped tests for re-throwing errors from tasks and
  microtasks are now enabled.

NOTE: this will cause some tests to start failing, but they're legit failures

Reviewed By: javache

Differential Revision: D101647822

fbshipit-source-id: b9cba056d46cc94a4f6dad5e3665266df62a0211
2026-04-21 03:29:54 -07:00
Pieter De Baets 3fb1fea57e Evict Metro bundle graphs after each Fantom test to prevent OOM (#56514)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56514

Changelog: [Internal]

Reviewed By: rubennorte

Differential Revision: D101652820

fbshipit-source-id: f7608fbf92a8fd2928434e74ad03bfc01b318d20
2026-04-20 10:56:52 -07:00
Rubén Norte def621f674 Move CI validation for debugCpp and profileCpp to EnvironmentOptions (#56464)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56464

Changelog: [internal]

Moved the CI validation checks for `debugCpp` and `profileCpp` from the `run()` function in `tester.js` to `validateEnvironmentVariables()` in `EnvironmentOptions.js`, alongside the existing CI/OSS validation for memory instrumentation.

This centralizes all environment option validation in one place, so invalid configurations are caught early during environment setup rather than at tester execution time.

Reviewed By: javache

Differential Revision: D101159820

fbshipit-source-id: 1e488db6e9de3eb3bac840c4931bb1536f8b5efb
2026-04-16 06:23:35 -07:00
Rubén Norte c482b936b2 Skip reporting benchmark results in test mode (#56435)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56435

Avoid printing the result summary table when benchmarks are executed in
test mode. In test mode, benchmarks run only a single iteration with no
warmup, so the timing results are not meaningful for comparison.

The per-suite results table (console.table) was already skipped in test
mode, but the benchmark result was still reported to the runner, which
could cause the cross-variant comparison table to be printed with
meaningless data. This change skips the reportBenchmarkResult call
entirely when running in test mode.

Changelog: [Internal]

Reviewed By: lenaic

Differential Revision: D100795458

fbshipit-source-id: 910f0aa5615ea07fd19b3703a2774e13b4531743
2026-04-15 02:39:57 -07:00
Bartlomiej Bloniarz e4f0509973 Add pushAnimationMutations to the AnimationBackend (#56401)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56401

Add `pushAnimationMutations(Callback)` to the AnimationBackend as a targeted alternative to `trigger()`.

The existing `trigger()` method has two problems:

1. **Blast radius**: It calls `onAnimationFrame()` which invokes ALL registered callbacks. When one animation frontend (e.g. Animated) calls `trigger()` in response to an event, every other frontend (e.g. Reanimated) also spins up unnecessarily.

2. **Broken timestamp on iOS**: `trigger()` uses `std::chrono::steady_clock` which on iOS maps to a different kernel clock than what `CADisplayLink` uses for vsync timestamps. These clocks have different baselines and can diverge over time (e.g. after device sleep), causing animations to see time jumps.

`pushAnimationMutations(Callback)` fixes both issues:
- Executes only the provided callback, not all registered ones
- Uses `AnimationChoreographer::now()` which delegates to `HighResTimeStamp`, providing a timestamp from the same clock as the vsync path on each platform

Also refactors `onAnimationFrame` to use `unpackMutations`/`applySurfaceUpdates` helpers, avoiding intermediate vector/set merging when accumulating mutations from multiple callbacks.

## Changelog:
[General][Added] - Add pushAnimationMutations to AnimationBackend for targeted event-driven animation updates

Reviewed By: zeyap

Differential Revision: D100164749

fbshipit-source-id: 53d36ed316614baa835707a45361ae8f3b828d26
2026-04-13 10:22:05 -07:00
Rubén Norte 7efb4b564e Run benchmarks in test mode by default instead of excluding them (#56418)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/56418

Changelog: [internal]

D92150163 excluded benchmark tests by default when running `yarn fantom` without `--benchmarks`. This was incorrect because it means benchmarks could silently break without being caught.

This changes the behavior so:
1. By default (without `--benchmarks`), benchmarks run in test mode (single iteration for correctness only), ensuring they do not break.
2. With `--benchmarks`, benchmarks run in full benchmark mode (multiple iterations for performance measurement).

Also renames `FANTOM_FORCE_TEST_MODE` to `FANTOM_RUN_BENCHMARKS` and `forceTestModeForBenchmarks` to `runBenchmarks` to better reflect the intent (opt-in to full benchmarks rather than opt-in to test mode).

Reviewed By: sammy-SC

Differential Revision: D100464314

fbshipit-source-id: 822cc5a25f0cdddf035616fdddf8619d27ef436a
2026-04-13 04:31:04 -07:00