# Technical Documentation: react/react-native

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/react/react-native)

### Overview (`README.md`)

<p align="center">
   <picture>
      <source media="(prefers-color-scheme: dark)" srcset="https://reactnative.dev/react-native-dark.svg">
      <source media="(prefers-color-scheme: light)" srcset="https://reactnative.dev/react-native-light.svg">
      <img alt="React Native logo" src="https://reactnative.dev/react-native-light.svg" height="80">
    </picture>
</p>

<p align="center">
  <strong>Learn once, write anywhere:</strong><br>
  Create native apps for Android, iOS, and more using React
</p>

<p align="center">
  <a href="./LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="React Native is released under the MIT license" /></a>
  <a href="https://www.npmjs.com/package/react-native"><img src="https://img.shields.io/npm/v/react-native.svg?color=blue" alt="Current npm package version" /></a>
  <a href="https://www.npmjs.com/package/react-native"><img src="https://img.shields.io/npm/dm/react-native.svg" alt="Monthly npm downloads" /></a>
  <a href="https://twitter.com/intent/follow?screen_name=reactnative"><img src="https://img.shields.io/badge/Follow_@reactnative-black?logo=x&logoColor=white" alt="Follow @reactnative on X" /></a>
</p>

<h4 align="center">
  <a href="https://reactnative.dev/docs/environment-setup">Getting Started</a>
  <span> · </span>
  <a href="https://reactnative.dev/docs/tutorial">Learn the Basics</a>
  <span> · </span>
  <a href="https://reactnative.dev/showcase">Showcase</a>
  <span> · </span>
  <a href="https://reactnative.dev/docs/contributing">Contribute</a>
  <span> · </span>
  <a href="https://reactnative.dev/help">Community</a>
  <span> · </span>
  <a href="./.github/SUPPORT.md">Support</a>
</h4>

# React Native

React Native lets you build native apps using [React](https://react.dev/). Written
in JavaScript, rendered with native code.

- **Native UI.** React Native primitives render to native platform UI, meaning your app
  uses the same native platform APIs other apps do. Gestures, text scaling, and
  accessibility behave the way users expect on each OS.
- **React, everywhere.** Declarative UI, components, hooks, and Suspense, reused
  across Android, iOS, and [other platforms](https://reactnative.dev/docs/out-of-tree-platforms).
- **Developer Velocity.** See local changes in seconds. Changes to JavaScript code are applied with Fast Refresh, without rebuilding the native app.
- **Extend it yourself.** Native Modules let you call platform code directly from JavaScript, synchronously and type-safe — or reach for [thousands of existing libraries](https://reactnative.directory/).

React Native is developed and supported by many companies and individual core contributors. Find out more on the [React Foundation website](https://react.foundation/).

## Building your first React Native app

Follow the [Getting Started guide](https://reactnative.dev/docs/environment-setup) for a new app, or [Integration with Existing Apps](https://reactnative.dev/docs/integration-with-existing-apps) to adopt React Native incrementally.

### Using a Framework

We believe that the best way to experience React Native is through a Framework, a toolbox with all the necessary APIs to let you build production ready apps. [Expo](https://docs.expo.dev/get-started/set-up-your-environment/) is a production-grade React Native Framework, with file-based routing, a standard library of native modules, and much more.

To create a new Expo project, run the following in your terminal:

    npx create-expo-app@latest

Then follow the rest of [Expo's getting started guide](https://docs.expo.dev/get-started/set-up-your-environment/) to start building.

### Without a Framework

You can also use React Native without a Framework, however we've found that most developers benefit from one — navigation, native dependencies, and platform tooling are problems the ecosystem has already solved. If a Framework doesn't suit your app, follow [Getting Started Without a Framework](https://reactnative.dev/docs/getting-started-without-a-framework).

## Documentation

The full documentation for React Native can be found on our [website](https://reactnative.dev/docs/getting-started).

- [Introduction](https://reactnative.dev/docs/getting-started)
- [Getting Started](https://reactnative.dev/docs/environment-setup)
- [Learn the Basics](https://reactnative.dev/docs/tutorial)
- [Components and APIs](https://reactnative.dev/docs/components-and-apis)
- [UI & Interaction](https://reactnative.dev/docs/style)
- [Native Modules](https://reactnative.dev/docs/native-platform)
- [Debugging](https://reactnative.dev/docs/debugging)
- [Upgrading](https://reactnative.dev/docs/upgrading)
- [Architecture](https://reactnative.dev/architecture/overview)

The source for the React Native docs and website is hosted on a separate repository, [**react/react-native-website**](https://github.com/react/react-native-website).

## Contributing

The main purpose of this repository is to continue evolving React Native core. We want to make contributing to this project as easy and transparent as possible, and we are grateful to the community for contributing bug fixes and improvements. Read below to learn how you can take part in improving React Native.

### [Code of Conduct](https://code.fb.com/codeofconduct/)

Meta has adopted a Code of Conduct that we expect project participants to adhere to.
Please read the [full text](https://code.fb.com/codeofconduct/) so that you can understand what actions will and will not be tolerated.

### [Contributing Guide](https://reactnative.dev/docs/contributing)

Read our [**Contributing Guide**](https://reactnative.dev/docs/contributing) to learn about our development process, how to propose bugfixes and improvements, and how to build and test your changes to React Native.

### Discussions

Larger discussions and proposals are discussed in [**react-native-community/discussions-and-proposals**](https://github.com/react-native-community/discussions-and-proposals).

React Native releases are discussed in [**reactwg/react-native-releases**](https://github.com/reactwg/react-native-releases/discussions).

## License

React Native is MIT licensed, as found in the [LICENSE](./LICENSE) file.

---

### Overview (`__docs__/README.md`)

# React Native Technical Documentation

The React Native technical documentation describes how React Native works
internally, the subsystems it is composed of, how they work and how they
interact with each other.

The intended audience is people who want to learn about the internals of React
Native and contribute to it. **End users of React Native are meant to use the
[public website](https://reactnative.dev) instead** (its code can be found
[here](https://github.com/facebook/react-native-website)).

For details on how we approach technical documentation in this repository, see
[GUIDELINES.md](./GUIDELINES.md).

## 🚀 Usage

This repository is not meant to be consumed directly by end users. Instead, it
creates several packages that are published to the NPM registry for direct
consumption by end users and frameworks.

This repository uses a monorepo approach, and public packages can be found in
the [`packages`](../packages/) directory (the ones that do not contain
`"private": true` in their `package.json` file).

The most important package is the
[`react-native`](https://www.npmjs.com/package/react-native) package, located in
[`packages/react-native`](../packages/react-native), which contains the public
JavaScript API.

This repository provides the Android and iOS versions of React Native. Versions
for other platforms are maintained in their own repositories.

## 📐 Design

TODO: Explain the different components of React Native at a high level.

## 🔗 Relationship with other systems

### Part of this

- Runtime
  - Cross-platform
    - [Feature Flags](../packages/react-native/src/private/featureflags/__docs__/README.md)
    - Host / Instance / Bridgeless
    - UI / Fabric
      - Events
      - Shadow Tree Lifecycle
        - [Runtime Shadow Node Reference Update](../packages/react-native/ReactCommon/react/renderer/core/__docs__/RSNRU.md)
        - [passChildrenWhenCloningPersistedNodes](../packages/react-native/ReactCommon/react/renderer/core/__docs__/passChildrenWhenCloning.md)
      - Layout
      - Mounting
      - [Animation Backend](../packages/react-native/ReactCommon/react/renderer/animationbackend/__docs__/AnimationBackend.md)
      - [Native Animated](../packages/react-native/ReactCommon/react/renderer/animated/__docs__/NativeAnimated.md)
    - Native Modules / TurboModules
    - JS Runtime
      - [Event Loop](../packages/react-native/ReactCommon/react/renderer/runtimescheduler/__docs__/README.md)
      - Globals and environment setup
      - Error handling
    - Developer Tools
      - React Native DevTools
        - Infrastructure
          - [Inspector proxy protocol](../packages/dev-middleware/src/inspector-proxy/__docs__/README.md)
      - LogBox
    - Misc
      - Web APIs
        - DOM Traversal & Layout APIs
        - [IntersectionObserver](../packages/react-native/src/private/webapis/intersectionobserver/__docs__/README.md)
        - [MutationObserver](../packages/react-native/src/private/webapis/mutationobserver/__docs__/README.md)
        - Performance & PerformanceObserver
        - Timers
  - Platform-specific
    - Host Platform Interface
  - Android
    - UI
      - [Events](../packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/events/__docs__/README.md)
      - Mounting
  - iOS
    - UI
      - Events
      - Mounting
    - [Bundler Connection](../packages/react-native/React/DevSupport/__docs__/README.md)
- Build system
  - Android
  - iOS
    - [SwiftPM](../packages/react-native/scripts/spm/__docs__/README.md)
  - C++
  - JavaScript
    - Metro
- Testing
  - Android
  - iOS
  - C++
  - JavaScript
    - Flow
    - TypeScript
    - Jest
    - ESLint
  - Integration / E2E
    - [Fantom](../private/react-native-fantom/__docs__/README.md)

### Used by this

This repository has many different types of dependencies: build systems,
external packages to be used during development, external packages used at
runtime, etc.

### Uses this

The main use cases for this repository are:

1. Developing React Native itself.
2. Testing and releasing React Native.
3. Synchronizing forks like `react-native-windows` and `react-native-macos`.

---

### Overview (`packages/asset-utils/README.md`)

# @react-native/asset-utils

[ [

[npm]: https://img.shields.io/npm/v/@react-native/asset-utils.svg?color=blue
[npm downloads]: https://img.shields.io/npm/dm/@react-native/asset-utils.svg

Android resource-path helpers used when copying React Native assets into `drawable-*` / `raw` folders. Consumed by bundling and build tooling; most apps never import this directly.

## API

```js
import {
  getAndroidResourceFolderName,
  getAndroidResourceIdentifier,
} from '@react-native/asset-utils';
```

| Export | Signature | Notes |
|---|---|---|
| `getAndroidResourceFolderName` | `(asset: PackagerAsset, scale: number) => string` | e.g. `drawable-xhdpi`; non-drawable types resolve to `raw` |
| `getAndroidResourceIdentifier` | `(asset: PackagerAsset) => string` | Sanitised resource name |
| `drawableFileTypes` | `Set<string>` | Asset types that map to a `drawable-*` folder |

---

### Overview (`packages/babel-plugin-codegen/README.md`)

# @react-native/babel-plugin-codegen

[ [

[npm]: https://img.shields.io/npm/v/@react-native/babel-plugin-codegen.svg?color=blue
[npm downloads]: https://img.shields.io/npm/dm/@react-native/babel-plugin-codegen.svg

Babel plugin that generates native module and view manager binding code for React Native, powered by [`@react-native/codegen`](https://www.npmjs.com/package/@react-native/codegen).

---

### Overview (`packages/community-cli-plugin/README.md`)

# @react-native/community-cli-plugin

[ [

[npm]: https://img.shields.io/npm/v/@react-native/community-cli-plugin.svg?color=blue
[npm downloads]: https://img.shields.io/npm/dm/@react-native/community-cli-plugin.svg

> This is an internal dependency of React Native. **Please don't depend on it directly.**

CLI entry points supporting core React Native development features.

Formerly [@react-native-community/cli-plugin-metro](https://www.npmjs.com/package/@react-native-community/cli-plugin-metro).

## Commands

### `start`

Start the React Native development server.

#### Usage

```sh
npx @react-native-community/cli start [options]
```

#### Options

| Option | Description |
| - | - |
| `--port <number>` | Set the server port. |
| `--host <string>` | Set the server host. |
| `--projectRoot <path>` | Set the path to the project root. |
| `--watchFolders <list>` | Specify additional folders to be added to the watch list. |
| `--assetPlugins <list>` | Specify additional asset plugins. |
| `--sourceExts <list>` | Specify additional source extensions to bundle. |
| `--max-workers <number>` | Set the maximum number of workers the worker-pool will spawn for transforming files. Defaults to the number of the cores available on your machine. |
| `--transformer <string>` | Specify a custom transformer. |
| `--reset-cache` | Remove cached files. |
| `--custom-log-reporter-path <string>` | Specify a module path exporting a replacement for `TerminalReporter`. |
| `--https` | Enable HTTPS connections. |
| `--key <path>`| Specify path to a custom SSL key. |
| `--cert <path>` | Specify path to a custom SSL cert. |
| `--config <string>` | Path to the CLI configuration file. |
| `--no-interactive` | Disable interactive mode. |
| `--client-logs` | **[Deprecated]** Enable plain text JavaScript log streaming for all connected apps. |

### `bundle`

Build the bundle for the provided JavaScript entry file.

#### Usage

```sh
npx @react-native-community/cli bundle --entry-file <path> [options]
```

#### Options

| Option | Description |
| - | - |
| `--entry-file <path>` | Set the path to the root JavaScript entry file. |
| `--platform <string>` | Set the target platform (either `"android"` or `"ios"`). Defaults to `"ios"`. |
| `--transformer <string>` | Specify a custom transformer. |
| `--dev [boolean]` | If `false`, warnings are disabled and the bundle is minified. Defaults to `true`. |
| `--minify [boolean]` | Allows overriding whether bundle is minified. Defaults to `false` if `--dev` is set. Disabling minification can be useful for speeding up production builds for testing purposes. |
| `--bundle-output <string>` | Specify the path to store the resulting bundle. |
| `--bundle-encoding <string>` | Specify the encoding for writing the bundle (<https://nodejs.org/api/buffer.html#buffer_buffer>). |
| `--resolver-option <string...>` | Custom resolver options of the form key=value. URL-encoded. May be specified multiple times. |
| `--sourcemap-output <string>` | Specify the path to store the source map file for the resulting bundle. |
| `--sourcemap-sources-root <string>` | Set the root path for source map entries. |
| `--sourcemap-use-absolute-path` | Report `SourceMapURL` using its full path. |
| `--max-workers <number>` | Set the maximum number of workers the worker-pool will spawn for transforming files. Defaults to the number of the cores available on your machine. |
| `--assets-dest <string>` | Specify the directory path for storing assets referenced in the bundle. |
| `--reset-cache` | Remove cached files. |
| `--read-global-cache` | Attempt to fetch transformed JS code from the global cache, if configured. Defaults to `false`. |
| `--config <string>` | Path to the CLI configuration file. |

### `codegen`

Run the React Native codegen, generating native boilerplate from JS spec files.

#### Usage

```sh
npx @react-native-community/cli codegen [options]
```

#### Options

| Option | Description |
| - | - |
| `--path <path>` | Path to the React Native project root. Defaults to the current working directory. |
| `--platform <string>` | Target platform. Supported values: `"android"`, `"ios"`, `"all"`. Defaults to `"all"`. |
| `--outputPath <path>` | Path where generated artifacts will be output to. |
| `--source <string>` | Whether the script is invoked from an `app` or a `library`. Defaults to `"app"`. |

### `spm [action]`

Set up or maintain Swift Package Manager support for the iOS/macOS app. Actions: `add`, `update`, `deinit`, `scaffold`. With no action: `add` (or `update` if SPM is already set up).

#### Usage

```sh
npx @react-native-community/cli spm [action] [options]
```

#### Options

| Option | Description |
| - | - |
| `--version <string>` | React Native version (e.g. `0.80.0`). Defaults to the version in `node_modules/react-native/package.json`. |
| `--yes` | Skip the dirty-pbxproj confirmation prompt. |
| `--xcodeproj <path>` | **[add]** Path to the `.xcodeproj` to inject SPM packages into (disambiguates when several exist). |
| `--productName <string>` | **[add]** App target to inject into (disambiguates when several exist). |
| `--deintegrate` | **[add]** Run `pod deintegrate` and strip React Native from the Podfile before injecting (CocoaPods → SwiftPM migration). |
| `--artifacts <path>` | **[advanced]** Local artifact root containing complete `debug/` and `release/` slots. |
| `--download <string>` | **[advanced]** Artifact download policy: `auto` (default), `skip`, or `force`. |
| `--skipCodegen` | **[advanced]** Skip the react-native codegen step. |

## Contributing

Changes to this package can be made locally and tested against the `rn-tester` app, per the [Contributing guide](https://reactnative.dev/contributing/overview#contributing-code). During development, this package is automatically run from source with no build step.

---

### Overview (`packages/debugger-frontend/README.md`)

# @react-native/debugger-frontend

[ [

[npm]: https://img.shields.io/npm/v/@react-native/debugger-frontend.svg?color=blue
[npm downloads]: https://img.shields.io/npm/dm/@react-native/debugger-frontend.svg

Debugger frontend for React Native based on Chrome DevTools. It is intended to be used via [`@react-native/dev-middleware`](https://www.npmjs.com/package/@react-native/dev-middleware).

## Usage

The package exports the absolute path to the directory containing the frontend assets.

```js
const frontendPath = require('@react-native/debugger-frontend');

// Pass frontendPath to a static server, etc
```

## Contributing

### Source repo

Source code for this package lives in the [react/react-native-devtools-frontend](https://github.com/react/react-native-devtools-frontend) repo. See below for how we build and check in changes.

### Updating the frontend assets

The compiled assets for the debugger frontend are periodically checked into this package under the `dist/` folder. To update these, run `node scripts/debugger-frontend/sync-and-build` from the root of your `react-native` checkout.

```sh
# For main
node scripts/debugger-frontend/sync-and-build --branch main

# For stable branches (e.g. '0.73-stable')
node scripts/debugger-frontend/sync-and-build --branch 0.73-stable
```

By default, this will clone and build from [react/react-native-devtools-frontend](https://github.com/react/react-native-devtools-frontend).

The updated files are committed on completion, with a generated summary and changelog of the synced revisions.

---

### Overview (`packages/debugger-shell/README.md`)

# @react-native/debugger-shell

[ [

[npm]: https://img.shields.io/npm/v/@react-native/debugger-shell.svg?color=blue
[npm downloads]: https://img.shields.io/npm/dm/@react-native/debugger-shell.svg

Experimental Electron-based shell for React Native DevTools.

## Why Electron?

The React Native DevTools frontend is based on Chrome DevTools, which is a web app, but is not particularly portable: it's designed to run in Chromium, and Chromium only. Prior to `@react-native/debugger-shell`, we would run it in [hosted mode](https://chromium.googlesource.com/devtools/devtools-frontend/+/main/docs/get_the_code.md#running-in-hosted-mode) in an instance of Chrome or Edge.

Relying on hosted mode presents a variety of UX issues in the debugging workflow, such as the need to ask developers to install a particular browser before they can debug in React Native, and the inability to foreground/reuse existing debugger windows when relaunching the debugger for the same app. In order to address these issues effectively, we fundamentally need to leave the browser sandbox and run the debugger in a shell we can bundle with React Native, and whose behavior we can control.

Electron is a tried-and-tested framework for the *specific* task of embedding a Chromium browser in a portable, customized shell. As a rule we'll hold a high bar for performance and reliability, and we'll only add features to the shell if they are strictly necessary to complement the DevTools frontend's built-in capabilities.

---

### Overview (`packages/dev-middleware/README.md`)

# @react-native/dev-middleware

[ [

[npm]: https://img.shields.io/npm/v/@react-native/dev-middleware.svg?color=blue
[npm downloads]: https://img.shields.io/npm/dm/@react-native/dev-middleware.svg

Dev server middleware supporting core React Native development features. This package is preconfigured in all React Native projects.

## Usage

Middleware can be attached to a dev server (e.g. [Metro](https://facebook.github.io/metro/docs/getting-started)) using the `createDevMiddleware` API.

```js
import { createDevMiddleware } from '@react-native/dev-middleware';

function myDevServerImpl(args) {
  ...

  const {middleware, websocketEndpoints} = createDevMiddleware({
    projectRoot: metroConfig.projectRoot,
    serverBaseUrl: new URL(`http://${args.host}:${args.port}`),
    logger,
  });

  await Metro.runServer(metroConfig, {
    host: args.host,
    ...,
    unstable_extraMiddleware: [
      middleware,
      // Optionally extend with additional HTTP middleware
    ],
    websocketEndpoints: {
      ...websocketEndpoints,
      // Optionally extend with additional WebSocket endpoints
    },
  });
}
```

## Included middleware

`@react-native/dev-middleware` is designed for integrators such as [`@expo/dev-server`](https://www.npmjs.com/package/@expo/dev-server) and [`@react-native/community-cli-plugin`](https://github.com/facebook/react-native/tree/main/packages/community-cli-plugin). It provides a common default implementation for core React Native dev server responsibilities.

We intend to keep this to a narrow set of functionality, based around:

- **Debugging** — The [Chrome DevTools protocol (CDP)](https://chromedevtools.github.io/devtools-protocol/) endpoints supported by React Native, including the Inspector Proxy, which facilitates connections with multiple devices.
- **Dev actions** — Endpoints implementing core [Dev Menu](https://reactnative.dev/docs/debugging#accessing-the-dev-menu) actions, e.g. reloading the app, opening the debugger frontend.

### HTTP endpoints

<small>`DevMiddlewareAPI.middleware`</small>

These are exposed as a [`connect`](https://www.npmjs.com/package/connect) middleware handler, assignable to `Metro.runServer` or other compatible HTTP servers.

#### GET `/json/list`, `/json` ([CDP](https://chromedevtools.github.io/devtools-protocol/#endpoints))

Returns the list of available WebSocket targets for all connected React Native app sessions.

#### GET `/json/version` ([CDP](https://chromedevtools.github.io/devtools-protocol/#endpoints))

Returns version metadata used by Chrome DevTools.

#### GET `/debugger-frontend`

Subpaths of this endpoint are reserved to serve the JavaScript debugger frontend.

#### POST `/open-debugger`

Open the JavaScript debugger for a given CDP target. Must be provided with one of the following query params:

- `device`‌ — An ID unique to a combination of device and app, stable across installs. Implemented by `getInspectorDeviceId` on each native platform.
- `target` — The target page ID as returned by `/json/list` for the current dev server session.
- `appId` (deprecated, legacy only) — The application bundle identifier to match (non-unique across multiple connected devices). This param will only match legacy Hermes debugger targets.

<details>
<summary>Example</summary>

    curl -X POST 'http://localhost:8081/open-debugger?target=<targetId>'
</details>

### WebSocket endpoints

<small>`DevMiddlewareAPI.websocketEndpoints`</small>

#### `/inspector/device`

WebSocket handler for registering device connections.

#### `/inspector/debug`

WebSocket handler that proxies CDP messages to/from the corresponding device.

## Experimental features

React Native frameworks may pass an `unstable_experiments` option to `createDevMiddleware` to configure experimental features. Note that these features might not work correctly, and they may change or be removed in the future without notice. Some of the experiment flags available are documented below.

### `unstable_experiments.enableStandaloneFuseboxShell`

Enables launching the debugger frontend in a standalone app shell (provided by the `@react-native/debugger-shell` package) rather than in a browser window. Since React Native 0.83 this defaults to `true`, and may be disabled by explicitly passing `false`.

The shell is powered by a separate binary that is downloaded and cached in the background (immediately after the call to `createDevMiddleware`). If there is a problem downloading or invoking this binary for the first time, the debugger frontend will revert to launching in a browser window until the next time `createDevMiddleware` is called (typically, on the next dev server start).

## Contributing

Changes to this package can be made locally and tested against the `rn-tester` app, per the [Contributing guide](https://reactnative.dev/contributing/overview#contributing-code). During development, this package is automatically run from source with no build step.

---

### Overview (`packages/eslint-config-react-native/README.md`)

# @react-native/eslint-config

[ [

[npm]: https://img.shields.io/npm/v/@react-native/eslint-config.svg?color=blue
[npm downloads]: https://img.shields.io/npm/dm/@react-native/eslint-config.svg

ESLint and Prettier configuration used by React Native apps.

## Installation

```sh
yarn add --dev eslint prettier @react-native/eslint-config
```

## Usage

### For ESLint 9+ (Flat Config)

Add to your `eslint.config.js`:

```javascript
const reactNativeConfig = require('@react-native/eslint-config/flat');

module.exports = [
  ...reactNativeConfig,
  // Your custom config here
];
```

Or with ES modules:

```javascript
import reactNativeConfig from '@react-native/eslint-config/flat';

export default [
  ...reactNativeConfig,
  // Your custom config here
];
```

### For ESLint 8 (Legacy Config)

Add to your eslint config (`.eslintrc`, or `eslintConfig` field in `package.json`):

```json
{
    "extends": "@react-native"
}
```

---

### Overview (`packages/eslint-plugin-react-native/README.md`)

# @react-native/eslint-plugin

[ [

[npm]: https://img.shields.io/npm/v/@react-native/eslint-plugin.svg?color=blue
[npm downloads]: https://img.shields.io/npm/dm/@react-native/eslint-plugin.svg

ESLint rules for [`@react-native/eslint-config`](https://github.com/facebook/react-native/tree/HEAD/packages/eslint-config-react-native). You probably want to install that package instead.

## Rules

### `platform-colors`

Enforces that calls to `PlatformColor` and `DynamicColorIOS` are statically analyzable to enable performance optimizations.

---

### Overview (`packages/eslint-plugin-specs/README.md`)

# @react-native/eslint-plugin-specs

[ [

[npm]: https://img.shields.io/npm/v/@react-native/eslint-plugin-specs.svg?color=blue
[npm downloads]: https://img.shields.io/npm/dm/@react-native/eslint-plugin-specs.svg

ESLint rules that validate React Native Native Module and Component specs.

---

### Overview (`packages/gradle-plugin/README.md`)

# @react-native/gradle-plugin

[ [

[npm]: https://img.shields.io/npm/v/@react-native/gradle-plugin.svg?color=blue
[npm downloads]: https://img.shields.io/npm/dm/@react-native/gradle-plugin.svg

Gradle plugin used to build and configure React Native applications for Android. It is applied automatically by apps created from the React Native template.

---

### Overview (`packages/jest-preset/README.md`)

# @react-native/jest-preset

[ [

[npm]: https://img.shields.io/npm/v/@react-native/jest-preset.svg?color=blue
[npm downloads]: https://img.shields.io/npm/dm/@react-native/jest-preset.svg

Jest preset for [React Native](https://reactnative.dev) apps.

## Usage

### Installation

Install `@react-native/jest-preset` in your app:

with `npm`:

```sh
npm i @react-native/jest-preset --save-dev
```

or with `yarn`:

```sh
yarn add -D @react-native/jest-preset
```

### Configuring Jest

Then, create a file called `jest.config.js` in your project's root directory. Then load this preset:

```
module.exports = {
  preset: '@react-native/jest-preset',
};
```

You can further customize your Jest configuration by specifying other options. See [Jest's `jest.config.js` documentation](https://jestjs.io/docs/configuration) to learn more.

---

### Overview (`packages/metro-config/README.md`)

# @react-native/metro-config

[ [

[npm]: https://img.shields.io/npm/v/@react-native/metro-config.svg?color=blue
[npm downloads]: https://img.shields.io/npm/dm/@react-native/metro-config.svg

Metro configuration for React Native. In React Native, your Metro config should extend either `@react-native/metro-config` or `@expo/metro-config`. These packages contain essential defaults necessary to build and run React Native apps.

See [Configuring Metro](https://reactnative.dev/docs/next/metro#configuring-metro) for the full guide.

## Usage

```js
const {
  getDefaultConfig,
  mergeConfig,
} = require('@react-native/metro-config');

/**
 * Metro configuration
 * https://metrobundler.dev/docs/configuration
 *
 * @type {import('metro-config').MetroConfig}
 */
const config = {};

module.exports = mergeConfig(getDefaultConfig(__dirname), config);
```

---

### Overview (`packages/new-app-screen/README.md`)

# @react-native/new-app-screen

[ [

[npm]: https://img.shields.io/npm/v/@react-native/new-app-screen.svg?color=blue
[npm downloads]: https://img.shields.io/npm/dm/@react-native/new-app-screen.svg

`NewAppScreen` component for React Native.

## Usage

```js
import { NewAppScreen } from '@react-native/new-app-screen';

function MyAppOrTemplate() {
  ...

  return <NewAppScreen />;
}
```

## Contributing

Changes to this package can be made locally and tested against the `rn-tester` app, per the [Contributing guide](https://reactnative.dev/contributing/overview#contributing-code).

---

### Overview (`packages/normalize-color/README.md`)

# @react-native/normalize-colors

[ [

[npm]: https://img.shields.io/npm/v/@react-native/normalize-colors.svg?color=blue
[npm downloads]: https://img.shields.io/npm/dm/@react-native/normalize-colors.svg

Color normalization utility for React Native. Converts CSS color values into the numeric form consumed by the native layer.

---

### Overview (`packages/polyfills/README.md`)

# @react-native/js-polyfills

[ [

[npm]: https://img.shields.io/npm/v/@react-native/js-polyfills.svg?color=blue
[npm downloads]: https://img.shields.io/npm/dm/@react-native/js-polyfills.svg

> This is an internal dependency of React Native. **Please don't depend on it directly.**

JavaScript environment polyfills set up by React Native at startup (e.g. `Promise`, timers, and other runtime globals).

---

### Overview (`packages/react-native-babel-preset/README.md`)

# @react-native/babel-preset

[ [

[npm]: https://img.shields.io/npm/v/@react-native/babel-preset.svg?color=blue
[npm downloads]: https://img.shields.io/npm/dm/@react-native/babel-preset.svg

Babel preset for [React Native](https://reactnative.dev) applications. React Native uses this Babel preset by default when transforming your app's source code.

You only need to use this preset directly if you provide a custom `babel.config.js` file in your project's root directory. React Native does not apply its default Babel configuration in that case, so you must specify all the plugins necessary to transform your code — start from this preset to get the defaults and add more plugins on top.

## Usage

### Installation

Install `@react-native/babel-preset` in your app:

with `npm`:

```sh
npm i @react-native/babel-preset --save-dev
```

or with `yarn`:

```sh
yarn add -D @react-native/babel-preset
```

### Configuring Babel

Then, create a file called `babel.config.js` in your project's root directory. The existence of this `babel.config.js` file tells React Native to use your custom Babel configuration instead of its own. Then load this preset:

```json
{
  "presets": ["module:@react-native/babel-preset"]
}
```

You can further customize your Babel configuration by specifying plugins and other options. See [Babel's `babel.config.js` documentation](https://babeljs.io/docs/en/config-files/) to learn more.

---

### Overview (`packages/react-native-babel-transformer/README.md`)

# @react-native/metro-babel-transformer

[ [

[npm]: https://img.shields.io/npm/v/@react-native/metro-babel-transformer.svg?color=blue
[npm downloads]: https://img.shields.io/npm/dm/@react-native/metro-babel-transformer.svg

Metro Babel transformer for React Native applications. Applies [`@react-native/babel-preset`](https://www.npmjs.com/package/@react-native/babel-preset) when transforming source files during bundling.

---

### Overview (`packages/react-native-codegen/README.md`)

# @react-native/codegen

[ [

[npm]: https://img.shields.io/npm/v/@react-native/codegen.svg?color=blue
[npm downloads]: https://img.shields.io/npm/dm/@react-native/codegen.svg

Code generation tools for React Native. Parses TypeScript and Flow NativeModule and Component specs and generates the native binding code used by the New Architecture.

---

### Overview (`packages/react-native-compatibility-check/README.md`)

# @react-native/compatibility-check

[ [

[npm]: https://img.shields.io/npm/v/@react-native/compatibility-check.svg?color=blue
[npm downloads]: https://img.shields.io/npm/dm/@react-native/compatibility-check.svg

Status: Experimental (stage 1)

Work In Progress. Documentation is lacking, and intended to be used by power
users at this point.

This tool enables checking the boundary between JavaScript and Native for
backwards incompatible changes to protect against crashes.

This is useful for:

- Local Development
- Over the Air updates on platforms that support it
- Theoretically: Server Components with React Native

## **Motivating Problems**

Let’s look at some motivating examples for this project.

> [!NOTE] 
> The examples below are written with Flow, but the compatibility-check
> tool is agnostic to the types you write. The compatibility-check runs on JSON
> schema files, most commonly generated by the
> [@react-native/codegen](https://www.npmjs.com/package/@react-native/codegen)
> tool which supports both TypeScript and Flow.

### **Adding new methods**

You might have an Analytics Native Module in your app, and you last built the
native client a couple of days ago:

```javascript
export interface Spec extends TurboModule {
  log: (eventName: string, content: string) => void;
}
```

And you are working on a change to add a new method to this Native Module:

```javascript
export interface Spec extends TurboModule {
  log: (eventName: string, content: string) => void;
  logError: (message: string) => void;
}
```

```
NativeAnalytics.logError('Oh No! We hit a crash')
```

Since you are working on this, you’ve built a new native client and tested the
change on your computer and everything works.

However, when your colleague pulls your latest changes and tries to run it,
they’ll get a crash `logError is not a function`. They need to rebuild their
native client\!

Using this tool, you can detect this incompatibility at build time, getting an
error that looks like:

```
NativeAnalytics: Object added required properties, which native will not provide
  -- logError
```

Errors like this can occur for much more nuanced reasons than adding a method.
For example:

### **Sending native new union values**

```javascript
export interface Spec extends TurboModule {
  // You add 'system' to this union
  +setColorScheme: (color: 'light' | 'dark') => void;
}
```

If you add a new option of `system` and add native support for that option, when
you call this method with `system` on your commit it would work but on an older
build not expecting `system` it will crash. This tool will give you the error
message:

```
ColorManager.setColorScheme parameter 0: Union added items, but native will not expect/support them
  -- position 3 system
```

### **Changing an enum value sent from native**

As another example, say you are getting the color scheme from the system as an
integer value, used in JavaScript as an enum:

```javascript
enum TestEnum {
  LIGHT = 1,
  DARK = 2,
  SYSTEM = 3,
}

export interface Spec extends TurboModule {
  getColorScheme: () => TestEnum;
}
```

And you realize you actually need native to send `-1` for System instead of 3\.

```javascript
enum TestEnum {
  LIGHT = 1,
  DARK = 2,
  SYSTEM = -1,
}
```

If you make this change and run the JavaScript on an old build, it might still
send JavaScript the value 3, which your JavaScript isn’t handling anymore\!

This tool gives an error:

```javascript
ColorManager: Object contained a property with a type mismatch
   -- getColorScheme: has conflicting type changes
       --new: ()=>Enum<number>
       --old: ()=>Enum<number>
       Function return types do not match
           --new: ()=>Enum<number>
           --old: ()=>Enum<number>
           Enum types do not match
               --new: Enum<number> {LIGHT = 1, DARK = 2, SYSTEM = -1}
               --old: Enum<number> {LIGHT = 1, DARK = 2, SYSTEM = 3}
               Enum contained a member with a type mismatch
                   -- Member SYSTEM: has conflicting changes
                       --new: -1
                       --old: 3
                       Numeric literals are not equal
                           --new: -1
                           --old: 3

```

## **Avoiding Breaking Changes**

You can use this tool to either detect changes locally to warn that you need to
install a new native build, or when doing OTA you might need to guarantee that
the changes in your PR are compatible with the native client they’ll be running
in.

### **Example 1**

In example 1, when adding logError, it needs to be optional to be safe:

```javascript
export interface Spec extends TurboModule {
  log: (eventName: string, content: string) => void;
  logError?: (message: string) => void;
}
```

That will enforce if you are using TypeScript or Flow that you check if the
native client supports logError before calling it:

```javascript
if (NativeAnalytics.logError) {
  NativeAnalytics.logError('Oh No! We hit a crash');
}
```

### **Example 2**

When you want to add '`system'` as a value to the union, modifying the existing
union is not safe. You would need to add a new optional method that has that
change. You can clean up the old method when you know that all of the builds you
ever want to run this JavaScript on have native support.

```javascript
export interface Spec extends TurboModule {
  +setColorScheme: (color: 'light' | 'dark') => void
  +setColorSchemeWithSystem?: (color: 'light' | 'dark' | 'system') => void
}
```

### **Example 3**

Changing a union case is similar to Example 2, you would either need a new
method, or support the existing value and the new `-1`.

```
enum TestEnum {
  LIGHT = 1,
  DARK = 2,
  SYSTEM = 3,
  SYSTEM_ALSO = -1,
}
```

## **Installation**

```
yarn add @react-native/compatibility-check
```

## **Usage**

To use this package, you’ll need a script that works something like this:

This script checks the compatibility of a React Native app's schema between two
versions. It takes into account the changes made to the schema and determines
whether they are compatible or not.

```javascript
import {compareSchemas} from '@react-native/compatibility-check';
const util = require('util');

async function run(argv: Argv, STDERR: string) {
  const debug = (log: mixed) => {
    argv.debug &&
      console.info(util.inspect(log, {showHidden: false, depth: null}));
  };

  const currentSchema =
    JSON.parse(/*you'll read the file generated by codegen wherever it is in your app*/);
  const previousSchema =
    JSON.parse(/*you'll read the schema file that you persisted from when your native app was built*/);

  const safetyResult = compareSchemas(currentSchema, previousSchema);

  const summary = safetyResult.getSummary();
  switch (summary.status) {
    case 'ok':
      debug('No changes in boundary');
      console.log(JSON.stringify(summary));
      break;
    case 'patchable':
      debug('Changes in boundary, but are compatible');
      debug(result.getDebugInfo());
      console.log(JSON.stringify(summary));
      break;
    default:
      debug(result.getDebugInfo());
      console.error(JSON.stringify(result.getErrors()));
      throw new Error(`Incompatible changes in boundary`);
  }
}
```

---

### Overview (`packages/react-native-popup-menu-android/README.md`)

# @react-native/popup-menu-android

[ [

[npm]: https://img.shields.io/npm/v/@react-native/popup-menu-android.svg?color=blue
[npm downloads]: https://img.shields.io/npm/dm/@react-native/popup-menu-android.svg

`PopupMenuAndroid` component for React Native, exposing the Android platform's [`PopupMenu`](https://developer.android.com/reference/android/widget/PopupMenu) for displaying a menu anchored to a view.

---

### Overview (`packages/react-native/README.md`)

# Where is the template?
The React Native Template has moved from being shipping inside the [react-native](https://www.npmjs.com/package/react-native) package to it's own package: [@react-native-community/template](https://github.com/react-native-community/template).

## Why has it moved?
The [React Native Frameworks RFC0759](https://github.com/react-native-community/discussions-and-proposals/blob/main/proposals/0759-react-native-frameworks.md#evolving-the-react-native-community-template--cli) provides background information.

## When was it moved?
The 0.75 release.

---

### Overview (`packages/rn-tester/README.md`)

# RNTester

The RNTester showcases React Native views and modules.

## Running this app

Before running the app, make sure you ran:
```sh
git clone https://github.com/facebook/react-native.git
cd react-native
yarn install
```

### Running on iOS

If you are testing non-fabric component, search for and modify the `fabric_enabled` flag in [RNTester's Podfile](https://github.com/facebook/react-native/blob/main/packages/rn-tester/Podfile).

```ruby
fabric_enabled = false
```

Also, if you previously built RNTester with fabric enabled, you might need to clean up the build files and Pods.
```sh
# Clean the generated files and folders to clean install RNTester
cd packages/rn-tester
yarn clean-ios
```

If you are still having a problem after doing the clean up (which can happen if you have built RNTester with older React Native versions where files were generated inside the react-native folder.), the best way might be to clean-install react-native (e.g. remove node_modules and yarn install). If after cleaning up, you are still having issues, you might also want to try `RCT_NEW_ARCH_ENABLED=0 bundle exec pod install` to disable the new architecture as it might be conflicting.

Both macOS and Xcode are required.
1. `cd packages/rn-tester`
2. Install [Bundler](https://bundler.io/): `gem install bundler`. We use bundler to install the right version of [CocoaPods](https://cocoapods.org/) locally.
3. Install Bundler and CocoaPods dependencies: `bundle install && bundle exec pod install` or `yarn prepare-ios`.
4. Open the generated `RNTesterPods.xcworkspace`. This is not checked in, as it is generated by CocoaPods. Do not open `RNTesterPods.xcodeproj` directly.

#### Note for Apple Silicon users

If you own a Mac laptop with Apple Silicon, you need to run some different commands to install and run cocoapods.

- `sudo arch -x86_64 gem install ffi`: this installs the `ffi` package to load dynamically-linked libraries.
- `arch -x86_64 pod install`: this run `pod install` with the right architecture.

### Running on Android

You'll need to have all the [prerequisites](https://reactnative.dev/contributing/how-to-build-from-source#prerequisites) (SDK, NDK) for Building React Native installed.

You can build and run RN-Tester by using this command from the root of the repo:

```sh
yarn android
```

> [!NOTE]
> Building for the first time can take a while.

If you're using a physical device, run `adb reverse tcp:8081 tcp:8081` to make sure the device can access Metro.

See [Running on Device](https://reactnative.dev/docs/running-on-device) for additional instructions on using a physical device.

## Building from source

Building the app on both iOS and Android means building the React Native framework from source. This way you're running the latest native and JS code the way you see it in your clone of the github repo.

This is different from apps created using `react-native init` which have a dependency on a specific version of React Native JS and native code, declared in a `package.json` file (and `build.gradle` for Android apps).

## Running tests (iOS)

RNTester provides both integration and unit tests. You can run them all by hitting `Cmd+U` in Xcode. Alternatively, it is possible to run just unit tests or integration tests using the keybinding after selecting the appropriate scheme (either `RNTesterUnitTests` or `RNTesterIntegrationTests`).

## Visual tests

CI captures screenshots of selected RNTester examples on Android and iOS and compares them with `main`. See [visual-tests/README.md](visual-tests/README.md) to add a test or review a failure.

---

### Overview (`packages/typescript-config/README.md`)

# @react-native/typescript-config

[ [

[npm]: https://img.shields.io/npm/v/@react-native/typescript-config.svg?color=blue
[npm downloads]: https://img.shields.io/npm/dm/@react-native/typescript-config.svg

This package provides the default `tsconfig.json` used by newly built React Native apps.

This template is customized for specific versions of React Native, and should be updated in sync with the rest of your app.

## Opting out of the Strict TypeScript API (default in 0.87)

To opt out of the new [Strict TypeScript API](https://reactnative.dev/docs/strict-typescript-api) you can extend from `@react-native/typescript-config/strict`

If your app still needs access to deep `'react-native/Libraries/*'` imports (deprecated in 0.80), you can opt out via `customConditions` in your `tsconfig.json`:

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

---

### Overview (`packages/virtualized-lists/README.md`)

# @react-native/virtualized-lists

[ [

[npm]: https://img.shields.io/npm/v/@react-native/virtualized-lists.svg?color=blue
[npm downloads]: https://img.shields.io/npm/dm/@react-native/virtualized-lists.svg

> This is an internal dependency of React Native. **Please don't depend on it directly.**

Virtualized list primitives (`VirtualizedList`, `VirtualizedSectionList`) backing React Native's `FlatList` and `SectionList` components.

---

### Overview (`private/core-cli-utils/README.md`)

# @react-native/core-cli-utils

A reference implementation of React Native CLI tooling. This package provides composable, ordered `Task` objects for common CLI operations including Android Gradle builds, iOS Xcode/CocoaPods workflows, Metro bundling with Hermes support, and cache cleaning.

This is not published to npm. Framework authors can use this code as a starting point for their own CLI tooling, but should not depend on it as a versioned API.

## Modules

- **`android`** — Gradle-based Android build tasks (assemble, build, install)
- **`apple`** — Xcode/CocoaPods-based iOS tasks (bootstrap, build, install)
- **`app`** — Metro bundler tasks (watch mode, bundle mode, Hermes bytecode compilation)
- **`clean`** — Cache-cleaning tasks (Android/Gradle, Metro, npm, Watchman, Yarn, CocoaPods)
- **`version`** — Semver version requirements for platform toolchains (Android NDK/SDK, Xcode, Node, etc.)

## Consumers

- [`private/helloworld/`](../helloworld/) — the primary consumer, using Android, iOS, and Metro modules
- [`packages/rn-tester/`](../../packages/rn-tester/) — uses iOS bootstrap for CocoaPods setup

---

### Overview (`private/eslint-plugin-monorepo/README.md`)

# @react-native/eslint-plugin-monorepo

This is a private package that contains ESLint rules for `react-native` itself.
They are configured in the `.eslintrc.js` at the repository root.

For ESLint rules intended for projects that consume React Native, add them to
the `@react-native-community/eslint-plugin` package instead.

---

### Overview (`private/helloworld/README.md`)

# Hello World Test Application

This is the [**React Native**](https://reactnative.dev) HelloWorld test app. It is for internal use and shouldn't be dependend on.

---

### Overview (`scripts/cxx-api/README.md`)

# scripts/cxx-api

Python build pipeline for React Native's C++ (and Objective-C) API snapshots.

## Overview

`scripts/cxx-api` generates human-readable snapshots of React Native's public C++ API surface. It uses [Doxygen](https://www.doxygen.nl/) to parse C/C++/Objective-C headers and a custom Python parser to produce a simplified, sorted representation of every public symbol. Symbols declared in headers that the C++ stable API classifies as private or "for frameworks" are left out by default (see [Tier filtering](#tier-filtering)).

The pipeline produces one `.api` snapshot file per configured **API view × variant** combination:

| Snapshot | Description |
|---|---|
| `ReactCommonDebugCxx.api` | Platform-independent C++ API (debug) |
| `ReactCommonReleaseCxx.api` | Platform-independent C++ API (release) |
| `ReactAndroidDebugCxx.api` | Android-specific C++ API (debug) |
| `ReactAndroidReleaseCxx.api` | Android-specific C++ API (release) |
| `ReactAppleDebugCxx.api` | Apple-specific C++/Obj-C API (debug) |
| `ReactAppleReleaseCxx.api` | Apple-specific C++/Obj-C API (release) |
| `ReactCommonFrameworksCxx.api` | Platform-independent C++ API, including for-frameworks symbols |
| `ReactAndroidFrameworksCxx.api` | Android-specific C++ API, including for-frameworks symbols |
| `ReactAppleFrameworksCxx.api` | Apple-specific C++/Obj-C API, including for-frameworks symbols |

For each view, debug and release variants are generated with different preprocessor definitions (e.g. `REACT_NATIVE_DEBUG` vs `NDEBUG`), since `#ifdef` guards in the source headers can produce a different public API surface per variant. The frameworks variant uses the view's base definitions and also includes symbols from "for frameworks" headers.

Snapshot files are committed to the repo under `scripts/cxx-api/api-snapshots/`.

## Usage

#### Generate snapshots

Maintainers should run this command whenever making intentional C++ API changes:

```sh
python -m scripts.cxx-api.parser
```

#### Validate snapshots against committed baseline

This mode generates snapshots to a temporary directory and compares them against the committed `.api` files. It is designed for CI:

```sh
python -m scripts.cxx-api.parser --validate
```

If any snapshot differs, a unified diff is printed and the process exits with a non-zero status. To fix a failing validation, regenerate the snapshots with `python -m scripts.cxx-api.parser` and commit the updated `.api` files.

#### Log tier boundary breaks

Pass `--log-boundary-breaks` (in either mode) to print every header whose includes cross a tier boundary, with the include chain that causes it:

```sh
python -m scripts.cxx-api.parser --validate --log-boundary-breaks
```

## How it works

The pipeline has three main stages:

### 1. Tier classification

Every header in a view's inputs is classified by the C++ stable API guard it includes:

| Guard | Tier |
|---|---|
| `react/cxxstableapi/UmbrellaGuard.h` | public |
| `react/cxxstableapi/FrameworksGuard.h` | for frameworks |
| `react/cxxstableapi/PrivateGuard.h` | private |
| none | unclassified |

The headers' `#include`/`#import` directives are resolved into an include graph of the view.

### 2. Doxygen XML generation

Doxygen is configured via a generated config file (built from `.doxygen.config.template`) with the input directories, exclude patterns, and preprocessor definitions specified in `config.yml`. It outputs XML describing every symbol found in the headers.

### 3. Snapshot parsing

The Python parser (`parser/`) reads the Doxygen XML output and builds a scope tree of the public API surface, leaving out symbols declared in skipped headers. The tree is then serialized to a deterministically sorted, human-readable `.api` text format.

## Tier filtering

Each view includes the tiers listed in its `visibility` config (`public`, `frameworks`, `private`), only `public` by default. A header in any other tier is skipped unless a header in an included tier reaches it, directly or through other includes: anything a public header includes is public in practice, whatever its own guard says. Unclassified headers are never skipped.

A boundary break is a public header that reaches a for-frameworks or private header, or a for-frameworks header that reaches a private one. `--log-boundary-breaks` reports them at the edge where visibility drops.

## When to use it

The snapshot should be regenerated whenever making intentional changes to the public C++ API surface. This includes additions, removals, and changes to files located in:
- `xplat/js/react-native-github/`
- `xplat/js/react-native-github/ReactCommon/`
- `xplat/js/react-native-github/ReactAndroid/`
- `xplat/js/react-native-github/ReactApple/`
- `xplat/js/react-native-github/Libraries/`

## Configuration

All API views and their variants are defined in `config.yml`. Each view specifies:

| Field | Description |
|---|---|
| `inputs` | Directories to scan for headers |
| `exclude_patterns` | Glob patterns for files to skip |
| `definitions` | Preprocessor macros to define |
| `variants` | Named build variants (e.g. debug/release) with extra definitions |
| `codegen` | Optional codegen platform (`android`, `ios`) to generate TurboModule/Component headers before scanning |
| `exclude_symbols` | Regex patterns for symbols to skip |
| `input_filter` | Whether to run Doxygen through the input filters in `parser/input_filters/` |
| `visibility` | C++ stable API tiers to include (`public`, `frameworks`, `private`); defaults to `[public]`. See [Tier filtering](#tier-filtering) |

`exclude_patterns` and `exclude_symbols` can also be set at the top level, in which case they apply to every view. A top-level `visibility` applies to every view that does not set its own, and a variant can set `visibility` to override its view's.

## Snapshot format

The `.api` files use a minimal pseudo-C++ syntax designed for easy diffing:

```
namespace facebook::react {
  class ComponentDescriptor {
    public ComponentDescriptor(ComponentDescriptorParameters params);
    public ComponentHandle getComponentHandle();
  }

  enum class AccessibilityRole {
    None = 0,
    Button = 1,
  }
}
```

- Scopes and members are sorted alphabetically.
- Access specifiers (`public`, `protected`) are preserved.
- Template parameters are included.
- Doc comments and source file names are stripped.

---

### Overview (`scripts/js-api/README.md`)

# scripts/js-api

TypeScript build pipeline for React Native's JavaScript API.

## Overview

`yarn build-types` is a custom build pipeline for translating React Native's Flow source code to TypeScript.

Specifically, it reduces the runtime JavaScript API of `react-native` into two outputs:

- **Generated TypeScript types**\
Public user types for react-native, shipped to npm\
`packages/react-native/types_generated/`
- **‌Public API snapshot**\
Snapshot file of the public API shape, used by maintainers\
`packages/react-native/ReactNativeApi.d.ts`

#### Dependencies

`yarn build-types` makes use of the following dependencies, composed with other pre/post transformation steps and dependency resolution.

- Flow → TypeScript conversion: [flow-api-translator](https://www.npmjs.com/package/flow-api-translator)
- TypeScript → (initial) API rollup: [@microsoft/api-extractor](https://api-extractor.com/)

## Usage

#### Build generated types + API snapshot

Maintainers should run this script whenever making intentional API changes.

```sh
# Build types + API snapshot
yarn build-types [--validate]

# Build types without API snapshot
yarn build-types --skip-snapshot
```

#### Diff API snapshot compatibility

This script is run by CI to compare changes to `ReactNativeApi.d.ts` between commits.

```sh
# Compare two versions of the API snapshot
yarn js-api-diff <before.d.ts> <after.d.ts>
```
```json
{
  "result": "BREAKING",
  "changedApis": [
    "ViewStyle"
  ]
}
```

#### Configuration

Sparse configuration options are defined and documented in `scripts/js-api/config.js`.

## About the two output formats

### Generated TypeScript types

`types_generated/`

Directory providing TypeScript user types for the `react-native` package, distributed via npm.

- Gitignored.
- Scoped to the `index.d.ts` entry point via `package.json#exports`.
- Preserves `unstable_` and `experimental_` APIs.
- Preserves doc comments.
- Preserves source file names (for go to definition).

### Public API snapshot

`ReactNativeApi.d.ts`

Provides a human-readable, maintainable reference of the React Native's public JavaScript API, optimized for developers and diff tooling.

- Committed to the repo.
- Strips `unstable_` and `experimental_` APIs.
- Strips doc comments.
- Strips source file names (types are merged into a single program).
- Versions exported APIs with an 8 char SHA hash, which will be updated when any input type dependencies change shape.

---

### Overview (`scripts/release-testing/README.md`)

# scripts/release-testing

Scripts supporting local manual release testing. See also [How to Test a Release](https://reactnative.dev/contributing/release-testing).

## Commands

For information on command arguments, run `node <command> --help`.

### `test-release-local`

Set up, build, and install a given test app configuration.

### `test-release-local-clean`

Clean up all file system and cache state between tests.

---

### Overview (`scripts/releases-ci/README.md`)

# scripts/releases-ci

CI-only release scripts — intended to run from a CI workflow (GitHub Actions).

## Commands

For information on command arguments, run `node <command> --help`.

### `prepare-package-for-release`

Prepares files within the `react-native` package and template for the target release version. Writes a new commit and tag, which will trigger `publish-npm.js` in a new workflow.

### `publish-npm`

Prepares release artifacts and publishes the `react-native` package to npm.

### `cleanup-maven-staging-repositories`

Drops Sonatype staging repositories that exactly match the description in
`ORG_GRADLE_PROJECT_SONATYPE_REPOSITORY_DESCRIPTION`, along with any associated
unpublished Central Portal deployments.

### `publish-updated-packages`

Publishes all updated packages (excluding `react-native`) to npm. Triggered when a commit on a release branch contains `#publish-packages-to-npm`.

---

### Overview (`scripts/releases/README.md`)

# scripts/releases

Scripts related to creating a React Native release. These are the lower level entry points used by [**scripts/releases-ci**](https://github.com/facebook/react-native/tree/main/scripts/releases-ci).

## Commands

For information on command arguments, run `node <command> --help`.

### `create-release-commit`

Creates a release commit to trigger a new release.

### `set-version`

Bump the version of all packages.

- Updates `package.json` metadata for all workspaces and the project root.
- Updates relevant native files in the `react-native` package.

If `--skipReactNativeVersion` is passed, the `react-native` package version will be left unmodified as `"1000.0.0"` (special static version on `main`), and native files will not be touched.

### `set-rn-artifacts-version`

> [!Note]
> **Deprecated**: Prefer `set-version`. This entry point is a subset of `set-version`, and is used only by test workflows. We will replace these call sites in future.

Updates relevant native files in the `react-native` package to materialize the given release version. This is run by `set-version` unless `--skipReactNativeVersion` is passed.

---

### Overview (`packages/gradle-plugin/react-native-gradle-plugin/README.md`)

# React Native Gradle Plugin

This plugin is used by React Native Apps to configure themselves.

NOTE: It's important that this folder is called `react-native-gradle-plugin` as it's used
by users in their `build.gradle` file as follows:

```gradle
buildscript {
    // ...
    dependencies {
        classpath("com.facebook.react:react-native-gradle-plugin")
    }
}
```

The name of the artifact is imposed by the folder name.

---

### Overview (`packages/react-native/ReactAndroid/README.md`)

# Building React Native for Android

See the [Building from Source guide](https://reactnative.dev/contributing/how-to-build-from-source#prerequisites) on the React Native website.

# Running tests

When you submit a pull request, ci will automatically run all tests.
To run tests locally, see [Testing guide](https://reactnative.dev/contributing/how-to-run-and-write-tests) on the React Native website.

---

### Overview (`packages/react-native/ReactApple/README.md`)

# ReactApple

ReactApple contains code to ship React Native apps to Apple devices. The dominant language is Objective-C.

New libraries built with Apple frameworks or intended to ship to Apple devices should live in this directory.

---

### Overview (`packages/rn-tester/visual-tests/README.md`)

# RNTester visual tests

Visual tests capture screenshots of RNTester examples in CI and compare them with the screenshots of the same tests on `main`. They catch rendering changes, particularly in text layout, that functional E2E tests don't.

Each test is a [Maestro](https://maestro.dev) flow in `flows/`. Maestro only opens the example and takes the screenshot - comparison happens afterwards in CI, so a flow never decides whether it passed.

## How it runs in CI

1. Test All builds RNTester Release for Android and iOS. Once a build is ready, the `test_visual_android_rntester` and `test_visual_ios_rntester` jobs (`.github/workflows/visual-capture-rntester.yml`) run every flow in this directory on one canonical device per platform: an API 35 Pixel 7 emulator and an iPhone 17 Pro simulator on iOS 26.2. They upload the screenshots and a manifest of the device environment as `visual-capture-android` and `visual-capture-ios` artifacts.
2. When Test All completes, Visual Compare RNTester (`.github/workflows/visual-compare-rntester.yml`) compares the screenshots with the baseline and reports a `Visual regression (android)` and `Visual regression (ios)` check and a `Visual regression approval` gate, plus a single PR comment with the expected, captured and diff images for anything that changed.
3. On pushes to `main`, Visual Compare RNTester also publishes the captures as the baseline for that commit. There's no separate workflow for this: the same run publishes them once it has compared them.

Only `main` and pull requests into it are compared. Stable branches have no baselines, so Visual Compare RNTester skips them.

The baseline for a PR is the one for the commit it's based on, or the nearest earlier commit on `main` that has one. Baselines are keyed by device environment too (OS image, screen size, density, font scale, locale and so on), so a change to the CI device starts a fresh baseline rather than failing every PR.

## Adding a test

1. Pick or add an RNTester example, and give its root view a `testID`. Keep the example's content fixed: no dates, random values, network images or animations that are still running when the screenshot is taken.
2. Add a flow to `flows/`. File names must be unique, and each `takeScreenshot` path becomes the test ID, so make it descriptive:

   ```yaml
   appId: ${APP_ID}
   ---
   - runFlow:
       file: ../helpers/open-example.yml
       env:
         EXAMPLE_URL: rntester://example/TextExample/textWidthMode
   - extendedWaitUntil:
       visible:
         id: 'text-width-mode-example'
       timeout: 15000
   - takeScreenshot:
       path: ${VISUAL_OUTPUT_DIR}/text/width-mode/default
       cropOn:
         id: 'text-width-mode-example'
   ```

   `open-example.yml` deep-links to `rntester://example/<module>/<example>`. Wait for something that's only visible once the example has rendered, and crop to the example's `testID` so that the status bar and surrounding UI aren't part of the screenshot.

3. Open a PR. The new test has no baseline yet, so the report lists it as new, and like any other difference it needs a maintainer's approval (see below). Once the PR lands, `main` is captured with it and later PRs are compared against that.

To try a flow locally, build and install RNTester Release on a simulator or emulator and run it with Maestro:

```sh
maestro test \
  -e APP_ID=com.meta.RNTester.localDevelopment \
  -e VISUAL_OUTPUT_DIR=/tmp/visual \
  packages/rn-tester/visual-tests/flows/text-width-mode.yml
```

Use `com.facebook.react.uiapp` as the `APP_ID` on Android. Local screenshots are only useful for checking the flow and the crop - they won't match CI's pixel for pixel unless you use the same device and OS image.

## When a check fails

Open the PR comment or the check run and compare the expected, captured and diff images.

- If the change is unintended, fix it and push.
- If it's intended, a maintainer applies the `visual-change-approved` label. The approval covers the exact set of differences in the report: if a later push changes them, the label is removed and the PR needs a new review. The baseline itself only changes once the PR lands and `main` is captured again.

## Tolerances

Comparison is strict by default: any changed pixel is a difference. If a test is genuinely nondeterministic, loosen it for that test in `config.json`, keyed by test ID, and say why in the PR:

```json
{
  "defaults": {"threshold": 0, "includeAA": true, "maxDiffPixels": 0},
  "tests": {
    "text/width-mode/default": {"maxDiffPixels": 20}
  }
}
```

`threshold` is pixelmatch's per-pixel color distance from 0 to 1, `includeAA` counts anti-aliased pixels, and `maxDiffPixels` and `maxDiffRatio` set how many changed pixels (or what share of the image) can pass. Prefer making the example deterministic over adding a tolerance.

---

### Overview (`private/react-native-fantom/__docs__/README.md`)

# 👻 React Native Fantom

[🏠 Home](../../../__docs__/README.md)

> [!WARNING]
>
> This is experimental!
>
> We are limiting the scope of the project to just React Native internals for
> now, so we can iterate on it quickly and keep the maintenance costs at bay.
>
> In the future, we might explore providing it for testing library/product code
> internally and externally.
>
> This means tests must live in `packages/react-native`.

Fantom is the new **integration testing and benchmarking tool for React
Native**.

Its main goal is to allow running JavaScript code as close as possible to a real
React Native application, using its cross-platform architecture (Hermes, Fabric,
C++ TurboModules, Bridgeless, etc.) in a fast headless environment that can run
on CI.

Removing the need for real devices and simulators makes this faster and more
stable than existing e2e testing solutions, while still allowing us to test the
integration between JavaScript and native without the need for mocks.

When compared against Jest, layout is calculated and can be inspected in tests:

```javascript
const root = Fantom.createRoot({viewportWidth: 200, viewportHeight: 600});
let viewElement;

Fantom.runTask(() => {
  root.render(
    <View
      ref={node => {
        viewElement = node;
      }}
      style={{width: '50%', height: '10%'}}
    />,
  );
});

// Without Fantom, getBoundingClientRect would have to be mocked.
const boundingClientRect = viewElement.getBoundingClientRect();
expect(boundingClientRect.height).toBe(60);
expect(boundingClientRect.width).toBe(100);
```

Fantom is designed to make it possible to test the integration between
JavaScript, React and React Native core - platform agnostic parts. When you are
making a change to any of these parts, you should consider writing a Fantom test
for it. It is geared towards engineers working on React Native.

With Fantom you can create scenarios close to those how a real product will
interact with React Native and observe what effects it has on a mock host
platform. It exposes fine grained controls over scheduling, making it possible
to test cases that are hard to reproduce manually.

## 🚀 Usage

Create a file with the `-itest.js` suffix anywhere you would normally create a
Jest unit test file.

The high level structure of Fantom tests is similar to Jest unit tests. However,
only a subset of Jest's Global API is currently available. For example,
`test.each` is not yet implemented in Fantom. We are working on adding more Jest
APIs. If you are blocked by the lack of a specific API, please reach out to us.

Most of the interesting APIs are available via the `@react-native/fantom`
package. Test files should also import `setUpDefaultReactNativeEnvironment` at
the top to set up the React Native environment. **Do not import
`InitializeCore`** — it installs LogBox, which interferes with Fantom's error
handling.

```javascript
import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
import * as Fantom from '@react-native/fantom';

describe('My feature', () => {
  it('should do something interesting', () => {
    const root = Fantom.createRoot();

    Fantom.runTask(() => {
      root.render(/* ... */);
    });

    /* some checks */
  });
});
```

For a full API reference, please see the [inline documentation](../src/index.js)
defined for the methods in the `@react-native/fantom` [module](../src/index.js).

You can check out existing files with the `-itest.js` suffix (e.g.:
[`View-itest`](../../../packages/react-native/Libraries/Components/View/__tests__/View-itest.js))
for code examples.

Run the test using the following command from the root of the React Native
repository:

```shell
yarn fantom <regexForTestFiles>
```

Similar to Jest, you can also run Fantom in watch mode using `--watch`:

```shell
yarn fantom <regexForTestFiles> --watch
```

### Interactive REPL

> [!WARNING]
>
> The REPL is experimental — its behavior and APIs may change.

You can start an interactive REPL that evaluates JavaScript against the same
Hermes runtime and React Native environment that Fantom tests use:

```shell
yarn fantom-cli
```

Each line is evaluated in a persistent session (bindings declared on one line
are available on the next) and goes through Metro, so `import`, JSX and Flow
syntax all work. `React`, `ReactNative` and the `Fantom` API are exposed as
globals, so you can explore them — and render surfaces — without importing
anything. Results are printed with a console-style inspector (similar to Chrome
DevTools / Node.js), and pressing <kbd>Tab</kbd> autocompletes global
identifiers, in-scope bindings and object properties.

```text
👻 Fantom REPL — evaluating against Hermes inside the Fantom runtime.
   ⚠️  Experimental: behavior and APIs may change.
fantom> const x = 21
fantom> x * 2
42
fantom> ({items: [1, 2, 3], nested: {ok: true}})
{ items: [ 1, 2, 3 ], nested: { ok: true } }
```

Press <kbd>Ctrl</kbd>+<kbd>D</kbd> to exit.

Like Node, you can also evaluate a snippet and exit with `-e`, or run a script
file:

```shell
yarn fantom-cli -e "console.log(Fantom.getHostPlatform())"
yarn fantom-cli path/to/script.js
```

In both cases the value of a trailing expression is not printed (use
`console.log`), and a thrown error exits with a non-zero status code.

#### Timers and asynchronous code in the REPL

The REPL runs in the Fantom environment, which uses a **deterministic virtual
clock** — real wall-clock time never passes on its own. A zero-delay
`setTimeout(fn, 0)` runs right after the current line, but timers with a delay
(and `setInterval`) stay pending until the clock is advanced, so this does
**not** print on its own:

```text
fantom> setTimeout(() => console.log('hi'), 1000)
```

Drive timers by installing the timer mock and advancing the clock, exactly like
in a test (see the timers FAQ below):

```text
fantom> const timers = Fantom.installTimerMock()
fantom> setTimeout(() => console.log('hi'), 1000)
fantom> timers.advanceTimersByTime(1000)
hi
```

### Conventions

- Prefer testing React Native through its public API (import from
  `'react-native'`) whenever possible, rather than reaching into internal
  modules or relying on private/protected members (e.g. `__`-prefixed methods
  and fields such as `__getValue()`). Exercising the public API also drives the
  underlying native (Fabric/TurboModules) code, so tests stay close to real
  usage and are more resilient to internal refactors. Observe results through
  the public surface too — e.g. assert the rendered output
  (`root.getRenderedOutput(...)`) or values delivered to public listeners rather
  than reading private state.
  - When Fantom doesn't support something (a native module, a capability, a way
    to observe a result, etc.), it's fine to reach into internals to work around
    that limitation. Prefer a short comment explaining why the internal access
    is necessary.
- Place test files in `__tests__` directories alongside the code being tested.
- Benchmark tests use the `-benchmark-itest.js` suffix.
- Use `Fantom.runTask()` to render and run synchronous operations; it ensures
  the React work is flushed before assertions.
- Access elements through refs and use `nullthrows` for type-safe access to the
  underlying instance:

  ```javascript
  import nullthrows from 'nullthrows';

  const element = nullthrows(elementRef.current);
  ```

- Prefer component-specific instance types (`TextInputInstance`,
  `ScrollViewInstance`, etc.) over the generic `HostInstance` when available.
- For components with imperative APIs (`focus`, `blur`, `clear`, etc.), test:
  - Each method's behaviour and edge cases (e.g. `blur` when not focused).
  - Method timing — that it works when called from refs, `useLayoutEffect`, and
    `useEffect`.
- Verify that native commands are dispatched with
  `root.takeMountingManagerLogs()`.
- Don't write tests with only trivial assertions like
  `expect(element).toBeDefined()` when more complex behaviour is under test.
  When a test fails, understand what should render rather than weakening the
  assertion to make it pass.

### Assertions

Prefer evaluating rendered output inline with `.toEqual()` and inline JSX over
`.toMatchSnapshot()` or weak numeric assertions like
`element.childNodes.length`.

```javascript
// Get JSX representation
expect(root.getRenderedOutput().toJSX()).toEqual(
  <rn-view width="100" height="50" />,
);

// Include layout metrics
expect(root.getRenderedOutput({includeLayoutMetrics: true}).toJSX()).toEqual(
  <rn-view
    layoutMetrics-frame="{x:0,y:0,width:100,height:50}"
    layoutMetrics-displayType="Flex"
  />,
);

// Filter to specific props for minimal assertions
expect(root.getRenderedOutput({props: ['backgroundColor']}).toJSX()).toEqual(
  <rn-view backgroundColor="rgba(255, 0, 0, 1)" />,
);
```

For element-level assertions, get a typed reference and inspect tag names,
layout metrics, or children:

```javascript
const elementRef = createRef<HostInstance>();

Fantom.runTask(() => {
  root.render(
    <View ref={elementRef}>
      <Text>the quick brown fox</Text>
    </View>,
  );
});

const element = ensureInstance(elementRef.current, ReactNativeElement);
expect(element.tagName).toBe('RN:View');

const bounds = element.getBoundingClientRect();
expect(bounds.width).toBe(100);
expect(bounds.height).toBe(50);

expect(root.getRenderedOutput().toJSX()).toEqual(
  <rn-view>
    <rn-paragraph>the quick brown fox</rn-paragraph>
  </rn-view>,
);
```

### Limitations

- `Fantom.runTask()` calls cannot be nested — doing so will throw.
- Only a subset of Jest's Global API is available (e.g. `test.each` is not
  implemented). Reach out if you're blocked by a specific missing API.
- Tests must live within `packages/react-native`; Fantom is not currently
  intended for application-specific code.

### Test configuration

You can configure certain aspects of the test execution using pragmas in the
docblock at the top of the file. E.g.:

```javascript
/**
 * @fantom_flags jsOnlyTestFlag:true
 * @fantom_mode opt
 */
```

Available pragmas:

- `@fantom_flags`: used to set overrides for
  [`ReactNativeFeatureFlags`](../../../packages/react-native/src/private/featureflags/__docs__/README.md).
  - Example: `@fantom_flags name:value`.
  - Multiple flags can be defined in different lines or in the same line
    separated by spaces (e.g.: `@fantom_flags name:value otherName:otherValue`).
- `@fantom_mode`: used to define the compilation mode for the bundle.
  - Example: `@fantom_mode opt`
  - Possible values:
    - `dev`: development, default for tests.
    - `opt`: optimized and using Hermes bytecode, default for benchmarks.
- `@fantom_native_opt`: used to define the compilation mode for native code.
  - Example: `@fantom_native_opt true`
  - Possible values:
    - `true`: optimized native code
    - `false`: development native code
- `@fantom_js_opt`: used to define the compilation mode for the JS bundle.
  - Example: `@fantom_js_opt true`
  - Possible values:
    - `true`: optimized JS bundle
    - `false`: development JS bundle
- `@fantom_js_bytecode`: used to define if the JS bundle should use bytecode.
  - Example: `@fantom_js_bytecode true`
  - Possible values:
    - `true`: using Hermes bytecode
    - `false`: not using Hermes bytecode
- `@fantom_disable_coverage`: used to disable coverage collection for the test.
  - Example: `@fantom_disable_coverage`
  - Does not require a value.
- `@fantom_react_fb_flags`: used to set overrides for internal React flags set
  in ReactNativeInternalFeatureFlags (Meta use only)

Setting `@fantom_mode` is mutually exclusive with setting any of
`@fantom_native_opt`, `@fantom_js_opt`, and `@fantom_js_bytecode`.

For all pragmas, except non-boolean feature flags, you can use a wildcard (`*`)
as value to run the test with all possible values for that pragma. For example,
this test:

```javascript
/**
 * @fantom_flags jsOnlyTestFlag:*
 * @fantom_mode *
 */
```

Would be executed with these combinations of options:

| `jsOnlyTestFlag` | `mode` |
| ---------------- | ------ |
| `false`          | `dev`  |
| `true`           | `dev`  |
| `false`          | `opt`  |
| `true`           | `opt`  |

With an output such as:

```text
  Test (jsOnlyTestFlag 🛑)
    [...]
  Test (jsOnlyTestFlag ✅)
    [...]
  Test (mode 🐛🔢, jsOnlyTestFlag 🛑)
    [...]
  Test (mode 🐛🔢, jsOnlyTestFlag ✅)
    [...]
  Test (mode 🚀, jsOnlyTestFlag 🛑)
    [...]
  Test (mode 🚀, jsOnlyTestFlag ✅)
    [...]
```

### Debugging

> [!WARNING] Meta-only: debugging only works on Meta's internal infrastructure
> at the moment.

You can use environment variables to enable debugging for your tests. These
options can be combined to debug JS and C++ at the same time.

#### Debugging JS

To debug JavaScript, run your fantom test with the flag `FANTOM_DEBUG_JS`:

```shell
FANTOM_DEBUG_JS=1 yarn fantom <regexForTestFiles>
```

This would open React Native DevTools, which would stop at a breakpoint at the
beginning of your test so you can debug it.

#### Debugging C++

To debug C++, run your fantom test with the flag `FANTOM_DEBUG_CPP`:

```shell
FANTOM_DEBUG_CPP=1 yarn fantom <regexForTestFiles>
```

This would start a debugging session in VS Code with an initial breakpoint in
the Fantom CLI binary.

#### Address and thread sanitizer for C++

It's also possible to run the C++ side with the thread or address sanitizer
enabled, which can help with debugging memory and threading issues.

To enable the address sanitizer, run your fantom test with the flag
`FANTOM_ENABLE_ASAN`:

```shell
FANTOM_ENABLE_ASAN=1 yarn fantom <regexForTestFiles>
```

For thread sanitizer, correspondingly, use flag `FANTOM_ENABLE_TSAN`:

```shell
FANTOM_ENABLE_TSAN=1 yarn fantom <regexForTestFiles>
```

### Profiling

#### JS sampling profiler

You can automatically record JS sampling profiler traces with the flag
`FANTOM_PROFILE_JS`:

```shell
FANTOM_PROFILE_JS=1 yarn fantom <regexForTestFiles>
```

As part of the test results, you will see a message indicating where the traces
where saved, e.g.:

```text
🔥 JS sampling profiler trace saved to /path/to/react-native/private/react-native-fantom/.out/js-traces/View-itest.js-2025-08-12T14:08:31.580Z.cpuprofile
```

If your test has multiple variants (when using wildcards in Fantom pragmas), a
trace will be created for each variant.

You can analyze the traces loading them in Chrome DevTools directly. You can
also open them in VS Code, which provides a built-in extension for analysis.

#### JS memory profiler

You can manually take JS memory heap snapshots during test execution using
`Fantom.takeJSMemoryHeapSnapshot()`. E.g.:

```javascript
// Using the 3 snapshot method to detect memory leaks:

// Warm up
renderView();
destroyView();

// #1
Fantom.takeJSMemoryHeapSnapshot();

renderView();

// #2
Fantom.takeJSMemoryHeapSnapshot();

destroyView();

// #3
Fantom.takeJSMemoryHeapSnapshot();

// See the objects allocated between #1 and #2 that still exist in #3.
```

This function will force a garbage collection pass, take a snapshot of the JS
memory heap and print a message indicating where it was saved. E.g.:

```text
💾 JS heap snapshot saved to /path/to/react-native/private/react-native-fantom/.out/js-heap-snapshots/View-itest.js-2025-08-12T14:29:25.987Z.heapsnapshot
```

You can have multiple calls to `Fantom.takeJSMemoryHeapSnapshot()` in your test,
and each one will create a different file.

#### C++ sampling profiler

You can automatically record C++ sampling profiler traces (with DWARF call
graphs) by wrapping the Fantom tester binary with Linux `perf record`. Run your
fantom test with the flag `FANTOM_PROFILE_CPP`:

```shell
FANTOM_PROFILE_CPP=1 yarn fantom <regexForTestFiles>
```

Output is saved to `.out/cpp-traces/perf-<timestamp>.data`. Analyze it with:

```shell
perf report -i .out/cpp-traces/perf-<timestamp>.data
```

This is not available on CI (the runner will throw an error if attempted) and
requires `perf` to be installed on the host.

### Running the full suite locally

When running the entire suite locally, set `FANTOM_FORCE_CI_MODE=1`:

```shell
FANTOM_FORCE_CI_MODE=1 yarn fantom
```

In CI mode, `globalSetup` pre-builds the entire
`(hermesVariant × enableOptimized)` binary matrix once up-front (see
[`global-setup/build.js`](../runner/global-setup/build.js)) and per-test buck2
invocations are skipped. This eliminates buck2 daemon contention from the worker
pool, which can otherwise cause sporadic build failures when many workers race
to build different binary variants at the same time.

CI environments (`SANDCASTLE`, `GITHUB_ACTIONS`) auto-detect this mode — see
[`runner/EnvironmentOptions.js`](../runner/EnvironmentOptions.js).

### FAQ

#### How is this different from Jest tests?

Fantom runs C++ part of React Native, as well as JavaScript on Hermes VM -
unlike Jest tests that run on V8. This makes it possible to test things related
to shadow nodes, layout, events, scheduling, C++ state updates to name a few.
The results of Fabric are mounted in a mock UI tree that can be asserted against
and individual mounting instructions can be inspected.

You can even test your C++ code. For example, we have
[Fantom tests for the new View Culling optimization](../../../packages/react-native/Libraries/Components/ScrollView/__tests__/ScrollView-viewCulling-itest.js),
which is written in C++.

#### How can I test logic related to &lt;ScrollView /> scrolling?

Fantom exposes the method `Fantom.scrollTo`. This method will trigger an
onScroll event and configure the shadow tree to reflect the new content offset:

```javascript
Fantom.scrollTo(scrollViewElement, {
  x: 0,
  y: 1,
});

expect(scrollViewElement.scrollTop).toBe(1);
```

#### How can I test logic that relies on timers (`setTimeout`/`setInterval`)?

Fantom runs on a **deterministic virtual clock**: wall-clock time never advances
on its own, and Fantom decides when the event loop and timers run. In the
default environment a zero-delay `setTimeout(fn, 0)` is dispatched on the next
work-loop tick, but timers with a positive delay (and any `setInterval`) stay
pending and never fire unless the virtual clock is advanced.

To advance the clock and run those callbacks, install a deterministic timer mock
with `Fantom.installTimerMock()`. While installed, you advance a virtual clock
to fire them, similar to `jest.useFakeTimers()`:

```javascript
const timers = Fantom.installTimerMock();

const callback = jest.fn();
setTimeout(callback, 100);

timers.advanceTimersByTime(50);
expect(callback).toHaveBeenCalledTimes(0);

timers.advanceTimersByTime(50);
expect(callback).toHaveBeenCalledTimes(1);

timers.uninstall();
```

`advanceTimersByTime`/`runAllTimers` run the work loop internally, so callbacks
have executed by the time they return. Use `getPendingTimerCount()` to inspect
how many timers are still scheduled, and `uninstall()` (typically in
`afterEach`) to restore the default behavior.

#### What can be tested with Fantom?

Fantom was designed to make it possible to test integration between React and
Fabric with the Jest API that many people are familiar with. You can write code
to simulate any kind of input into React and assert what the output is from
React Native core to the host platform. Fantom controls the app's message queue,
which gives complete control over scheduling. This makes it possible to write
tests that simulate scenarios where an event interrupts React rendering in a
deterministic fashion.

Even JavaScript only code can be tested with Fantom. We are considering fully
deprecating "vanilla" Jest in favor of Fantom for all JavaScript tests in React
Native.

#### Is Fantom ready for production use cases?

Fantom is a stable and reliable testing framework that is here to stay. If
you're planning to make changes to React or React Native internals, we highly
recommend using Fantom as your go-to testing solution.

**Important Note:** While Fantom is ideal for testing React and React Native
internals, it is not currently supported for testing application-specific code
in React Native apps. We'll keep you updated on any future developments that may
change this.

#### Where can I find examples of tests?

Look for files with the `-itest.js` suffix to find existing tests. The Fantom
test for its public API ([`Fantom-itest.js`](../src/__tests__/Fantom-itest.js))
has simple examples you can learn from.

#### Are tests executed on Github CI?

Fantom tests are currently tied to Meta's infrastructure and do not run outside
of Meta's CI. We are working on migrating Fantom to Github CI. If you submit a
PR, the tests will run as part of the PR import process.

#### Can I gate individual tests within a suite to only run, or not run, with a specific feature flag?

Yes, you can use the `@fantom_flags` pragma to customize the flags that are
going to be used for the entire test suite, and conditionally define or exclude
the test in the suite depending on the flag value for that run. E.g.:

```javascript
/**
 * @fantom_flags commonTestFlag:*
 */

import {ReactNativeFeatureFlags} from 'react-native/react-private-interface';

// The entire suite will be run with commonTestFlag set to true and false.
describe('MyTest', () => {
  it('should run with all values of the flag', () => {
    // ...
  });

  if (ReactNativeFeatureFlags.commonTestFlag()) {
    it('should only run when the flag is true', () => {
      // ...
    });
  }

  if (!ReactNativeFeatureFlags.commonTestFlag()) {
    it('should only run when the flag is false', () => {
      // ...
    });
  }
});
```

And the result would look like this:

```text
 PASS  MyTest-itest.js
  MyTest (commonTestFlag ❌)
    ✓ should run with all values of the flag
    ✓ should only run when the flag is false
  MyTest (commonTestFlag ✅)
    ✓ should run with all values of the flag
    ✓ should only run when the flag is true
```

---

If you have any questions not answered here, please reach out to us.

## 📐 Design



Fantom tests are meant to be written, executed and reported as regular Jests
tests. To accomplish that, **Fantom is implemented as a Jest test runner**.

Fantom provides a [Jest configuration](../config/jest.config.js) to use
[its runner](../runner/runner.js) for any tests matching the `-itest.js` suffix
within the repository.

When Jest runs, for every file that matches that configuration, it calls into
the Fantom runner, which receives the path to the test file along with different
configuration objects.

The runner then follows these steps:

1. It creates a single "executable" JavaScript file using Metro (with this
   [configuration](../config/metro.config.js)), containing the test itself, its
   dependencies and some glue code to run the test at runtime and report its
   results. Depending on the configured "mode" for the test, the runner might
   compile that JavaScript file into Hermes bytecode.
2. It calls into the Fantom CLI passing the path to the executable JavaScript
   code (or Hermes bytecode) and the configured feature flags for the test. The
   Fantom CLI evaluates that code in the context of a React Native C++
   application and prints the results as JSON via its standard output.
3. The runner receives the output from the Fantom CLI and reports the provided
   results back to Jest in the correct format.

## 🔗 Relationship with other systems

### Part of this

- The Fantom runner, which provides the integration point with Jest.
- The Fantom CLI, which provides the execution environment for the Fantom
  JavaScript tests.
- The Fantom benchmarking system, which is just a library and some automatic
  configuration on top of Fantom.

### Used by this

- Metro, to compile the test code into a single file consumable by the Fantom
  CLI.
- Hermes Compiler, to compile the JavaScript test code into Hermes bytecode.
- The
  [React Native Feature Flags](../../../packages/react-native/src/private/featureflags/__docs__/README.md)
  system, via the `@fantom_flags` pragmas defined in the docblock for test
  files.

---

### Overview (`packages/react-native/Libraries/Renderer/README.md`)

# React & React Native Versions

This page describes how React and React Native versions interact each other.
The version alignment between the two frameworks relies on two synchronization points:

1. The versions in the `package.json` of the new app template. For example [for React Native 0.68.1](https://github.com/facebook/react-native/blob/0.68-stable/template/package.json#L12-L15) the versions are aligned as follows:

```
  "dependencies": {
    "react": "17.0.2",
    "react-native": "0.68.1"
  },
```

1. The React renderers **shipped** with React Native inside this folder, the [./Libraries/Renderer](https://github.com/facebook/react-native/tree/main/Libraries/Renderer) folder, of React Native.

This practically means that you **can't bump** the version of React in your `package.json` to a later version,
as you will still be using the older renderer from the folder mentioned above. Bumping the react version in your `package.json` will lead to unexpected behaviors.

For the sake of React 18, the first version of React Native compatible with React 18 is **0.69.0**. Users on React Native 0.68.0 and previous versions won't be able to use React 18.

If you use the [React Native Upgrade Helper](https://react-native-community.github.io/upgrade-helper/), you'll bump to the correct React version once you upgrade React Native.

---

### Overview (`scripts/releases/ios-prebuild/__docs__/README.md`)

# iOS Prebuild Scripts Documentation

This folder contains scripts for creating precompiled XCFrameworks for React
Native's dependencies. These scripts automate the process of downloading,
building, and packaging third-party libraries into distributable XCFramework
bundles for iOS.

## Overview

The iOS prebuild system creates precompiled frameworks to reduce build times for
React Native iOS apps. Instead of compiling dependencies from source during
every build, these scripts package them as ready-to-use XCFrameworks.

The prebuild process creates a Swift package that builds frameworks for the
following 3rd party libraries:

- boost
- folly
- glog
- fmt
- double-conversion
- socketrocket
- fast-float

## Main Scripts

### `cli.js`

Command-line interface for the prebuild system.

```bash
node scripts/releases/prepare-ios-prebuilds.js
```

If no options are passed, the script executes all the steps in this order:

- setup dependencies and prepares them
- creates Swift package file
- builds for all platforms and configurations
- creates xcframeworks

**Options:**

| Option             | Short | Description                                             |
| ------------------ | ----: | ------------------------------------------------------- |
| `--setup`          |  `-s` | Download and setup dependencies                         |
| `--build`          |  `-b` | Build dependencies for target platforms                 |
| `--compose`        |  `-c` | Compose XCFrameworks from built artifacts               |
| `--swiftpackage`   |  `-w` | Generate `Package.swift` file                           |
| `--platforms`      |  `-p` | Target platforms (ios, macos, catalyst, tvos, visionos) |
| `--configurations` |  `-g` | Build configurations (Debug, Release)                   |
| `--dependencies`   |  `-d` | Specific dependencies to process                        |
| `--clean`          |     — | Clean build folder before building                      |
| `--identity`       |  `-i` | Signing identity for frameworks                         |

## Integrating in your project with Cocoapods

To use the prebuilt React Native Dependencies XCFrameworks in your iOS project,
run pod install with the environment variable `RCT_USE_RN_DEP` set to `1`:

```bash
RCT_USE_RN_DEP=1 bundle exec pod install
```

This can be combined with `RCT_USE_RN_DEP=1` to use both React Native and its
dependencies as prebuilt frameworks.

For debugging and troubleshooting the Cocoapods scripts, you can use the
following environment variables:

- `RCT_USE_RN_DEP`: If set to 1, it will use the release tarball from Maven
  instead of building from source.
- `RCT_USE_LOCAL_RN_DEP`: **TEST ONLY** If set, it will use a local tarball of
  ReactNativeDependencies if it exists.
- `RCT_DEPS_VERSION`: **TEST ONLY** If set, it will override the version of
  ReactNativeDependencies to be used.

---

### Overview (`packages/dev-middleware/src/inspector-proxy/__docs__/README.md`)

# Inspector Proxy Protocol

[🏠 Home](../../../../../__docs__/README.md)

The inspector-proxy protocol facilitates Chrome DevTools Protocol (CDP) target
discovery and communication between **debuggers** (e.g., Chrome DevTools, VS
Code) and **devices** (processes containing React Native hosts). The proxy
multiplexes connections over a single WebSocket per device, allowing multiple
debuggers to connect to multiple pages on the same device.

## 🚀 Usage

### Target Discovery (HTTP)

We implement a subset of the
[Chrome DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/)'s
[HTTP endpoints](https://chromedevtools.github.io/devtools-protocol/#:~:text=a%20reconnect%20button.-,HTTP%20Endpoints,-If%20started%20with)
to allow debuggers to discover targets.

| Endpoint                    | Description              |
| --------------------------- | ------------------------ |
| `GET /json` or `/json/list` | List of debuggable pages |
| `GET /json/version`         | Protocol version info    |

### Device Registration (WebSocket)

Devices register themselves with the proxy by connecting to `/inspector/device`:

```text
ws://{host}/inspector/device?device={id}&name={name}&app={bundle_id}&profiling={true|false}
```

| Parameter   | Required | Description                                                  |
| ----------- | -------- | ------------------------------------------------------------ |
| `device`    | No\*     | Logical device identifier. Auto-generated if omitted.        |
| `name`      | No       | Human-readable device name. Defaults to "Unknown".           |
| `app`       | No       | App bundle identifier. Defaults to "Unknown".                |
| `profiling` | No       | "true" if this is a profiling build. (Used for logging only) |

\*Recommended for connection persistence across app restarts.

#### Requirements for the `device` parameter

The intent of the logical device ID is to help with target discovery and
especially *re*discovery - to reduce the number of times users need to
explicitly close and restart the debugger frontend (e.g. after an app crash).

If provided, the logical device ID:

1. SHOULD be stable for the current combination of physical device (or emulator
   instance) and app.
2. SHOULD be stable across installs/launches of the same app on the same device
   (or emulator instance), though it MAY be user-resettable (so as to not
   require any special privacy permissions).
3. MUST be unique across different apps on the same physical device (or
   emulator).
4. MUST be unique across physical devices (or emulators).
5. MUST be unique for each concurrent _instance_ of the same app on the same
   physical device (or emulator).

NOTE: The uniqueness requirements are stronger (MUST) than the stability
requirements (SHOULD). In particular, on platforms that allow multiple instances
of the same app to run concurrently, requirements 1 and/or 2 MAY be violated in
order to meet requirement 5. This is relevant, for example, on desktop
platforms.

### Debugger Connection (WebSocket)

Debuggers connect to `/inspector/debug` to form a CDP session with a page:

```text
ws://{host}/inspector/debug?device={device_id}&page={page_id}
```

Both `device` and `page` query parameters are required.

## 📐 Design

### Architecture

```text
┌─────────────────┐     ┌─────────────────────────┐     ┌────────────────┐
│    Debugger     │────▶│    Inspector Proxy      │◀────│     Device     │
│ (Chrome/VSCode) │     │      (Node.js)          │     │ (iOS/Android)  │
└─────────────────┘     └─────────────────────────┘     └────────────────┘
   WebSocket               HTTP + WebSocket               WebSocket
   /inspector/debug        /json, /json/list              /inspector/device
                           /json/version
```

### Device ↔ Proxy Protocol

All messages are JSON-encoded WebSocket text frames:

```typescript
interface Message {
  event: string;
  payload?: /* depends on event */;
}
```

#### Proxy → Device Messages

| Event          | Payload                                                       | Description                                   |
| -------------- | ------------------------------------------------------------- | --------------------------------------------- |
| `getPages`     | _(none)_                                                      | Request current page list. Sent periodically. |
| `connect`      | `{ pageId: string, sessionId: string }`                       | Prepare for debugger connection to page.      |
| `disconnect`   | `{ pageId: string, sessionId: string }`                       | Terminate debugger session for page.          |
| `wrappedEvent` | `{ pageId: string, sessionId: string, wrappedEvent: string }` | Forward CDP message (JSON string) to page.    |

#### Device → Proxy Messages

| Event          | Payload                                                        | Description                                           |
| -------------- | -------------------------------------------------------------- | ----------------------------------------------------- |
| `getPages`     | `Page[]`                                                       | Current list of inspectable pages.                    |
| `disconnect`   | `{ pageId: string, sessionId?: string }`                       | Notify that page disconnected or rejected connection. |
| `wrappedEvent` | `{ pageId: string, sessionId?: string, wrappedEvent: string }` | Forward CDP message (JSON string) from page.          |

#### Page Object

```typescript
interface Page {
  id: string; // Unique page identifier (typically numeric string)
  title: string; // Display title
  app: string; // App bundle identifier
  description?: string; // Additional description
  capabilities?: {
    nativePageReloads?: boolean; // Target keeps the socket open across reloads
    nativeSourceCodeFetching?: boolean; // Target supports Network.loadNetworkResource
    supportsMultipleDebuggers?: boolean; // Supports concurrent debugger sessions
  };
}
```

**Note**: The value of `supportsMultipleDebuggers` SHOULD be consistent across
all pages for a given device.

### Connection Lifecycle

**Device Registration:**

```text
Device                              Proxy
   │                                  │
   │──── WS Connect ─────────────────▶│
   │     /inspector/device?...        │
   │                                  │
   │◀──── getPages ───────────────────│  (periodically)
   │                                  │
   │───── getPages response ─────────▶│
   │      (page list)                 │
```

**Debugger Session:**

```text
Debugger            Proxy                        Device
   │                  │                            │
   │── WS Connect ───▶│                            │
   │   ?device&page   │── connect ────────────────▶│
   │                  │   {pageId, sessionId}      │
   │                  │                            │
   │── CDP Request ──▶│── wrappedEvent ───────────▶│
   │                  │   {pageId, sessionId,      │
   │                  │    wrappedEvent}           │
   │                  │                            │
   │                  │◀── wrappedEvent ───────────│
   │◀── CDP Response ─│   {pageId, sessionId,      │
   │                  │    wrappedEvent}           │
   │                  │                            │
   │── WS Close ─────▶│── disconnect ─────────────▶│
   │                  │   {pageId, sessionId}      │
```

**Connection Rejection:**

If a device cannot accept a `connect` (e.g., page doesn't exist), it should send
a `disconnect` back to the proxy for that `pageId`. Devices also send a
`disconnect` for each session when a page is removed.

For targets with `nativePageReloads`, the proxy closes the debugger connection
with `[PAGE_REMOVED]` when it receives a `disconnect` for its session (or for
its page, if `sessionId` is omitted).

### Connection Semantics

#### Multi-Debugger Support

Multiple debuggers can connect simultaneously to the same page when **both** the
proxy and device support session multiplexing:

1. **Session IDs**: The proxy assigns a unique, non-empty `sessionId` to each
   debugger connection. All messages include this `sessionId` for routing. This
   SHOULD be a UUID or other suitably unique and ephemeral identifier.

2. **Capability Detection**: Devices report `supportsMultipleDebuggers: true` in
   their page capabilities to indicate session support.

3. **Backwards Compatibility**: Legacy devices ignore `sessionId` fields in
   incoming messages and don't include them in responses.

#### Connection Rules

1. **Session-Capable Device**: Multiple debuggers can connect to the same page
   simultaneously. Each connection has an independent session.

2. **Legacy Device (no `supportsMultipleDebuggers`)**: New debugger connections
   to an already-connected page disconnect the existing debugger. The proxy MUST
   NOT allow multiple debuggers to connect to the same page.

3. **Device Reconnection**: If a device reconnects with the same `device` ID
   while debugger connections to the same logical device are open in the proxy,
   the proxy may attempt to preserve active debugger sessions by forwarding them
   to the new device.

### WebSocket Close Reasons

The proxy uses specific close reasons that DevTools frontends may recognize:

| Reason                  | Context                                 |
| ----------------------- | --------------------------------------- |
| `[PAGE_NOT_FOUND]`      | Debugger connected to non-existent page |
| `[PAGE_REMOVED]`        | Device ended or rejected the session    |
| `[CONNECTION_LOST]`     | Device disconnected                     |
| `[RECREATING_DEVICE]`   | Device is reconnecting                  |
| `[NEW_DEBUGGER_OPENED]` | Another debugger took over this page    |
| `[UNREGISTERED_DEVICE]` | Device ID not found                     |
| `[INCORRECT_URL]`       | Missing device/page query parameters    |

### PageDescription (HTTP Response)

The `/json` endpoint returns enriched page descriptions based on those reported
by the device.

```typescript
interface PageDescription {
  // Used for target selection
  id: string; // "{deviceId}-{pageId}"

  // Used for display
  title: string;
  description: string;
  deviceName: string;

  // Used for target matching
  appId: string;

  // Used for debugger connection
  webSocketDebuggerUrl: string;

  // React Native-specific metadata
  reactNative: {
    logicalDeviceId: string; // Used for target matching
    capabilities: {
      nativePageReloads?: boolean; // Used for target filtering
    };
  };
}
```

## 🔗 Relationship with other systems

### Part of this

- **Device.js** - Per-device connection handler in the proxy
- **InspectorProxy.js** - Main proxy HTTP/WebSocket server

### Used by this

- **Chrome DevTools Protocol (CDP)** - The wrapped messages are CDP messages
  exchanged between DevTools frontends and JavaScript runtimes.
- **WebSocket** - Transport layer for device and debugger connections.

### Uses this

- **InspectorPackagerConnection (C++)** - Shared device-side protocol
  implementation in `ReactCommon/jsinspector-modern/`.
- **Platform layers** - iOS (`RCTInspectorDevServerHelper.mm`), Android
  (`DevServerHelper.kt`), and ReactCxxPlatform (`Inspector.cpp`) provide
  WebSocket I/O and threading.
- **openDebuggerMiddleware** - Uses `/json` to discover targets for the
  `/open-debugger` endpoint.
- **OpenDebuggerKeyboardHandler** - Uses `/json` to display target selection in
  the CLI.

---

## Legacy Features

The following features exist for backward compatibility with older React Native
targets that lack modern capabilities. New implementations should set
appropriate capability flags and may ignore this section.

### Synthetic Reloadable Page (Page ID `-1`)

For targets without the `nativePageReloads` capability, the proxy exposes a
synthetic page with ID `-1` titled "React Native Experimental (Improved Chrome
Reloads)". Debuggers connecting to this page are automatically redirected to the
most recent React Native page, surviving page reloads.

When a new React Native page appears while a debugger is connected to `-1`:

1. Proxy sends `disconnect` for the old page, `connect` for the new page
2. Proxy sends `Runtime.enable` and `Debugger.enable` CDP commands to the new
   page
3. When `Runtime.executionContextCreated` is received, proxy sends
   `Runtime.executionContextsCleared` to debugger, then `Debugger.resume` to
   device

### URL Rewriting

For targets without the `nativeSourceCodeFetching` capability, the proxy
rewrites URLs in CDP messages:

- **Debugger.scriptParsed** (device → debugger): Device-relative URLs are
  rewritten to debugger-relative URLs
- **Debugger.setBreakpointByUrl** (debugger → device): URLs are rewritten back
  to device-relative form
- **Debugger.getScriptSource**: Intercepted and handled by proxy via HTTP fetch
- **Network.loadNetworkResource**: Returns CDP error (code -32601) to force
  frontend fallback

Additionally, if a script URL matches `^[0-9a-z]+$` (alphanumeric ID), the proxy
prepends `file://` to ensure Chrome downloads source maps.

### Legacy Reload Notification

For targets without `nativePageReloads`, when a `disconnect` event is received
for a page, the proxy sends `{method: 'reload'}` to the connected debugger to
signal a page reload.

---

### Overview (`packages/react-native/React/DevSupport/__docs__/README.md`)

# Bundler Connection (Apple platforms)

[🏠 Home](../../../../../__docs__/README.md)

When a React Native app on an Apple platform (iOS, tvOS, etc.) is launched, the
native side calculates where to load the JavaScript from: the bundler (Metro)
running on the development machine, or a bundle embedded in the app. In a Debug
build, the app then stays connected to Metro, which enables reloading, Fast
Refresh, opening the Dev Menu from the terminal, and debugging with React Native
DevTools. In a Release build, the app runs the embedded bundle and does not
contact Metro (see [Build modes](./BuildModes.md)).

The app talks to Metro through two kinds of channels:

1. **HTTP**: one-shot requests to check whether Metro is running, download the
   bundle, and open React Native DevTools.
2. **WebSocket**: long-lived connections for Metro's commands (`/message`), Fast
   Refresh (`/hot`), and React Native DevTools (`/inspector/device`).

The details are split into the documents below. File paths are relative to
`packages/react-native/`; paths in examples are relative to the repository root.

| Document                                                               | Covers                                                                                                                                                                             |
| ---------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [Bundle URL](./BundleURL.md)                                           | How the app chooses where its JavaScript comes from, how to point it at a specific Metro, how Metro is found, what the bundle request asks for, and where the current URL is kept. |
| [Downloading and Running the Bundle](./BundleLoading.md)               | Fetching the bundle from Metro or reading it from the app, the loading banner, and load errors.                                                                                    |
| [Reloading and Switching Metro](./Reloading.md)                        | What a reload restarts, what triggers it, how the URL changes between loads, and Configure Bundler.                                                                                |
| [Commands from Metro (`/message`)](./PackagerConnection.md)            | The WebSocket for reload and Dev Menu commands and its message protocol.                                                                                                           |
| [Fast Refresh (`/hot`)](./FastRefresh.md)                              | How Fast Refresh connects to Metro.                                                                                                                                                |
| [React Native DevTools (`/inspector/device`)](./DevToolsConnection.md) | How the app registers with Metro for debugging.                                                                                                                                    |
| [JavaScript Dev Tools That Use Metro](./JavaScriptDevTools.md)         | LogBox symbolication, open in editor, links, split bundles and images.                                                                                                             |
| [Build Modes](./BuildModes.md)                                         | What each build configuration and compile flag enables.                                                                                                                            |

## 🚀 Usage

The app chooses where its JavaScript comes from by implementing `bundleURL` in
the delegate of its `RCTReactNativeFactory`. Typically, Debug builds ask
`RCTBundleURLProvider` for a Metro URL and Release builds use the embedded
`main.jsbundle`. [Bundle URL](./BundleURL.md) describes this, the ways to point
the app at a specific Metro, and how the URL can change.

## 📐 Design

All bundle loading goes through `RCTHost`
(`ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.mm`). When the app
starts, or reloads, React Native:

1. Connects to Metro for terminal commands and React Native DevTools.
2. Downloads the bundle while showing "Loading from Metro…" with progress.
3. Runs the bundle, which renders the app, and connects Fast Refresh.

```text
App delegate ── bundleURL (provider block) ──► RCTHost ── RCTBundleManager.bundleURL
                                                  │
                                            RCTInstance._loadJSBundle
                                                  │
         1. moduleForName:"DevSettings" ◄─────────┤
            RCTDevSettings.initialize             │
              ├─ RCTPackagerConnection ──────── WS /message ───────────► Metro  (receives reload and devMenu commands)
              └─ RCTInspectorDevServerHelper ── WS /inspector/device ──► Metro  (connects React Native DevTools)
                                                  │
         2. RCTHost.loadBundleAtURL ◄─────────────┤
            └─ RCTJavaScriptLoader ──────────── GET /<root>.bundle ────► Metro  (downloads the bundle)
                                                  │
         3. _loadJSBundle onComplete ◄────────────┘
            ├─ _loadScriptFromSource                                            (runs the bundle)
            │  └─ ReactInstance::loadScript                                     (runs the app's JavaScript)
            └─ setupHMRClientWithBundleURL
               └─ HMRClient.setup ───────────── WS /hot ───────────────► Metro  (applies hot updates)
```

Each step is described in its own document:
[Downloading and Running the Bundle](./BundleLoading.md),
[Commands from Metro](./PackagerConnection.md),
[React Native DevTools](./DevToolsConnection.md) and
[Fast Refresh](./FastRefresh.md).

### Endpoints

| Endpoint                   | Client                                                                         | Purpose                                                                                                                                                             |
| -------------------------- | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GET /status`              | `RCTBundleURLProvider`                                                         | Is Metro running                                                                                                                                                    |
| `GET /<root>.bundle?…`     | `RCTJavaScriptLoader`                                                          | Bundle download                                                                                                                                                     |
| `GET /<root>/<name>.<ext>` | `RCTBundleURLProvider` resource URLs                                           | Native resources                                                                                                                                                    |
| WS `/message?role=ios`     | `RCTPackagerConnection`                                                        | Reload, Dev Menu, custom                                                                                                                                            |
| WS `/hot`                  | `HMRClient.js`                                                                 | Fast Refresh                                                                                                                                                        |
| WS `/inspector/device?…`   | `RCTCxxInspectorPackagerConnection`                                            | React Native DevTools                                                                                                                                               |
| `POST /open-debugger`      | `RCTInspectorDevServerHelper`                                                  | Open React Native DevTools                                                                                                                                          |
| `POST /symbolicate`        | `symbolicateStackTrace.js` (used by LogBox)                                    | Sends a JavaScript stack trace (`{stack, extraData}`); Metro maps each frame from the bundle back to the original source file, line and column using the source map |
| `POST /open-stack-frame`   | `openFileInEditor.js` (used when a LogBox stack frame or code frame is tapped) | Sends `{file, lineNumber}`; Metro opens that file at that line in the editor on the development machine                                                             |
| `POST /open-url`           | `openURLInBrowser.js`                                                          | Sends `{url}`; Metro opens the URL in the browser on the development machine                                                                                        |

## 🔗 Relationship with other systems

### Part of

- React Native developer tooling on Apple platforms.

### Part of this

- `React/Base/RCTBundleURLProvider`: finds Metro, builds bundle and resource
  URLs, stores the settings.
- `React/Base/RCTBundleManager`: `RCTBundleConfiguration` and the current bundle
  URL shared with native modules.
- `React/Base/RCTJavaScriptLoader`, `RCTMultipartDataTask`,
  `RCTMultipartStreamReader`: download and file loading.
- `React/Base/RCTReloadCommand`: reload listeners and the reload notification.
- `React/Base/RCTDevSupportHttpHeaders`: extra headers for Metro requests.
- `React/DevSupport/RCTPackagerConnection`, `RCTPackagerClient`,
  `Libraries/WebSocket/RCTReconnectingWebSocket`: the `/message` connection.
- `React/DevSupport/RCTInspectorDevServerHelper`: the DevTools connection and
  `/open-debugger`.
- `React/CoreModules/RCTDevSettings`: owns the `/message` connection, starts
  Fast Refresh and the DevTools connection.
- `React/CoreModules/RCTDevMenu`: Reload and Configure Bundler.
- `React/CoreModules/RCTDevLoadingView`: the loading banner.
- `Libraries/Utilities/HMRClient.js`, `Libraries/Core/Devtools/getDevServer.js`:
  the JavaScript side.
- `scripts/react-native-xcode.sh`: the embedded bundle and `ip.txt`.

### Used by this

- Metro and `@react-native/dev-middleware`: serve the endpoints above. See the
  [Inspector proxy protocol](../../../../dev-middleware/src/inspector-proxy/__docs__/README.md).
- `jsinspector-modern`: the DevTools socket protocol and flags (`InspectorFlags`
  adds the DevTools query parameters).
- SocketRocket: WebSocket client.
- `metro-runtime` `HMRClient`: the `/hot` protocol.

### Uses this

- `RCTHost` / `RCTInstance`: get the bundle URL, load the bundle, reload.
- `RCTReactNativeFactory` / `RCTRootViewFactory`: pass the app's bundle URL
  provider and `RCTBundleConfiguration` to `RCTHost`.
- JavaScript dev tools: LogBox symbolication, open in editor, image loading.

---

### Overview (`packages/react-native/ReactApple/Libraries/RCTFoundation/README.md`)

# RCTFoundation

RCTFoundation is a collection of lightweight utility libraries.

Rules for RCTFoundation libraries:
- They must only depend on other RCTFoundation libraries.
- Headers cannot contain C++.
- They have modular set to true in BUCK.
- They have complete_nullability set to true.
- They have enabled Clang compiler warnings.
- They have documentation.
- They have unit tests.

---

### Overview (`packages/react-native/ReactCommon/react/runtime/README.md`)

# Bridgeless Mode for iOS

This library is not ready for integration for production nor local experimentation. Expect breaking changes regularly if you use any of these APIs. Use at your own risk!

---

### Overview (`packages/react-native/scripts/featureflags/__docs__/README.md`)

# Feature Flags

[🏠 Home](../../../../../__docs__/README.md)

This directory contains the flag definitions and codegen for the internal React
Native feature flags system.

## 🔗 Relationship with other systems

### Part of

- [Feature Flags system](../../../src/private/featureflags/__docs__/README.md)

---

### Overview (`packages/react-native/scripts/ios-prebuild/__docs__/README.md`)

# iOS Prebuild Scripts

This directory contains scripts for prebuilding React Native itself into
XCFrameworks for iOS and related platforms.

## Overview

These scripts automate the process of building React Native as a Swift Package
and packaging it into XCFrameworks that can be distributed and consumed by iOS
applications. The build process creates optimized frameworks for multiple
architectures and platforms.

## Purpose

The prebuild scripts are used to:

- Build React Native itself (not its dependencies) as XCFrameworks
- Create distributable binaries for iOS, iOS Simulator, Catalyst.
- Support both Debug and Release build configurations
- Generate Debug Symbol (dSYM) files for debugging

## Usage

Run the prebuild script from the command line:

```bash
cd packages/react-native
node scripts/ios-prebuild
```

If no options are passed, the script executes all the steps in this order:

- setup the codebase for all platforms and flavors
- build for all platforms and flavors
- compose xcframeworks
- sign (if an identity is passed)

### Options

| Option        | Alias | Type    | Default                                    | Description                                                         |
| ------------- | ----- | ------- | ------------------------------------------ | ------------------------------------------------------------------- |
| `--setup`     | `-s`  | boolean | -                                          | Download and setup dependencies                                     |
| `--build`     | `-b`  | boolean | -                                          | Build dependencies/platforms                                        |
| `--compose`   | `-c`  | boolean | -                                          | Compose XCFramework from built dependencies                         |
| `--platforms` | `-p`  | array   | `['ios', 'ios-simulator', 'mac-catalyst']` | Specify one or more platforms to build for                          |
| `--flavor`    | `-f`  | string  | `Debug`                                    | Specify the flavor to build: `Debug` or `Release`                   |
| `--identity`  | `-i`  | string  | -                                          | Specify the code signing identity to use for signing the frameworks |
| `--help`      | -     | boolean | -                                          | Show help information                                               |

### Output Structure

The build produces:

- XCFrameworks in the specified output directory
- Debug symbols (dSYM files) for debugging
- Build products organized by platform and configuration

## Architecture

The build system consists of several components:

### `cli.js`

The main entry point that orchestrates the build process. It:

- Parses command-line arguments
- Validates build parameters
- Coordinates the build, archiving, and XCFramework creation steps

### `build.js`

Handles the Swift Package build process. It:

- Executes `xcodebuild` commands with appropriate flags
- Builds for specific platforms and build types (Debug/Release)
- Locates and validates the generated framework artifacts
- Uses build settings like `BUILD_LIBRARY_FOR_DISTRIBUTION=YES` for binary
  compatibility

### `types.js`

Defines TypeScript/Flow type definitions for:

- `BuildFlavor`: Debug or Release configurations
- `Destination`: Target platforms (iOS, iOS Simulator, Catalyst, Vision,
  visionOS)
- `ArchiveOptions`: Configuration options for the build process

### `utils.js`

Provides utility functions including:

- Logging functionality with prefixed output
- Common helper functions used across scripts

## Build Flags

The build process uses specific `xcodebuild` flags:

- `BUILD_LIBRARY_FOR_DISTRIBUTION=YES`: Enables module stability
- `SKIP_INSTALL=NO`: Ensures frameworks are properly installed
- `DEBUG_INFORMATION_FORMAT="dwarf-with-dsym"`: Generates debug symbols
- `OTHER_SWIFT_FLAGS="-no-verify-emitted-module-interface"`: Skips interface
  verification (useful for React Native modules due to the header structure not
  beeing modular)

## Notes

- These scripts build React Native itself, not third-party dependencies
- The build process requires significant disk space for derived data
- Build times vary depending on the target platform and configuration
- XCFrameworks support multiple architectures in a single bundle

## Header Resolution (headers-spec layout)

The prebuilt XCFrameworks ship a **headers-spec layout** so that header imports
resolve through plain header/framework search paths — there is **no clang VFS
overlay**. The layout contract is defined and validated in code:

- `headers-spec.js`: the executable layout contract (rules R1–R8) — which
  namespaces are hoisted, which carry module maps, and how collisions are
  rejected.
- `headers-inventory.js`: scans the source tree to build the live header
  inventory that feeds the spec.
- `headers-compose.js`: emits the layout. `emitReactFrameworkHeaders()` writes
  the `React/` and bare-aliased headers into every slice's
  `React.framework/Headers`, and `buildReactNativeHeadersXcframework()`
  assembles the headers-only `ReactNativeHeaders.xcframework` carrying every
  other React Native namespace (incl. `react/`). The third-party dependency
  namespaces (`folly`, `glog`, `boost`, `fmt`, `double-conversion`,
  `fast_float`, `SocketRocket`) ship in the separate headers-only
  `ReactNativeDependenciesHeaders.xcframework` sidecar, built by the
  dependencies prebuild. The Hermes public headers (`<hermes/...>`) are folded
  into the published `ReactNativeHeaders` when the hermes-ios headers are
  staged; without them the compose ships no `hermes/`, unless `--require-hermes`
  is set, which makes it fail closed.

### Artifacts

The prebuild (`xcframework.js`) always produces:

- `React.xcframework` — the compiled React core. Each slice's `React.framework`
  carries the headers-spec layout (every `<React/...>` header + the framework
  module map). CocoaPods consumes that layout directly, through
  `FRAMEWORK_SEARCH_PATHS`. SwiftPM consumes the same headers indirectly,
  because the XCFramework is not a member of the Swift package graph. The
  consumer side stages a copy of `React.framework/Headers` into
  `ReactHeadersTarget/include/React`, rewrites `framework module React` to a
  plain `module React`, and vends it as the `ReactHeaders` target (see
  [spm-header-paths-contract.md](../../spm/__docs__/spm-header-paths-contract.md)).
- `ReactNativeHeaders.xcframework` — headers-only; carries every other React
  Native namespace. Consumed by SwiftPM as a `binaryTarget` and by CocoaPods via
  the `React-Core-prebuilt` pod (headers flattened onto the header search path).

### CocoaPods consumption

The `React-Core-prebuilt` pod vends `React.xcframework` (so `<React/...>` and
`@import React;` resolve through the framework module via
`FRAMEWORK_SEARCH_PATHS`) and flattens `ReactNativeHeaders.xcframework`'s
headers into a top-level `Headers/` exposed on the pod header search path (so
`<react/...>`, `<yoga/...>`, `<folly/...>` resolve). `rncore.rb` adds the
`HEADER_SEARCH_PATHS` entry to `React-Core-prebuilt/Headers` for podspec,
aggregate (main app), and third-party pod targets. No `-ivfsoverlay` flags are
added.

## Integrating in your project with Cocoapods

For consuming, debugging or troubleshooting when using Cocoapods scripts, you
can use the following environment variables:

- `RCT_USE_PREBUILT_RNCORE`: If set to 1, it will use the release tarball from
  Maven instead of building from source.
- `RCT_TESTONLY_RNCORE_TARBALL_PATH`: **TEST ONLY** If set, it will use a local
  tarball of RNCore if it exists.
- `RCT_TESTONLY_RNCORE_VERSION`: **TEST ONLY** If set, it will override the
  version of RNCore to be used.
- `RCT_SYMBOLICATE_PREBUILT_FRAMEWORKS`: If set to 1, it will download the dSYMs
  for the prebuilt RNCore frameworks and install these in the framework folders

---

### Overview (`packages/react-native/scripts/spm/__docs__/README.md`)

# SwiftPM (Apple platforms) — Preview

[🏠 Home](../../../../../__docs__/README.md)

> **Preview.** SwiftPM support is an early preview. The commands, flags,
> generated layout, and distribution model may change in future releases. It is
> not yet recommended for production. CocoaPods remains the supported default.

The scripts in `scripts/spm/` let a React Native iOS app consume React Native
through **Swift Package Manager** instead of CocoaPods, using prebuilt
XCFrameworks. Support is opt-in and additive: `npx react-native spm` injects
package references into the app's existing `.xcodeproj` in place, and `deinit`
reverses exactly what it injected.

[RFC0994](https://github.com/react-native-community/discussions-and-proposals/blob/main/proposals/0994-swift-package-manager-support-for-react-native-ios-projects.md)
holds the motivation, the staged migration plan, and the open questions. The
documents here describe how the implementation works.

## 🚀 Usage

```bash
cd ios
npx react-native spm      # add on first run, update thereafter
```

**If an autolinked dependency ships no `Package.swift`, setup stops with
`error: Package.swift is missing for library "<name>"` and exit code 2.** Run
`npx react-native spm scaffold`, persist the manifest with `patch-package`, and
re-run setup. See
[Community packages without a Package.swift](./spm-scripts.md#community-packages-without-a-packageswift).

See **[spm-scripts.md](./spm-scripts.md)** for the CLI actions and flags,
CocoaPods migration, brownfield apps, what to commit, fresh clones and CI, and
troubleshooting.

## 📐 Design

Three documents cover the design, each owning one area:

| Document                                                       | Covers                                                                                                                                                                                                                          |
| -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [spm-scripts.md](./spm-scripts.md)                             | The tool itself: CLI surface, the six-step pipeline, [every file it creates or modifies](./spm-scripts.md#files-the-tool-touches), the two auto-sync hooks, and how Debug/Release flavor selection works.                       |
| [spm-header-paths-contract.md](./spm-header-paths-contract.md) | How headers and package references resolve. The contract is **zero-`-I`**: no generated manifest carries a search path into React Native's own headers. Also covers remote mode.                                                |
| [spm-autolinking-plugins.md](./spm-autolinking-plugins.md)     | The extension seam for frameworks with their own module system (Expo is the first consumer): discovery, the full context/return contract including `flavoredFrameworks`, `watchPaths` and `scriptPhases`, and failure behavior. |

Two ideas explain most of the architecture:

- **Headers go through SwiftPM; runtime binaries do not.** A `binaryTarget`
  cannot vary by build configuration, but React Native ships flavored binaries.
  So the package graph vends headers only, and generated Xcode build settings
  link and embed the flavored frameworks. See
  [Debug/Release flavor is automatic](./spm-scripts.md#debugrelease-flavor-is-automatic).
- **Generated state is regenerable, and the injection is reversible.**
  Everything under `build/` is gitignored and rebuilt from the app's
  `package.json`. Every edit to the `.xcodeproj` is recorded in a
  `.spm-injected.json` marker, so `deinit` can undo exactly that.

## 🔗 Relationship with other systems

### Part of

- iOS build system — the alternative to the CocoaPods integration in
  [`scripts/cocoapods/`](../../cocoapods).

### Used by this

- **Prebuilt XCFrameworks** from [`scripts/ios-prebuild/`](../../ios-prebuild) —
  produces the `React`, `ReactNativeDependencies`, `hermes-engine`, and
  headers-only artifacts that these scripts download, stage, and link.
- **Codegen** (`generate-codegen-artifacts.js`) — its output is installed as a
  local `React-GeneratedCode` package rather than a Pod.
- **`@react-native-community/cli config`** — supplies the autolinking metadata
  (`autolinking.json`) that the SwiftPM autolinker turns into a `Package.swift`.
  Override it with the `RCT_SPM_AUTOLINKING_CONFIG_COMMAND` environment
  variable, or with `--config-command` when you run `setup-apple-spm.js`
  directly.

### Uses this

- Apps opting into SwiftPM, via the `spm` React Native CLI command.
- Frameworks layering their own module system on top of React Native, via
  [autolinking plugins](./spm-autolinking-plugins.md).

---

### Overview (`packages/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation/README.md`)

RCTDeprecation contains C macros to identify deprecated APIs at build-time.

---

### Overview (`packages/react-native/ReactCommon/react/featureflags/__docs__/README.md`)

# Feature Flags

[🏠 Home](../../../../../../__docs__/README.md)

This directory contains the shared C++ implementation of the internal React
Native feature flags system.

## 🔗 Relationship with other systems

### Part of

- [Feature Flags system](../../../../src/private/featureflags/__docs__/README.md)

---

### Overview (`packages/react-native/ReactCommon/react/nativemodule/devtoolsruntimesettings/README.md`)

# Options for DevTools Settings

| Module | Survives native restarts | Survives JavaScript VM restarts |
| --- | --- | --- |
| DevToolsRuntimeSettings | No | Yes
| DevToolsSettings | Yes | Yes

---

### Overview (`packages/react-native/ReactCommon/react/timing/__docs__/README.md`)

# React Native Timing

[🏠 Home](../../../../../../__docs__/README.md)

This directory contains the shared C++ implementation of high-resolution timing
primitives for React Native. These primitives provide precise time measurement
capabilities that align with Web standards while being optimized for the React
Native environment.

## 🚀 Usage

The timing primitives in this module are primarily used by internal React Native
systems that require precise time measurements. The monotonic clock is used for
these primitives: they should be used for measuring time intervals. These
primitives should not be used for wall times. They are not expected to be used
directly by application developers but serve as foundational components for
various React Native features.

Key primitives include:

- `HighResTimeStamp`: A class representing a specific point in time with high
  precision.
- `HighResDuration`: A class representing a duration of time with high
  precision.

These primitives support various operations:

```cpp
// Getting the current high-resolution timestamp
auto start = HighResTimeStamp::now();

// Creating durations
auto duration = HighResDuration::fromNanoseconds(100);
auto durationMs = HighResDuration::fromMilliseconds(100);

// Arithmetic operations
auto later = start + duration;
auto elapsed = later - start;

// Converting to absolute time units of highest precision
auto end = HighResTimeStamp::now();
int64_t nanoseconds = (end - start).toNanoseconds();

// Converting to DOMHighResTimeStamp (for JavaScript interoperability)
double jsTimeValue = now.toDOMHighResTimeStamp();
```

## 📐 Design

The timing primitives are designed to align with Web standards while leveraging
C++'s type system and the performance characteristics of native code. The
implementation uses `std::chrono` internally but provides a more specialized
interface tailored to React Native's needs.

### Platform-Specific Clock Sources

On different platforms, `HighResTimeStamp` uses different underlying clock
sources to ensure compatibility with platform-specific timing APIs:

- **iOS/macOS**: Uses `mach_absolute_time()`, which measures time since device
  boot and **excludes sleep time**. This ensures compatibility with iOS system
  APIs (like `UITouch.timestamp` and `NSProcessInfo.processInfo.systemUptime`)
  and native performance logging systems that use the same clock source.

- **Other platforms**: Uses `std::chrono::steady_clock`, which provides a
  monotonic clock that may include or exclude sleep time depending on the
  platform.

This design ensures that timestamps recorded in JavaScript and passed to native
systems will have correct timing on all platforms.

### HighResTimeStamp

This class represents a specific point in time with high precision. It
encapsulates a `std::chrono::steady_clock::time_point` and provides methods to:

- Convert to `DOMHighResTimeStamp` for JavaScript interoperability.
- Perform arithmetic operations with durations.
- Compare with other timestamps.

### HighResDuration

This class represents a duration of time with high precision. It encapsulates a
`std::chrono::duration` and provides methods to:

- Convert to `DOMHighResTimeStamp` for JavaScript interoperability.
- Convert to an absolute number of nanoseconds.
- Perform arithmetic operations.
- Compare with other durations.

## 🔗 Relationship with other systems

### Used by

- [Event Loop](../../renderer/runtimescheduler/__docs__/README.md): Uses timing
  primitives for measuring task execution times and scheduling.
- Web Performance API: Timing primitives are used to implement performance
  measurement APIs like `PerformanceObserver` entries (e.g., `longtask` and
  `event`).
- React Native DevTools: The timing primitives integrate with the React Native
  DevTools tracing infrastructure to report the timing of tasks and events.

### Related to

- Web timing APIs: The timing primitives are designed to be compatible with Web
  timing concepts, making it easier to implement Web-compatible APIs in React
  Native.

---

### Overview (`packages/react-native/src/private/featureflags/__docs__/README.md`)

# Feature Flags

[🏠 Home](../../../../../../__docs__/README.md)

Feature flags are values that determine the behavior of specific parts of React
Native. This directory contains the configuration for those values, and scripts
to generate files for different languages to access and customize them.

There are 2 types of feature flags:

- Common: can be accessed from any language and they provide consistent values
  everywhere.
- JS-only: they can only be accessed and customized from JavaScript.

## 🚀 Usage

### Defining feature flags

The source of truth for the definition of the flags is the file
`ReactNativeFeatureFlags.config.js` in this directory.

Example contents:

```javascript
module.exports = {
  common: {
    enableNativeBehavior: {
      description: 'Enable some behavior both in native and in JS.',
      defaultValue: false,
    },
  },
  jsOnly: {
    enableJSBehavior: {
      description: 'Enables some behavior in the JS layer.',
      defaultValue: false,
    },
  },
};
```

**After any change to these definitions**, the code that provides access to them
must be regenerated running this from the `react-native` repository:

```shell
yarn featureflags --update
```

### Accessing feature flags

You can access the common feature flags from anywhere in your application using
the `ReactNativeFeatureFlags` interface (available in C++/Objective-C++,
Kotlin/Java and JavaScript). JS-only feature flags can only be accessed from
JavaScript.

**Accessing feature flags should be considered fast for all use cases**. Feature
flags are cached at every layer, which prevents having to go through JNI when
accessing the values from Kotlin and through JSI when accessing the values from
JavaScript.

#### C++ / Objective-C

```c++
#include <react/featureflags/ReactNativeFeatureFlags.h>

if (ReactNativeFeatureFlags::enableNativeBehavior()) {
  // do something
}
```

#### Kotlin

```kotlin
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags

fun someMethod() {
  if (ReactNativeFeatureFlags.enableNativeBehavior()) {
    // do something
  }
}
```

#### JavaScript

```javascript
import {ReactNativeFeatureFlags} from 'react-native/react-private-interface';

if (ReactNativeFeatureFlags.enableNativeBehavior()) {
  // Native flag
}

if (ReactNativeFeatureFlags.enableJSBehavior()) {
  // JS-only flag
}
```

### Setting feature flag overrides

Feature flags provide the default values defined in the configuration unless
overrides are applied at the application level. Overrides for common feature
flags can only be defined in native, while overrides for JS-ony flags can only
be defined in JavaScript.

Overrides must be applied before any of the available feature flags has been
accessed. This prevents having inconsistent behavior during the lifecycle of the
application.

#### C++/Objective-C

```c++
#include <react/featureflags/ReactNativeFeatureFlags.h>
#include <react/featureflags/ReactNativeFeatureFlagsDefaults.h>

class CustomReactNativeFeatureFlags : public ReactNativeFeatureFlagsDefaults {
 public:
  CustomReactNativeFeatureFlags();

  bool enableNativeBehavior() override {
    return true;
  }
}

ReactNativeFeatureFlags::override(std::make_unique<CustomReactNativeFeatureFlags>());
```

#### Kotlin

```kotlin
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlagsDefaults

fun overrideFeatureFlags() {
  ReactNativeFeatureFlags.override(object : ReactNativeFeatureFlagsDefaults() {
    override fun useMicrotasks(): Boolean = true
  })
}
```

#### JavaScript

```javascript
import {ReactNativeFeatureFlags} from 'react-native/react-private-interface';

ReactNativeFeatureFlags.override({
  enableJSBehavior: () => true,
});
```

### Reviewing feature flags

You can find the list of feature flags with their configuration in
[`ReactNativeFeatureFlags.config.js`](../../../../scripts/featureflags/ReactNativeFeatureFlags.config.js),
but you can also use the CLI to list them:

```shell
yarn featureflags --print
```

Which would print something like:

```
/* Detailed source-code truncated for AI context efficiency. */
```

If you need to consume this as structured data, you can print it as JSON using:

```shell
yarn featureflags --print --json
```

## 📐 Design

The architecture of this feature flags system can be described as follows:

- A shared C++ core, where we provide access to the flags and allow
  customizations.
- A Kotlin/Java interface that allows accessing and customizing the values in
  the C++ core (via JNI).
- A JavaScript interface that allows accessing the common values (via a native
  module) and accessing and customizing the JS-only values.



Most of the code for this system is automatically generated from
[`ReactNativeFeatureFlags.config.js`](../../../../scripts/featureflags/ReactNativeFeatureFlags.config.js).
The entrypoint for the codegen can be found
[here](../../../../scripts/featureflags/index.js).

The codegen uses a simple templating system based on JavaScript template strings
to generate the files (see files ending with `-template.js` in the
[`templates`](../../../../scripts/featureflags/templates/) directory),

## 🔗 Relationship with other systems

### Part of this

- [C++ TurboModule](../../../../ReactCommon/react/nativemodule/featureflags/__docs__/README.md)
- [C++ implementation](../../../../ReactCommon/react/featureflags/__docs__/README.md)
- [Android implementation](../../../../ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/__docs__/README.md)
- [Configuration and codegen](../../../../scripts/featureflags/__docs__/README.md)

### Used by this

- The only dependency is the C++ TurboModule infrastructure (including codegen),
  as the JavaScript API uses it to access the feature flag values from native.

### Uses this

This system is used extensively throughout the codebase and it evolves over time
as feature flags are added or cleaned up.

---

### Overview (`packages/react-native/src/private/specs_DEPRECATED/__docs__/README.md`)

# specs_DEPRECATED

This directory was created to move all the existing native module and native
component specs from the legacy `Libraries` directory. This was necessary
because we needed to change the directory for the codegen from `Libraries` to
`src/private`, and specs in `Libraries` needed to continue working.

Do **not** create new specs in this directory. Instead, create them colocated
with the rest of the logic in an appropriate directory in `src/private`.

Over time, as we move code from `Libraries` to `src/private`, we should be
moving the specs in this directory out until it is empty and we can remove it.

---

### Overview (`packages/rn-tester/js/examples/Experimental/PlatformTest/README.md`)

# RNTester PlatformTest

A barebones manual testing framework designed to work as a mechanism for recreating [Web Platform Tests](https://github.com/web-platform-tests/wpt) in React Native in order to verify their compliance with W3C specifications.

## Usage

Any new test case will start as a new React component which at the very least accepts a `harness` prop which will contain all of the framework's testing APIs. This component you write will be passed into the `component` prop of a `RNTesterPlatformTest` element whose other props are used for documenting your test. Rendering this `RNTesterPlatformTest` will look similar to something like this:

```js
function ExampleTestCase ({ harness }) { /* ... */ }

<RNTesterPlatformTest
  title="Example Test"
  description="Imagine there's a detailed description of this example test here"
  instructions={[
    "This is the example test's first step",
    "A second step",
    "A third step",
  ]}
  component={ExampleTestCase}
/>
```


As of writing this README there are 2 different types of tests that the `harness` prop provides:

### `test(testcase: (TestContext) => void, testName: string, options?: TestOptions)`

This is a method to create "regular" test reminiscent of other frameworks such as Jest. These are meant to be run imperatively, and while that means that they technically could work in a `useEffect` hook as a way to run the test "on mount" — it is instead recommended to try and keep these tests in callbacks instead. A good alternative to running the test on mount would be to instead put the test in a callback and render a "Start Test" button which executes the callback.

The first argument is the closure in which you will run your test and make assertions. The assertions are contained in the `TestContext` object which is provided in the test closure's first argument and contains the following assertions:

* `assert_true(a: boolean, description: string): void`
* `assert_equals(a: any, b: any, description: string): void`
* `assert_greater_than_equal(a: number, b: number, description: string): void`
* `assert_less_than_equal(a: number, b: number, description: string): void`

An optional third argument can be used for specifying additional options to the test — that object currently has the following properties (all of which are optional themselves):

* `skip: boolean`: In cases where we want the test to be registered but we don't want it to contribute to the pass/fail count.

Here's what a basic/contrived example which verifies the layout of a basic view:

```js
const EXPECTED_WIDTH = 100;
const EXPECTED_HEIGHT = 200;

function BasicLayoutTestCase({harness}) {
  const viewRef = useRef(null);

  const runTest = useCallback(() => {
    const view = viewRef.current;
    if (view != null) {
      view.measureInWindow(({width, height}) => {
        harness.test(({assert_equals}) => {
          assert_equals(
            width,
            EXPECTED_WIDTH,
            `view's computed width should be ${EXPECTED_WIDTH}`,
          );
          assert_equals(
            height,
            EXPECTED_HEIGHT,
            `view's computed width should be ${EXPECTED_HEIGHT}`,
          );
        }, "view's width and height are correct");
      });
    }
  }, [harness]);

  return (
    <>
      <View
        ref={viewRef}
        style={{width: EXPECTED_WIDTH, height: EXPECTED_HEIGHT}}
      />
      <Button title="Start Test" onPress={runTest} />
    </>
  );
}
```

### `useAsyncTest(description: string, timeoutMs?: number): AsyncPlatformTest`

This is a hook which can be used to represent tests that expect something to happen *some time* in the future. If the test isn't marked as "done" within a certain amount of time (10 seconds by default but can be optionally specified in the hook's second argument). This hook returns an object containing a `done` function which is used for marking the completion of the async test.

Here's what a basic example would look like for verifying that `pointermove` events are emitted:

```js
function BasicPointerMoveTestCase({harness}) {
  const testPointerMove = harness.useAsyncTest('pointermove event received');

  return (
    <View
      style={{width: 100, height: 100, backgroundColor: 'black'}}
      onPointerMove={() => testPointerMove.done()}
    />
  );
}
```

---

### Overview (`packages/react-native/ReactCommon/react/nativemodule/featureflags/__docs__/README.md`)

# Feature Flags

[🏠 Home](../../../../../../../__docs__/README.md)

This directory contains the native C++ TurboModule for the internal React Native
feature flags system.

## 🔗 Relationship with other systems

### Part of

- [Feature Flags system](../../../../../src/private/featureflags/__docs__/README.md)

---

### Overview (`packages/react-native/ReactCommon/react/nativemodule/intersectionobserver/__docs__/README.md`)

# IntersectionObserver

[🏠 Home](../../../../../../../__docs__/README.md)

This directory contains the native module used by the
[IntersectionObserver API](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver)
in React Native.

## 🔗 Relationship with other systems

### Part of

- [IntersectionObserver API](../../../../../src/private/webapis/intersectionobserver/__docs__/README.md)

---

### Overview (`packages/react-native/ReactCommon/react/nativemodule/microtasks/__docs__/README.md`)

# Microtasks

[🏠 Home](../../../../../../../__docs__/README.md)

This directory contains the native module used to implement `queueMicrotask` in
React Native, which schedules microtasks in the
[Event Loop](../../../renderer/runtimescheduler/__docs__/README.md).

## 🔗 Relationship with other systems

### Part of

- [Event Loop](../../../renderer/runtimescheduler/__docs__/README.md)

---

### Overview (`packages/react-native/ReactCommon/react/nativemodule/mutationobserver/__docs__/README.md`)

# MutationObserver

[🏠 Home](../../../../../../../__docs__/README.md)

This directory contains the native module used by the
[MutationObserver API](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver)
in React Native.

## 🔗 Relationship with other systems

### Part of

- [MutationObserver API](../../../../../src/private/webapis/mutationobserver/__docs__/README.md)

---

### Overview (`packages/react-native/ReactCommon/react/nativemodule/resizeobserver/__docs__/README.md`)

# ResizeObserver

[🏠 Home](../../../../../../../__docs__/README.md)

This directory contains the native module used by the
[ResizeObserver API](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver)
in React Native.

## 🔗 Relationship with other systems

### Part of

- [ResizeObserver API](../../../../../src/private/webapis/resizeobserver/__docs__/README.md)

---

### Overview (`packages/react-native/ReactCommon/react/nativemodule/samples/ReactCommon/README.md`)

Refer to packages/rn-tester/NativeCxxModuleExample/NativeCxxModuleExample.h for a concrete example.
See: https://reactnative.dev/docs/the-new-architecture/pure-cxx-modules

---

### Overview (`packages/react-native/ReactCommon/react/renderer/runtimescheduler/__docs__/README.md`)

# Event Loop

[🏠 Home](../../../../../../../__docs__/README.md)

The Event Loop is the formalization of the execution model for JavaScript in
React Native, and how that model synchronizes with rendering work in the host
platform.

Its main goals are:

- To make the behavior of the framework more predictable, to help developers
  build more reliable and performant apps.
- To increase the alignment with Web specifications, to simplify the adoption of
  Web APIs in React Native.
- (Secondary) Provide a solid foundation for general performance optimizations
  relying on better scheduling or sequencing.

The implementation of the event loop in React Native is aligned with
[its definition in the HTML specification](https://html.spec.whatwg.org/multipage/webappapis.html#event-loop-processing-model).
React Native only implements a subset of it, in order to support its existing
semantics and APIs.

> [!NOTE]
>
> The Event Loop in React Native was originally proposed in this
> [RFC](https://github.com/react-native-community/discussions-and-proposals/blob/main/proposals/0744-well-defined-event-loop.md),
> which contains additional context (e.g.: how this was introduced and what
> React Native had before).

## 🚀 Usage

The event loop is an implementation detail so it is not used directly, but
several APIs integrate deeply with it:

- State updates processed by React are scheduled to be flushed (rendered in the
  host platform) at the end of the current event loop tick.
- Promises, `queueMicrotask` and APIs like `MutationObserver` add microtasks to
  the microtask queue, processed as part of the current event loop tick.
- Timers and APIs like `requestIdleCallback` schedule tasks to be processed by
  the event loop. In the case of `requestIdleCallback`, the tasks are scheduled
  with specific priorities.
- `PerformanceObserver` entries like `longtask` and `event` provide timing
  information about different parts of the event loop.

One of the most important semantics of the event loop is the **atomicity of UI
updates in tasks**. All changes to the UI triggered from JavaScript in a task
(processing state updates in React, dispatching view commands, etc.) are always
flushed together to the host platform, so the UI is never updated with partial
work done within a task. For example:

1. We dispatch an event to JavaScript and execute one or more event handlers.
2. Those event handlers do one or more state updates in React. React schedules a
   microtask to process them.
3. In a microtask, React processes all those state updates together,
   re-rendering the necessary components and committing at the end.
4. As part of the commit, we might execute layout effects that might trigger
   more state updates. Those state updates are processed synchronously at the
   end of the commit.
5. At the end of the current microtask, we execute the rest of the microtasks.
6. When the microtask queue is empty, we flush all changes to the host platform.

In code, that could look like this:

```javascript
function App(props) {
  const [showContent, setShowContent] = useState(false);

  return (
    <>
      <Header
        onPressButton={event => {
          // A task executes all the event handlers.
          // The state update is processed in a microtask.
          setShowContent(true);
        }}
      />
      {showContent ? <Content /> : null}
    </>
  );
}

function Content(props) {
  const [width, setWidth] = useState(0);

  // Executed synchronously as part of the commit phase, in the microtask.
  useLayoutEffect(() => {
    // This state update is processed synchronously in the same microtask.
    // UI updates are still not flushed to the host platform until the end
    // of the event loop tick, so the user never saw this changed widths.
    setWidth(ref.getBoundingClientRect().width);
  }, []);

  return (
    <>
      <SomeView ref={ref} />
      <OtherComponent width={width} />
    </>
  );
}
```

## 📐 Design

The conceptual model is **aligned with
[the model on the Web](https://html.spec.whatwg.org/multipage/webappapis.html#event-loop-processing-model)**
(from which it borrows some concepts and steps), while **still benefiting from
the React Native threading model**.

The event loop continuously goes through these steps (in what we refer to as an
"event loop tick"):

1. Select the next task to execute among all tasks waiting for execution.
2. Execute the selected task.
3. Execute **all** scheduled microtasks.
4. Update the rendering.



One of the key benefits of this model is that each **event loop iteration
represents an atomic UI update**. This helps reason about whether work scheduled
within a specific task should be rendered together or not. If it is a step in
the same task, scheduled as a microtask or one of the specific sub-steps in
updating the rendering, then it will be atomic. Otherwise, if it was scheduled
as a separate task (e.g.: using timers, native callbacks, etc.) it would
constitute a separate UI update.

### Detailed steps

#### 1. Task selection

On the Web, task selection is an implementation detail left to browsers to
decide.

In React Native, we rely on `RuntimeScheduler` for task selection, which already
supports the execution of tasks with priorities. The criteria it uses is:

1. If there are expired tasks, select expired tasks in the order in which they
   expired.
2. Otherwise, select tasks by priority, in the order in which they were
   scheduled.

The Web specification defines the concept of task queues as a mechanism to
ensure that certain types of tasks execute in a specific order (e.g.: events).
React Native has the concept of event queue that serve the same purpose.

#### 2. Task execution

Task execution is calling the JavaScript function or C++ callback that is
associated to the task that was scheduled.

#### 3. Microtask execution

In this step we drain the microtask queue, executing all the microtasks in
order. A microtask can schedule additional microtasks, so incorrect product
logic could lead to an infinite loop. This is expected and it is the same
behavior as on the Web.

#### 4. Update the rendering

The last step applies work that browsers perform after task and microtask
execution, before the next task is selected (see
[HTML — update the rendering](https://html.spec.whatwg.org/multipage/webappapis.html#update-the-rendering)).

In [`RuntimeScheduler_Modern`](../RuntimeScheduler_Modern.h), this step
currently:

1. Dispatches pending Event Timing entries (when enabled).
2. Runs
   [Resize Observer](https://drafts.csswg.org/resize-observer/#broadcast-resize-notifications-h)
   observations via
   `RuntimeSchedulerResizeObserverDelegate::runResizeObservations()`. See the
   [ResizeObserver API](../../../../../src/private/webapis/resizeobserver/__docs__/README.md).
3. Updates [Intersection Observer](https://www.w3.org/TR/intersection-observer/)
   observations via `RuntimeSchedulerIntersectionObserverDelegate`.
4. Drains pending rendering updates (commits, view commands) so the host
   platform can apply mutations.

Observer steps run before the rendering-update queue is drained. Resize and
intersection observer integration is only implemented in
`RuntimeScheduler_Modern`; `RuntimeScheduler_Legacy` treats the corresponding
delegates as no-ops.

Additional browser work in this phase (e.g. animation frame callbacks) may be
added in the future.

### Synchronous execution, events and rendering

The formalization of the event loop also allows the efficient implementation of
synchronous events. Because the event loop defines the tick as an atomic unit of
work that leads to a full UI update, we can also use it as the unit of work to
be executed in the UI thread.



### Implementation

Most of the implementation of the event loop is done in the
[`RuntimeScheduler`](../RuntimeScheduler.h) class (specifically in
[`RuntimeScheduler_modern`](../RuntimeScheduler_Modern.h), which is the version
used in the new architecture).

That class implements both the task scheduler that handles priorities and the
processing of those tasks within the event loop.

## 🔗 Relationship with other systems

### Part of this

- The implementation of
  [`queueMicrotask`](../../../nativemodule/microtasks/__docs__/README.md) to
  schedule microtasks in the event loop.

### Used by this

- React timing primitives, to do time measurements of the execution of certain
  parts of the event loop to integrate with `PerformanceObserver`.
- Indirectly, it reports long tasks and event timing to `PerformanceObserver`.
- It also integrates with the React Native DevTools tracing infrastructure to
  report the timing of tasks.

### Uses this

- [MutationObserver](../../../../../src/private/webapis/mutationobserver/__docs__/README.md)
  uses the event loop to schedule mutation observer callbacks as microtasks.
- [ResizeObserver](../../../../../src/private/webapis/resizeobserver/__docs__/README.md)
  uses the event loop to run resize observations during the "update the
  rendering" step.
- [IntersectionObserver](../../../../../src/private/webapis/intersectionobserver/__docs__/README.md)
  uses the event loop to update intersection observations during the same step.
- `Scheduler` integrates with the event loop to register reporters (for
  `PerformanceObserver`) and schedules the specific work to be done as part of
  the rendering updates.

---

### Overview (`packages/react-native/src/private/webapis/intersectionobserver/__docs__/README.md`)

# IntersectionObserver

[🏠 Home](../../../../../../../__docs__/README.md)

This directory contains the React Native implementation of the
[IntersectionObserver API](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver).

## 🚀 Usage

`IntersectionObserver` is meant to be used from JavaScript, exposed as a global
class.

## 📐 Design

This is the high-level design of the IntersectionObserver API:



The global `IntersectionObserver` class is defined in JavaScript and it does its
setup using a native module.

In native, it uses mount hooks from `UIManager` to run intersection calculations
and update the state of the observers. When a mount operation is reported from
the host platform to `UIManager`, `UIManager` notifies the mount hook that
triggers a check on the observers that are observing intersections on that
surface. If the intersection triggers a state change, the notification is
dispatched to the JavaScript observers.

For the initial intersection notification (which is meant to report the state at
the time of observation), we run a step in the Event Loop as specified in the
Web spec (via `RuntimeSchedulerIntersectionObserverDelegate`), where we check if
there are pending transactions for the given surface. If there are, we just wait
for the transaction to be mounted and use the mount hook to report the initial
notification. If there aren't, we dispatch the notification immediately.

## 🔗 Relationship with other systems

### Part of this

- [NativeIntersectionObserver C++ TurboModule](../../../../../ReactCommon/react/nativemodule/intersectionobserver/__docs__/README.md).
- [C++ implementation](../../../../../ReactCommon/react/renderer/observers/intersection/__docs__/README.md).

### Used by this

- This relies on mount hooks provided by `UIManager`, and on the information
  provided by the shadow tree registry provided by `UIManager` as well.
- It uses the C++ TurboModule infra for communication between JavaScript and
  native.

### Uses this

- This is an API meant to be used by end users. It is not used directly but any
  other parts of the platform.

---

### Overview (`packages/react-native/src/private/webapis/mutationobserver/__docs__/README.md`)

# MutationObserver

[🏠 Home](../../../../../../../__docs__/README.md)

This directory contains the React Native implementation of the
[MutationObserver API](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver).

## 🚀 Usage

`MutationObserver` is meant to be used from JavaScript, exposed as a global
class.

## 📐 Design

This is the high-level design of the MutationObserver API:



The global `MutationObserver` class is defined in JavaScript and it does its
setup using a native module.

In native, it relies on ShadowTree commit hooks to get notifications about
changes in the tree, and detects mutations using the before/after revisions. It
relies on referential equality of the shadow nodes for performance
optimizations.

## 🔗 Relationship with other systems

### Part of this

- [NativeMutationObserver C++ TurboModule](../../../../../ReactCommon/react/nativemodule/mutationobserver/__docs__/README.md).
- [C++ implementation](../../../../../ReactCommon/react/renderer/observers/mutation/__docs__/README.md).

### Used by this

- This relies on `ShadowTree` commit hooks provided by `UIManager`.
- It uses the C++ TurboModule infra for communication between JavaScript and
  native.
- It uses the
  [`Event Loop`](../../../../../ReactCommon/react/renderer/runtimescheduler/__docs__/README.md)
  to schedule mutation observer callbacks as microtasks.

### Uses this

- This is an API meant to be used by end users. It is not used directly but any
  other parts of the platform.

---

### Overview (`packages/react-native/src/private/webapis/resizeobserver/__docs__/README.md`)

# ResizeObserver

[🏠 Home](../../../../../../../__docs__/README.md)

This directory contains the React Native implementation of the
[ResizeObserver API](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver).

## 🚀 Usage

`ResizeObserver` is meant to be used from JavaScript, exposed as a global class.

## 📐 Design

This is the high-level design of the ResizeObserver API:



The global `ResizeObserver` class is defined in JavaScript and it does its setup
using a native module.

In native, it relies on commit hooks from `UIManager` to learn which nodes had
layout updates after each commit (`shadowTreeDidCommit` with the affected layout
nodes). The commit hook records which observed targets may have resized. A
dedicated step in the Event Loop (as specified in the Web spec, via
`RuntimeSchedulerResizeObserverDelegate`) then runs resize observations against
the latest committed tree and notifies JavaScript when there are pending
entries. JavaScript pulls those entries via `takeRecords` and dispatches them to
the right observers.

Unlike layout events (`onLayout`), `ResizeObserver` lets callers choose which
box to observe (`content-box`, `border-box`, or `device-pixel-content-box`) and
delivers sizes for those boxes in the notification. Notifications are delivered
from the «update the rendering» step of the Event Loop (via
`RuntimeSchedulerResizeObserverDelegate`) — after the task that committed the
layout change and that task's microtask checkpoint, not synchronously when
layout is computed.

## 🔗 Relationship with other systems

### Part of this

- [NativeResizeObserver C++ TurboModule](../../../../../ReactCommon/react/nativemodule/resizeobserver/__docs__/README.md).
- [C++ implementation](../../../../../ReactCommon/react/renderer/observers/resize/__docs__/README.md).

### Used by this

- This relies on `ShadowTree` commit hooks provided by `UIManager`, including
  the list of nodes whose layout changed after each commit.
- It uses the C++ TurboModule infra for communication between JavaScript and
  native.
- It uses the
  [`Event Loop`](../../../../../ReactCommon/react/renderer/runtimescheduler/__docs__/README.md)
  to run resize observations as a dedicated step.

### Uses this

- This is an API meant to be used by end users. It is not used directly by any
  other parts of the platform.

---

### Overview (`packages/react-native/ReactAndroid/src/main/jni/first-party/jni-hack/README.md`)

This buck module exists so that targets that need to be built against both 1) Android (where we can and should use the Android NDK jni headers) and 2) the host platform(generally for local unit tests) can depend on a single target and get the right jni header for whatever platform they're building against automatically.

---

### Overview (`packages/react-native/ReactCommon/react/renderer/observers/intersection/__docs__/README.md`)

# IntersectionObserver

[🏠 Home](../../../../../../../../__docs__/README.md)

This directory contains the C++ implementation of the
[IntersectionObserver API](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver)
in React Native.

## 🔗 Relationship with other systems

### Part of

- [IntersectionObserver API](../../../../../../src/private/webapis/intersectionobserver/__docs__/README.md)

---

### Overview (`packages/react-native/ReactCommon/react/renderer/observers/mutation/__docs__/README.md`)

# MutationObserver

[🏠 Home](../../../../../../../../__docs__/README.md)

This directory contains the C++ implementation of the
[MutationObserver API](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver)
in React Native.

## 🔗 Relationship with other systems

### Part of

- [MutationObserver API](../../../../../../src/private/webapis/mutationobserver/__docs__/README.md)

---

### Overview (`packages/react-native/ReactCommon/react/renderer/observers/resize/__docs__/README.md`)

# ResizeObserver

[🏠 Home](../../../../../../../../__docs__/README.md)

This directory contains the C++ implementation of the
[ResizeObserver API](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver)
in React Native.

## 🔗 Relationship with other systems

### Part of

- [ResizeObserver API](../../../../../../src/private/webapis/resizeobserver/__docs__/README.md)

---

### Overview (`packages/react-native/src/private/testing/fantom/specs/__docs__/README.md`)

# Fantom

[🏠 Home](../../../../../../../../__docs__/README.md)

This directory contains the specifications for internal native modules used by
Fantom. These are not meant to be consumed directly.

> [!NOTE]
>
> These definitions are here (in the `react-native` package) and not in the
> `@react-native/fantom` package just for convenience, to reuse the same codegen
> configuration we already have (that is configured to look for definitions in
> `src/`).

## 🔗 Relationship with other systems

### Part of

- [Fantom](../../../../../../../../private/react-native-fantom/__docs__/README.md).

---

### Overview (`packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/README.md`)

# Bridgeless Mode for Android

This library is not ready for integration for production nor local experimentation. Expect breaking changes regularly if you use any of these APIs. Use at your own risk!

---

### Overview (`packages/react-native/ReactAndroid/src/main/java/com/facebook/react/activityresult/__docs__/README.md`)

# ActivityResultContracts for native modules

[🏠 Home](../../../../../../../../../../../__docs__/README.md)

This package lets an Android native module register an AndroidX
[`ActivityResultContract`](https://developer.android.com/training/basics/intents/result)
and receive results. The consumer app does not need to change its
`MainActivity`, add manifest entries, or ship extra Activities.

Before this, modules had to use `ActivityEventListener` with self-assigned int
request codes, which live in a global namespace with no coordination between
libraries. Calling `registerForActivityResult` on `getCurrentActivity()` does
not work either: AndroidX only allows it before the Activity is started, and
native modules are created lazily, long after that. See
[facebook/react-native#33639](https://github.com/facebook/react-native/issues/33639)
(Health Connect, whose permission contract cannot be used without
`registerForActivityResult`).

## 🚀 Usage

The API is `ReactContext.registerForActivityResult`. It has the same shape as
[`ComponentActivity.registerForActivityResult`](https://developer.android.com/training/basics/intents/result#register),
plus a leading `owner` argument that scopes the registration key. You can
register at any time. A field initializer is the recommended spot. The returned
launcher connects to the real registry once an Activity is available.

```kotlin
class MyModule(private val context: ReactApplicationContext) :
    NativeMyModuleSpec(context) {

  private var pendingPromise: Promise? = null

  private val requestPermission =
      context.registerForActivityResult(
          /* owner = */ this,
          ActivityResultContracts.RequestPermission()) { isGranted ->
        pendingPromise?.resolve(isGranted)
        pendingPromise = null
      }

  override fun requestCameraPermission(promise: Promise) {
    pendingPromise = promise
    requestPermission.launch(Manifest.permission.CAMERA)
  }
}
```

Stock AndroidX contracts work unchanged, with their own input and output types
(for example `PickVisualMedia`).

### Registration keys and collisions

Registrations are keyed by `"<owner class>:<contract class>"`, so two unrelated
libraries can register the same stock contract without clashing. Pass a stable,
long-lived `owner`, normally the module itself. Only named classes are allowed
as owners: an anonymous object gets a generated class name that can change
between builds, which breaks result delivery after the process is killed and
restored, so passing one throws `IllegalArgumentException` at registration.

The same stability concern applies to minification. If the app minifies class
names (R8/ProGuard), the obfuscated name of the owner class is not guaranteed to
be the same from one build to the next, so a result delivered after an app
update can be dropped. Keep the owner class's name (for example with
`-keepnames`) if results must survive across builds.

Registering the same contract class twice from one owner throws
`IllegalStateException`. In that case use the overload that takes a key:

```kotlin
private val pickAvatar = ctx.registerForActivityResult(this, "avatar", GetContent()) { }
private val pickBanner = ctx.registerForActivityResult(this, "banner", GetContent()) { }
```

The key is added to the owner-and-contract prefix, not used instead of it. It
only has to be unique among that owner's launchers of that contract, and it can
never clash with another library's keys. It must stay the same across process
restarts, so derive it from a constant.

Why not automatic keys, like `ComponentActivity`'s counter? Modules are created
lazily, in whatever order JS touches them. After the process is killed and
restored, the same counter value could belong to a different module, and a
restored result would reach the wrong callback. Keys built from class names do
not depend on creation order.

### Contract parameters that come from JS

Contract constructor arguments are fixed when you register. If a value comes
from JS on each call, put it in the contract's input type instead: subclass the
stock contract and pass the value through `launch()`. See `PickUpToMedia` in
`SampleTurboModule.kt`, which does this for the photo picker's item limit.

### Working examples

- `SampleTurboModule.kt`
  (`ReactCommon/react/nativemodule/samples/platform/android/`):
  `requestSamplePermission`, `pickMedia`, `pickMultipleMedia`, and
  `startSecondActivity` (multi-Activity regression check).
- rn-tester screens: `TurboModule/SampleTurboModuleExample.js` and
  `PhotoPickerAndroid/PhotoPickerAndroid.js`.

## 📐 Design

`ReactActivity` extends `ComponentActivity`, so the host Activity already owns a
real `ActivityResultRegistry`. This package only bridges the timing gap between
lazily-created modules and that registry.

- `ReactActivityResultCaller` / `ReactActivityResultCallerImpl` (internal):
  owned by the `ReactContext`. Holds the `(key, contract, callback)`
  registrations and connects them to the current Activity's registry, right away
  if an Activity exists, otherwise on the next `onHostResume`.
- `DeferredActivityResultLauncher` (internal): the launcher handed to callers.
  It forwards to the real AndroidX launcher once connected. A `launch()` made
  before that is stored (latest wins) and fired on connect.
- Registrations outlive any single Activity. `onHostDestroy` disconnects them
  but keeps them, and because the keys stay the same, AndroidX can deliver a
  result that arrives after the Activity was recreated.
- Every `onHostResume` checks each launcher against the current registry, not
  just whether it is connected to something. With more than one Activity, the
  new Activity resumes before the old one is destroyed, and the old one's
  `onHostDestroy` never runs because `currentActivity` has already moved on. A
  launcher that only checked "am I connected?" would stay attached to the old
  Activity's registry: that Activity could never be freed, and launches from the
  new screen would go to the old one.

### Threading

`ActivityResultRegistry` must only be used from the UI thread, but nothing
enforces that at runtime; calls from other threads corrupt its internal maps
silently. React Native calls in from the JS thread (registrations in field
initializers) and from the native-modules thread (`launch()`), so:

- The bookkeeping used for collision detection is a concurrent map and can be
  used from any thread. Claiming a key is a single atomic step. Registration
  stays synchronous: you get the launcher back immediately, and a duplicate key
  throws from your own call.
- Every call that reaches the registry (`register`, `launch`, `unregister`) is
  forwarded to the UI thread, and so is the launcher's connection state (checked
  with assertions in debug builds).

Notes for library authors:

- Register early, in a field initializer or the constructor. Only launching
  needs an Activity.
- An Activity that is not an `ActivityResultRegistryOwner` cannot serve
  launchers; binding to one throws `IllegalStateException`. In practice every
  `ComponentActivity` (including `ReactActivity`) is a registry owner.
- After the process is killed and restored, AndroidX redelivers a pending result
  under the same key, but any state your module held for the call (typically a
  `Promise`) is gone. Write callbacks so they tolerate firing with no pending
  state.
- `unregister()` on the returned launcher removes the registration and frees the
  key.

## 🔗 Relationship with other systems

### Part of

- [ReactAndroid](../../../../../../../../README.md): the core of React Native on
  Android.

### Used by this

- `com.facebook.react.bridge.ReactContext`: exposes the public
  `registerForActivityResult` methods, owns the caller instance, and drives
  connecting and disconnecting through its lifecycle events.
- AndroidX `androidx.activity.result`: the contracts, launchers, and registry
  that actually start activities and deliver results.

### Uses this

- `SampleTurboModule` (demo) and, in the future, third-party modules that need
  activity results or AndroidX permission contracts (for example Health
  Connect).

This API coexists with `ActivityEventListener`: results claimed by the AndroidX
registry are consumed by it, and everything else still reaches
`ActivityEventListener.onActivityResult`. The listener remains the right tool
for intents a module builds and starts itself.

---

### Overview (`packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/events/__docs__/README.md`)

# Android event dispatching

[🏠 Home](../../../../../../../../../../../../__docs__/README.md)

This directory contains Kotlin classes specific to Android event dispatching in
the new architecture.

## 📐 Design



## 🔗 Relationship with other systems

### Part of

- Android's Fabric implementation

### Used by this

This component is tightly coupled with the legacy event dispatch mechanism. Some
of the interfaces and components live in the com.facebook.react.uimanager.events
package so that they may reference internal API's.

---

### Overview (`packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/__docs__/README.md`)

# Feature Flags

[🏠 Home](../../../../../../../../../../../../__docs__/README.md)

This directory contains the Java/Kotlin bindings for the internal React Native
feature flags system.

## 🔗 Relationship with other systems

### Part of

- [Feature Flags system](../../../../../../../../../../src/private/featureflags/__docs__/README.md)

---

--- METRICS ---
- Files Extracted: 74
- Estimated Token Budget: ~45436 tokens
- Canonical Reference: https://codewiki.google/github.com/react/react-native
