Skip to content

chore(0.87): sync upstream 0.87.1 and prepare the release branch - #3100

Open
Saad Najmi (Saadnajmi) wants to merge 117 commits into
microsoft:review/0.87-interop-headerfrom
Saadnajmi:review/0.87-stable-sync
Open

Saad Najmi (Saadnajmi) wants to merge 117 commits into
microsoft:review/0.87-interop-headerfrom
Saadnajmi:review/0.87-stable-sync

Conversation

@Saadnajmi

@Saadnajmi Saad Najmi (Saadnajmi) commented Sep 22, 2026

Copy link
Copy Markdown
Collaborator

Current release stack

Depends on #3106. Sync upstream RN 0.87.1 after the reusable feature work and prepare the public RC graph. #3101 follows.

Validation and backups

The branch-specific repaired source passed hardened immutable installation, constraints, and its complete release-helper selection. The selected 18-head packet records 1,406 passing helper tests. Exact source-tree equivalence is used for rewritten endpoints where applicable; the two changed linear RC checkpoints were tested separately.

Native/API evidence retains its recorded scope. The SwiftPM and RNTester repairs have six focused native build passes. Public stable versions and runtime/API contents were preserved except for the independently reviewed SwiftPM destination repair where applicable.

Public-registry lock correction passed all 18 hosted generation, hardened immutable, constraints, and metadata-audit jobs in run 35769816507. Only equivalent executable-path spelling changes are permitted; dependency versions, checksums, and ranges are unchanged. The previous functional test results remain applicable to this metadata-only correction. Fresh GitHub CI and review remain required. Previous heads are preserved on the same repository under backup/pre-ci-repair-20260922/<original-branch> and backup/pre-public-registry-20260922/<original-branch>; local complete-history bundles were verified as well.

The 0.87 PR sequence is one first-parent path: #3037#3104#3105#3106#3100#3101#3107. The redundant #3102/#3103 reviews are consolidated into #3105.

This section supersedes earlier stack order, source identity, and validation-status notes below.

Final CI follow-up

This branch receives only these independently reviewed follow-up paths:

  • .github/workflows/microsoft-npm-publish.yml
  • .github/workflows/microsoft-pr.yml
  • packages/react-native/ReactNativeApi.d.ts
  • packages/react-native/scripts/ios-prebuild/__tests__/headers-conditional-test.js
  • packages/react-native/scripts/ios-prebuild/__tests__/hermes-test.js
  • packages/react-native/scripts/ios-prebuild/__tests__/reactNativeDependencies-test.js

The complete 16-head batch passed 92 recorded validation commands, including branch-specific API revalidation/generated TypeScript, full formatting checks, and combined targeted suites where applicable. Native changes are limited to the reviewed #3033 destination guards (also present in stable 0.85) and #3104's sidecar-copy correction (already present in its descendants). Exact source equivalence preserves earlier native results elsewhere. The public-registry lockfiles and package manifests remain byte-identical.

Previous heads are backed up at backup/pre-ci-followup-20260922/<original-branch> on their source repository. Fresh current-head CI remains required. The one-first-parent 0.87 sequence is preserved.

Flow/lint closeout

This branch receives the reviewed Flow annotation/test-fixture or duplicate Jest mapper correction. Full Flow, ESLint, and format checks pass; generator output/runtime AST or effective Jest mapper behavior remain equivalent as applicable. Public-registry locks, package manifests, and API declarations remain unchanged. Backups are verified under backup/pre-flow-lint-20260922/<original-branch>. The single first-parent PR path is preserved; current-head CI remains the final acceptance gate.

Rubén Norte (rubennorte) and others added 30 commits July 7, 2026 16:26
)

Summary:
Pull Request resolved: react#57447

The `window` and `navigator` globals were installed with plain property assignments, which produced writable and configurable data properties. This makes the global definitions safer and more spec-compliant: `window` is now non-writable and non-configurable (still enumerable), matching how browsers expose it, and `navigator` is now non-writable (still configurable and enumerable). `self` is unchanged and remains writable, configurable and enumerable. `window` and `self` are now installed on `globalThis`.

Also adds Fantom tests that assert the property descriptors of the `window`, `self`, `navigator`, `Infinity`, `NaN` and `undefined` globals so these guarantees don't regress.

Changelog:
[General][Changed] - Make the `window` global non-writable and non-configurable, and the `navigator` global non-writable

Reviewed By: huntie

Differential Revision: D110759948

fbshipit-source-id: 7cd79d9ba5a7dc4b6ef9fb61fede0d25723516b5
#publish-packages-to-npm&next
#publish-packages-to-npm&next
#publish-packages-to-npm&next
Changelog: [Internal]
Changelog: [Internal]
Changelog: [General][Changed] Bump Metro to 0.87.0
Summary:
Pull Request resolved: react#57481

It's been two releases since we separated `react-native/jest-preset` in 0.85 and this has been updated in the template.

Clean up by removing internal redirect module, public export, and peer dependency.

Changelog:
[General][Breaking] - `react-native/jest-preset` is removed — all projects must now migrate to `react-native/jest-preset` (package)

Reviewed By: rubennorte

Differential Revision: D111035221

fbshipit-source-id: d66fed9218c801201c1e965f8163f048934d4200
Summary:
Pull Request resolved: react#57482

Another cleanup to our `package.json#exports` map ahead of the Strict API rollout. This has been long-migrated to `react-native/js-polyfills` in Metro configs.

https://www.internalfb.com/code/fbsource/[960845236d89]/xplat/js/react-native-github/packages/metro-config/src/index.flow.js?lines=66

Changelog:
[General][Breaking] - `react-native/rn-get-polyfills` is removed — please use `react-native/js-polyfills` (package)

Reviewed By: rubennorte

Differential Revision: D111035710

fbshipit-source-id: d36acd7583f76f78c69a07ba7134ce8145d578f9
Summary:
Pull Request resolved: react#57475

NOTE: Resubmission of D110890810.

Replace `'react-native/Libraries/Core/InitializeCore'` with an explicit `'react-native/setup-env'` secondary export.

This was previously a special-case path excluded from our ESLint warnings. It is now formalised.

**Changes**

- Add new `src/setup-env.js` entry point and `package.json` mapping.
- Replace references in `packages/metro-config/` and `packages/community-cli-plugin/`.
- Update `warn-on-deep-imports` ESLint rule.

Changelog:
[General][Added] - Add `'react-native/setup-env'` entry point. This replaces the previous side-effectful `'react-native/Libraries/Core/InitializeCore'`.
[General][Deprecated] - Deprecate `'react-native/Libraries/Core/InitializeCore'`. Use `'react-native/setup-env'` instead.

Reviewed By: rubennorte

Differential Revision: D111022546

fbshipit-source-id: c9081997468b55b02c8a89544c7cb2026d625ad3
Summary:
Pull Request resolved: react#57476

NOTE: Resubmission of D110488985.

**Motivation**

The public type for `Touchable` has zero overlap with its runtime value. This is an internal implementation object which is undocumented.

https://www.internalfb.com/code/fbsource/[86267213ee84]/xplat/js/react-native-github/packages/react-native/Libraries/Components/Touchable/Touchable.d.ts?lines=18-24

https://www.internalfb.com/code/fbsource/[86267213ee84]/xplat/js/react-native-github/packages/react-native/Libraries/Components/Touchable/Touchable.js?lines=966-986

Replaces D110483989 / react#57419.

**Impact**

This is a **breaking change** with few open source consumers. The `onTouchStart` etc prop typings are part of `ViewProps` today, which is a suitable replacement.

Across projects I've been testing for the Strict TypeScript API rollout, the only load bearing consumer was Uniwind — where I've sent a PR to address this.

- uni-stack/uniwind#592.

Changelog:
[General][Breaking] - The `Touchable` root export (undocumented) is removed. If you are extending `Touchable` as a type, please use `ViewProps` instead.

Reviewed By: rubennorte

Differential Revision: D111022549

fbshipit-source-id: bf29ae826d34fb04889b9f56de0f11904fce3f53
Summary:
Pull Request resolved: react#57484

Follows up react#57277, going further to remove this entry point mapping entirely — D110911864 further supports that these import paths were never used externally (and in the first case, `src/private/` has always been an explicit name).

**One caveat**

`rn-tester` includes some runtime and Fantom test references to `'react-native/src/private/...'`.

- This happens to continue working because we've not enabled `"exports"` resolution under Flow.
- These can be classified as repo-local — motivation is simplifying/tightening the root `package.json` for open source.

Changelog:
[Internal] - (Covered by react#57277)

Reviewed By: rubennorte

Differential Revision: D111034634

fbshipit-source-id: 4c80223dcf634201df9c77f8bde96dfb0c6f64f9
Summary:
Pull Request resolved: react#57495

See [**RFC0894: Removing deep imports from react-native**](react-native-community/discussions-and-proposals#894)

Exposes a `'react-native/react-private-interface'` subpath export on the main package, to replace `Libraries/ReactPrivate/ReactNativePrivateInterface.js`.

**Impact: Internal**

This is a private contract between `react` and `react-native`.

- `ReactNativePrivateInterface` is deprecated and we'll migrate React call sites in a future version before cleanup.

**Naming**

Translate directly to `react-private-interface` ("private interface for React"). There's alternatives here but the explicitness and continuity is helpful, I believe.

Changelog: [Internal]

Reviewed By: robhogan

Differential Revision: D111231527

fbshipit-source-id: 9caa17d2762fe290f21f80894e018e29f95fba46
Summary:
Pull Request resolved: react#57489

See [**RFC0894: Removing deep imports from react-native**](react-native-community/discussions-and-proposals#894)

Adds a `'react-native/unstable-internals-do-not-use'` entry point that acts as an explicit, opt-in escape hatch for frameworks and libraries that depend on specific React Native internals.

Follows (and supersedes) react-native-community/discussions-and-proposals#985.

Resolves T270727304.

**Motivation**

- Maintains a known list of which React Native internals are still in use.
- Decouples removal of the Strict API opt-out from the longer-term decisions about these APIs.
- Lets us relocate supporting source files freely, since consumers reference this subpath instead of deep internal paths.

**Notes**

- Reuses the runtime **object-with-getter pattern** (same as `index.js`), to avoid any native module side effects caused by loading adjacent file exports.
    - e.g. in Expo, [`hmrUtils.js`](https://github.com/expo/expo/blob/2d07e3a17f4be2284bbf579d8825fe32f762ce1a/packages/expo/src/async-require/hmrUtils.native.ts?fbclid=IwY2xjawS7GjNwZG9mA2V4dG4DYWVtAjExAGJyaWQRMTZ1ckEwU05oWUw2bDBVN21zcnRjBmFwcF9pZAEwAAEen3UuX4Ig-RD3n1ULZIHIHq21Mfk_ci9b2SxquY7UkngDs6qhnRt5YQlb8Os_aem_ylJy40egSOl1qhZ9bA9HTA) is designed to be run early in RN startup — preserve the lazy require characteristic and do not break this.
- TypeScript defs on this API are minimal, with complex internal input/handle types reduced to `unknown`. As with D110602194, these are intended to be feature-locked.

**Exposed internals and known consumers**

NOTE: The exports the community needs have reduced slightly since the spreadsheet in RFC0895 and would almost all align with `devsupport`. However, we're explicitly leaving a decision to formalise until later, and we may need to add in extra APIs quickly based on RC feedback.

| Export | Source module | Known consumers |
|---|---|---|
| `AppContainer` | `Libraries/ReactNative/AppContainer` | react-native-screens ([DebugContainer.tsx](https://github.com/software-mansion/react-native-screens/blob/6f38d76129d40cc8145d06b98f885b508fa7bf2d/src/components/DebugContainer.tsx#L5)) |
| `AssetSourceResolver` | `Libraries/Image/AssetSourceResolver` | Re.pack ([IncludeModules.ts](https://github.com/callstack/repack/blob/2498b3a426203daa4b81c7e6f7a88e86d88e77b9/packages/repack/src/modules/IncludeModules.ts#L9)) |
| `customDirectEventTypes` | `Libraries/Renderer/shims/ReactNativeViewConfigRegistry` | react-native-gesture-handler ([customDirectEventTypes.ts](https://github.com/software-mansion/react-native-gesture-handler/blob/ee147abf364bef48a02d3cf437572b4dddd30bec/packages/react-native-gesture-handler/src/handlers/customDirectEventTypes.ts#L2)) |
| `DevLoadingView` | `Libraries/Utilities/DevLoadingView` | Expo ([hmrUtils.native.ts](https://github.com/expo/expo/blob/2d07e3a17f4be2284bbf579d8825fe32f762ce1a/packages/expo/src/async-require/hmrUtils.native.ts)), Re.pack ([WebpackHMRClient.ts](https://github.com/callstack/repack/blob/2498b3a426203daa4b81c7e6f7a88e86d88e77b9/packages/repack/src/modules/WebpackHMRClient.ts)) |
| `getDevServer` | `Libraries/Core/Devtools/getDevServer` | Expo ([getDevServer.native.ts](https://github.com/expo/expo/blob/2d07e3a17f4be2284bbf579d8825fe32f762ce1a/packages/expo/src/async-require/getDevServer.native.ts), [hmrUtils.native.ts](https://github.com/expo/expo/blob/2d07e3a17f4be2284bbf579d8825fe32f762ce1a/packages/expo/src/async-require/hmrUtils.native.ts), [base.ts](https://github.com/expo/expo/blob/2d07e3a17f4be2284bbf579d8825fe32f762ce1a/packages/expo/src/dom/base.ts), [getDevServer.native.ts](https://github.com/expo/expo/blob/2d07e3a17f4be2284bbf579d8825fe32f762ce1a/packages/expo/metro-runtime/src/getDevServer.native.ts), [devServerEndpoints.ts](https://github.com/expo/expo/blob/2d07e3a17f4be2284bbf579d8825fe32f762ce1a/packages/expo/log-box/src/utils/devServerEndpoints.ts), [getConnectionInfo.native.ts](https://github.com/expo/expo/blob/2d07e3a17f4be2284bbf579d8825fe32f762ce1a/packages/expo/devtools/src/getConnectionInfo.native.ts), [index.native.ts](https://github.com/expo/expo/blob/2d07e3a17f4be2284bbf579d8825fe32f762ce1a/packages/expo-router/src/getDevServer/index.native.ts)) |
| `HMRClient` | `Libraries/Utilities/HMRClient` | Expo ([metroServerLogs.native.ts](https://github.com/expo/expo/blob/2d07e3a17f4be2284bbf579d8825fe32f762ce1a/packages/expo/metro-runtime/src/metroServerLogs.native.ts)) |
| `NativeExceptionsManager` | `Libraries/Core/NativeExceptionsManager` | Expo ([hmrUtils.native.ts](https://github.com/expo/expo/blob/2d07e3a17f4be2284bbf579d8825fe32f762ce1a/packages/expo/src/async-require/hmrUtils.native.ts)), Re.pack ([WebpackHMRClient.ts](https://github.com/callstack/repack/blob/2498b3a426203daa4b81c7e6f7a88e86d88e77b9/packages/repack/src/modules/WebpackHMRClient.ts)) |
| `NativeRedBox` | `Libraries/NativeModules/specs/NativeRedBox` | Expo ([hmrUtils.native.ts](https://github.com/expo/expo/blob/2d07e3a17f4be2284bbf579d8825fe32f762ce1a/packages/expo/src/async-require/hmrUtils.native.ts)), Re.pack ([WebpackHMRClient.ts](https://github.com/callstack/repack/blob/2498b3a426203daa4b81c7e6f7a88e86d88e77b9/packages/repack/src/modules/WebpackHMRClient.ts)) |
| `NativeSourceCode` | `Libraries/NativeModules/specs/NativeSourceCode` | Expo ([getBundleUrl.native.ts](https://github.com/expo/expo/blob/2d07e3a17f4be2284bbf579d8825fe32f762ce1a/packages/expo/src/utils/getBundleUrl.native.ts)) |
| `PressabilityDebugView` | `Libraries/Pressability/PressabilityDebug` | react-native-gesture-handler ([PressabilityDebugView.tsx](https://github.com/software-mansion/react-native-gesture-handler/blob/ee147abf364bef48a02d3cf437572b4dddd30bec/packages/react-native-gesture-handler/src/handlers/PressabilityDebugView.tsx#L2)) |

**Alternative names**

- `unstable-frameworks`
- `unstable-devsupport`
- `frameworks-private-interface` (mirroring `ReactPrivateInterface.js`) — this is likely a future stable shape candidate.

Changelog: [Internal]

Reviewed By: rubennorte

Differential Revision: D110911864

fbshipit-source-id: 4cb4758e6621a626916cc6543f9a1f8462f1d5b0
Summary:
Pull Request resolved: react#57490

See [**RFC0894: Removing deep imports from react-native**](react-native-community/discussions-and-proposals#894)

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

**Opt-in → opt-out**

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

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

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

**How to opt out**

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

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

**Other changes**

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

**Rollout plan**

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

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

**What's improved since 0.80?**

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

Most notably:

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

**Rollback plan**

Revert this diff.

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

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

Reviewed By: cortinico

Differential Revision: D110458670

fbshipit-source-id: 4b0e0b458a5f895f783d6d936e7b11ccff2df076
…oval (react#57539)

Summary:
react#57481 removed the `react-native/jest-preset` subpath redirect, but the
in-repo `private/helloworld` template still referenced `preset: 'react-native'`,
which Jest resolves to the now-deleted `react-native/jest-preset.js`. This broke
all `test_ios_helloworld*` CI jobs on 0.87-stable at the `yarn test` step:

  Validation Error: Module react-native should have "jest-preset.js" or
  "jest-preset.json" file at the root.

Since `private/helloworld` is excluded from the yarn workspace and installed
standalone, it also needs `@react-native/jest-preset` as an explicit
devDependency for the preset to resolve.

- Point jest.config.js preset at `@react-native/jest-preset`.
- Add `@react-native/jest-preset` to devDependencies.

Changelog: [Internal]

Test Plan:
CI: `test_ios_helloworld*` jobs pass (previously failing at `yarn test`).
…t#57498)

Summary:
Pull Request resolved: react#57498

**Motivation**

While sanity checking react#57492, I double checked why we use `path.join(ctx.reactNativePath, ...)` here when adjacent OOT platforms resolve by package name.

It turns out this complexity is historic and redundant:

- `reactNativePath` doesn't customize the `react-native` package name — it only resolves the `node_modules` directory. [[1]](https://github.com/react-native-community/cli/blame/main/packages/cli-tools/src/findPackageDependencyDir.ts#L81)
- We now (since ~2 years ago) resolve using `{paths: [ctx.root]}`, making the manual `path.join` redundant.

**This diff**

Drops the `reactNativePath` option and resolves `react-native/setup-env` directly by package name.

Purely a refactor. No need to pick to 0.87.

Changelog: [Internal]

Reviewed By: cipolleschi

Differential Revision: D111225671

fbshipit-source-id: ff0a385172228f51cde747266543cc615be7ee38
react#57557)

Summary:
Pull Request resolved: react#57557

Fresh projects **redbox on launch** — e.g.:

```
Failed to call into JavaScript module method RCTDeviceEventEmitter.emit().
Module has not been registered as callable.
Registered callable JavaScript modules (n = 1): AppRegistry.
```

(The named module varies — `HMRClient.setup()`, `RCTDeviceEventEmitter.emit()` — it's whichever callable module native calls first.) `n = 1: AppRegistry` is the tell: **core initialization never runs**.

## Root cause (react#57475)

Core init runs via Metro's `serializer.getModulesRunBeforeMainModule`. Metro (`metro/src/lib/getAppendScripts.js`) only emits the run-before `__r()` for a module **already present in the bundle graph**, and silently skips it otherwise:

```js
const paths = [...options.runBeforeMainModule, entryPoint];
for (const path of paths) {
  if (modules.some((module) => module.path === path)) {  // only if already in the graph
    /* __r(moduleId) */
  }
}
```

**react#57475 switched the run-before target from `Libraries/Core/InitializeCore` → `src/setup-env.js`.

- `InitializeCore.js` **is** reachable (imported by `Libraries/ReactPrivate/ReactNativePrivateInitializeCore.js`).
- `src/setup-env.js` is imported by **nothing** → not in the graph → silently skipped → core init never runs.

The two modules are functionally identical (both call `setUpDefaultReactNativeEnvironment().default()`), so only *reachability* changed. react#57498 was cosmetic (same resolved file) and does not fix this.

### Evidence (bundle tail)

| Run-before target | Bundle tail | Boots? |
|---|---|---|
| `setup-env` (current) | `__r(0);` | ❌ |
| `InitializeCore` (this PR) | `__r(<InitializeCore>); __r(0);` | ✅ |

Verified end-to-end via `test-release-local -t RNTestProject -p iOS`. Ruled out: Metro cache (cold `--reset-cache` identical), stale Metro, and react#57484 (`./src/*` exports removal). Reproduces via the `react-native-community/cli` bundling path (OSS `react-native start`); internal Meta bundling is unaffected, which is why CI/internal stayed green.

## Scope — interim stopgap

Only the **internal Metro bootstrap target** reverts to `InitializeCore`. The public `react-native/setup-env` entry point and its deprecation of `InitializeCore` are **unchanged**.

The **durable fix** is to make `setup-env` graph-reachable (or make Metro treat `getModulesRunBeforeMainModule` entries as graph roots) — which will then allow `InitializeCore` to be removed as intended. cc huntie (`setup-env` stack owner).

A cherry-pick of this is also up against `0.87-stable` (react#57553).

## Changelog

[General][Fixed] - Fix apps failing to boot ("... not registered as callable") caused by core init not running.

Reviewed By: christophpurrer

Differential Revision: D112002434

fbshipit-source-id: ea3559ef74d31f2c0f9af78aa0a020f4b322e7e0
…react#57552)

Summary:
`scripts/e2e/init-project-e2e.js` publishes in-repo packages to the local Verdaccio proxy with `npm publish`, but omits `--tag`. **npm ≥ 11** (bundled with Node 24+) refuses to publish a prerelease version (e.g. `0.87.0-rc.0`) without an explicit tag:

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

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

## Fix

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

## Changelog

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

Pull Request resolved: react#57552

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

Reviewed By: christophpurrer

Differential Revision: D111995913

Pulled By: zeyap

fbshipit-source-id: 107a96d5c4317129228f783ad52bffe1578d1138
#publish-packages-to-npm&next
Summary:
react#57475 pointed Metro's `getModulesRunBeforeMainModule` at `react-native/setup-env` (`src/setup-env.js`) instead of `InitializeCore`.

But Metro's serializer only emits a run-before-main require for modules **already in the bundle graph** — see `getAppendScripts`:

```js
const paths = [...options.runBeforeMainModule, entryPoint];
for (const path of paths) {
  if (modules.some(module => module.path === path)) { /* emit run stmt */ }
}
```

Nothing imports `src/setup-env.js` at runtime, so it was silently dropped. The RN environment setup (`setUpDefaultReactNativeEnvironment`: `HMRClient`, timers, batched bridge, `AppRegistry` setup, …) then never ran before the app's main module, and the app **redboxed on launch**:

```
Error: Failed to call into JavaScript module method HMRClient.setup().
Module has not been registered as callable.
Registered callable JavaScript modules (n = 1): AppRegistry.
```

This broke the **template E2E tests** on both iOS and Android — the app renders a redbox, so Maestro's `assertVisible: 'Welcome to React Native'` fails (the `test (…)` jobs are green only because the Maestro step runs with `continue-on-error: true`; the real failure surfaces via the retry chain and the `retry_2 / report` job).

## Fix

Have the deprecated `InitializeCore` delegate to `'react-native/setup-env'` via a side-effectful `require`. `InitializeCore` is a guaranteed graph entry (renderer → `ReactNativePrivateInitializeCore` → `InitializeCore`), so this pulls `src/setup-env.js` into the graph, and `getModulesRunBeforeMainModule` runs it before the main module again.

Behavior is unchanged: `setup-env` and `InitializeCore` both call the idempotent `setUpDefaultReactNativeEnvironment()`. This keeps react#57475 move to `setup-env` intact rather than reverting it.

## Changelog:
[General][Fixed] - Fix app failing to initialize (`HMRClient.setup()` redbox) because the environment setup module was dropped from the bundle

Pull Request resolved: react#57492

Test Plan:
- Template E2E (`test_e2e_ios_templateapp` / `test_e2e_android_templateapp`) should pass: app launches and shows "Welcome to React Native" instead of the redbox.

cc huntie (react#57475)

Reviewed By: cipolleschi

Differential Revision: D111226610

Pulled By: huntie

fbshipit-source-id: b44e82a248c1f2333c2ea85001c9f243b54619ad
Summary:
Pull Request resolved: react#57560

Reverts D112002434.

This fix was needed on `0.87-stable` but not on `main`, since the `setup-env`-in-bundle-graph fix (react#57492) was already present, see file at time of D112002434:

https://github.com/react/react-native/blob/08c323346be6c0fbbd70900d48435f977a78a1bb/packages/react-native/Libraries/Core/InitializeCore.js#L30-L37

See react#57559 for more info.

Changelog: [Internal]

Reviewed By: zeyap

Differential Revision: D112101450

fbshipit-source-id: 435a24e72415e18b5e3d6a5144ed805adc415a95
…tNativeHeaders framework (react#57285)

Summary:
The prebuilt `React.xcframework` previously relied on a Clang VFS overlay (`React-VFS.yaml`) to make headers importable, because the headers were laid out in CocoaPods-style namespaced folders rather than standard framework conventions. The overlay had to be generated at build time, re-resolved at pod-install time per slice, and injected as `-ivfsoverlay` flags into every Obj-C, C++, and Swift compile (including aggregate and third-party pod targets).

This is fragile, hard to reason about, and incompatible with SwiftPM consumption.

This PR removes the VFS overlay entirely and resolves headers through standard framework/header-search-path mechanics instead.

**Headers are now emitted into the artifact according to an explicit, executable spec:**

- **`React.xcframework`** — each slice's `React.framework` carries every `<React/...>` header plus a framework module map, so `#import <React/...>` and `import React` resolve through `FRAMEWORK_SEARCH_PATHS` automatically.
- **`ReactNativeHeaders.xcframework`** (new, headers-only) — carries every other namespace (`<react/...>`, `<yoga/...>`, `folly`, `glog`, …), shipped alongside in the prebuilt tarball and exposed via a single header search path.
- This makes `ReactNativeDependencies` binary-only.

No clang VFS overlay, no per-target `-ivfsoverlay` flags. The layout is driven by a single source of truth (`headers-spec.js`, rules R1–R11) that both the prebuild compose step and downstream SwiftPM tooling derive from, so the shipped header set cannot drift from the spec.

Source headers are byte-identical to the repo — the only consumer-facing change needed is bare-form angle includes (`#import <RCTAppDelegate.h>` → `#import <React/RCTAppDelegate.h>`).

**Consumer surfaces the flattened layout initially dropped are restored** (validated against Expo and community Fabric modules):

- Private headers (`RCTBridge+Private.h` + the Fabric `RCTComponentView*` family) are exposed in the `React` module map — modular where safe, `textual` where they reach C++ — so frameworks like Expo compile unchanged, incl. Swift access to `RCTBridge.moduleRegistry`.
- `React_RCTAppDelegate-umbrella.h` is re-emitted (derived from the live header set) for consumers probing it via `__has_include`.
- Sources shipping under multiple include spellings (`React/X.h` + legacy `CoreModules/…`, `RCTImage/…`, bare aliases — 116 today) keep content at ONE module-owned spelling; other spellings become generated redirect shims, so `-fmodules` consumers cannot hit duplicate declarations.
- The `React-RCTFabric` facade re-vends `RCTFabricComponentsPlugins.h` at `header_dir "React"`, keeping community Fabric modules' quoted `#import "RCTFabricComponentsPlugins.h"` working as with source pods.

**The layout is verified at generator time** (`headers-verify.js`, runs in the prebuild compose CI job): unresolvable includes ratchet against a committed baseline, composed module maps/umbrellas must byte-match the spec render, and consumer-shaped compile smokes must pass (the `React` module, every namespace module, an Expo-shaped ObjC++ fixture, and a Swift `moduleRegistry` fixture). Fail-closed guards cover header collisions, allowlist drift, and missing OR undeclared third-party deps namespaces (the latter surfaced `SocketRocket`, which is deliberately NOT relocated — the real pod vends it, and textual copies collide under `use_frameworks`; the gate asserts its absence).

**Key changes**

- **New**: `headers-spec.js` (the executable layout contract, R1–R11), `headers-compose.js` (emitter for both xcframeworks), `headers-inventory.js` (podspec-driven header classifier feeding the spec + a diagnostic manifest), `headers-verify.js` (generator-time gate + CI step), `__docs__/headers-rules.md` (rules + rationale).
- **Removed**: `vfs.js`, VFS types in `types.js`, and the VFS processing/flag-injection paths in `rncore.rb` and `xcframework.js`.
- **Updated**: `React-Core-prebuilt.podspec` (vends both xcframeworks, flattens `ReactNativeHeaders` headers into `Headers/` via `prepare_command`, fails closed on incomplete tarballs), `rncore.rb` / `react_native_pods.rb` (header search path instead of overlay flags), `prebuild-ios-core.yml` (core tarball ships both xcframeworks; compose job verifies the composed headers), README (VFS docs replaced with the new model).
- Added facades to the Podspecs that shouldn't be in use when running using precompiled frameworks to satisfy dependencies as empty pod-specs (with the single `RCTFabricComponentsPlugins.h` re-vend exception noted above).

## Changelog:

[IOS] [CHANGED] - Remove the Clang VFS overlay from prebuilt React Native Core; resolve headers via React.xcframework + a new headers-only ReactNativeHeaders.xcframework

Pull Request resolved: react#57285

Test Plan:
- [x] rn-tester builds against the prebuilt `React-Core-prebuilt` pod (Debug + Release) with no `-ivfsoverlay` flags present in the generated xcconfigs.
- [x] rn-tester builds against React native source code (without any prebuilt artifacts)
- [x] `#import <React/...>`, `import React;`, and the relocated namespaces (`<react/...>`, `<yoga/...>`, `folly`/`glog`) all resolve.
- [x] Prebuilt tarball contains both `React.xcframework` and `ReactNativeHeaders.xcframework`; pod install flattens headers into `React-Core-prebuilt/Headers`.
- [x] Switch RN-tester between Debug/Release and verify that both `React.xcframework` and `ReactNativeHeaders.xcframework` are changed between debug and release correctly.
- [x] `headers-verify.js` gate green on Debug and Release composes (`-Werror=non-modular-include-in-framework-module` never trips in consumer builds).
- [x] `private/helloworld` builds against the prebuilt core (CocoaPods path).
- [x] Expo SDK compiles against the prebuilt artifacts (private headers, `React_RCTAppDelegate` umbrella probe, Fabric quoted imports).

Reviewed By: fabriziocucci

Differential Revision: D111448598

Pulled By: cipolleschi

fbshipit-source-id: 72bc2f37765ad425722161a038e410ba976858a5
…Frameworks (react#57305)

Summary:
**Depends on react#57285

In source builds, `React-Core` ships non-header resources — its privacy manifest (`PrivacyInfo.xcprivacy`) and its localized strings (RCTI18nStrings) — via the podspec's resource_bundles. In the prebuilt path those source pods aren't installed (CocoaPods facades) or aren't present at all (SwiftPM), so these resources were silently dropped: prebuilt/SwiftPM apps shipped no React Native privacy manifest, and localized strings were unavailable.

This embeds them in React.framework at prebuild time so they ship uniformly across CocoaPods-prebuilt and SwiftPM, with source builds unchanged:

- **Privacy manifest** — the PrivacyInfo.xcprivacy of the pods baked into React.framework are merged into one manifest at the framework root. React.framework is a dynamic framework, so Xcode's privacy-report aggregation picks it up automatically (no runtime involvement).
- **RCTI18nStrings** — rebuilt as RCTI18nStrings.bundle inside React.framework. RCTLocalizedString.mm now resolves the bundle from its own framework first (bundleForClass:), falling back to the app's main bundle for static source builds.

It also fixes a latent bug in `React-Core.podspec`: a later resource_bundles = was overwriting the earlier resource_bundle =, so source builds had stopped shipping RCTI18nStrings. Both bundles are now declared together. With the artifact owning these resources, the prebuilt RNCore facade no longer carries them.

## Changelog:

[IOS][FIXED] - Ship React-Core's privacy manifest and localized strings (RCTI18nStrings) inside the prebuilt React.xcframework, so CocoaPods-prebuilt and SwiftPM apps include them

Pull Request resolved: react#57305

Test Plan:
- ✅ yarn jest packages/react-native/scripts/ios-prebuild — unit + integration tests for the merge/discovery/bundle-build logic (red/green).
- ✅ Built React.xcframework from this branch and confirmed each slice's React.framework carries the merged PrivacyInfo.xcprivacy and RCTI18nStrings.bundle (37 locales).
- ✅ Cold-built rn-tester in prebuilt mode and verified the app bundle contains Frameworks/React.framework/{PrivacyInfo.xcprivacy, RCTI18nStrings.bundle}.
- ✅ Confirmed React-Core.podspec now reports both resource bundles (RCTI18nStrings, React-Core_privacy) for source builds.

Reviewed By: fabriziocucci

Differential Revision: D111448862

Pulled By: cipolleschi

fbshipit-source-id: a95360f51cc1131510ef03f7e48c689575d1c22d
…encies pod via dependency-only facades (react#57440)

Summary:
Step 1 of making the prebuilt `ReactNativeDependencies` pod the **single header authority** for the third-party C/C++ deps (RCT-Folly, glog, boost, DoubleConversion, fmt, fast_float, SocketRocket) in prebuilt-deps mode.

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

Three commits:

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

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

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

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

## Changelog:

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

Pull Request resolved: react#57440

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

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

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

Reviewed By: fabriziocucci

Differential Revision: D111449257

Pulled By: cipolleschi

fbshipit-source-id: ace5716868d126a08721200efd640e903b191658
…ude-health ratchet (react#57565)

Summary:
After the SwiftPM stack landed (react#57332), the `prebuild_react_native_core / compose-xcframework` jobs (Debug and Release) went red on the **"Verify composed headers"** step (`headers-verify.js`), not on the XCFramework compile:

```
include-health ratchet: 2 NEW unresolvable include(s) in shipped headers
(work in source builds via pod header maps, break the packaged layout):
  unresolved CoreModules/RCTInspectorWebSocketReporter.h -> CFNetwork/CFNetwork.h
  unresolved React/RCTInspectorWebSocketReporter.h -> CFNetwork/CFNetwork.h
```

`React/CoreModules/RCTInspectorWebSocketReporter.h` (added in react#57543, "Add CDP support for WebSocket events (iOS)") does `#import <CFNetwork/CFNetwork.h>` because it uses `CFHTTPMessageRef`. The include-health ratchet classifies any include whose first path segment isn't in the `SDK_PREFIXES` allowlist in `headers-inventory.js` as `unresolved`. **`CFNetwork` was missing from that allowlist** — even though it's a genuine Apple system framework that's always available in the SDK, exactly like `CoreFoundation`, `Security`, and `Network`, which are already listed. (Two offenders because the same header ships under two natural paths, `CoreModules/` and `React/`.)

## Fix

Add `CFNetwork` to `SDK_PREFIXES`. This is the accurate classification (it's a system framework), so **no baseline change is required**.

## Changelog:

[INTERNAL] [FIXED] - Classify `CFNetwork` as a system framework in the prebuilt-header include-health ratchet

Pull Request resolved: react#57565

Test Plan:
- Ran the include-health stage locally against the source tree + committed `headers-include-baseline.json`: `CFNetwork` is no longer flagged, **0 new offenders, 0 baseline entries to shrink**.
- `ios-prebuild` unit suite: **56/56 pass**.

Reviewed By: cortinico

Differential Revision: D112115176

Pulled By: cipolleschi

fbshipit-source-id: 1bf28d5dae361e88c85c4f4678aeb9b4b9c6c7ca
Preserve validated per-branch source and corrected stack dependencies.
Preserve package versions and the linear stack; change only equivalent executable-path metadata.
Apply the independently reviewed branch-specific CI follow-up while preserving public-registry locks and the linear stack.
Apply the independently reviewed branch-specific CI follow-up while preserving public-registry locks and the linear stack.
Apply the independently reviewed branch-specific CI follow-up while preserving public-registry locks and the linear stack.
Apply the independently reviewed branch-specific CI follow-up while preserving public-registry locks and the linear stack.
Apply the independently reviewed branch-specific CI follow-up while preserving public-registry locks and the linear stack.
Apply the independently reviewed branch-specific CI follow-up while preserving public-registry locks and the linear stack.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.