Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .flowconfig
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ experimental.multi_platform.extensions=.android
munge_underscores=true

module.name_mapper='^react-native$' -> '<PROJECT_ROOT>/packages/react-native/index.js'
module.name_mapper='^react-native/react-private-interface$' -> '<PROJECT_ROOT>/packages/react-native/src/react-private-interface.js'
module.name_mapper='^react-native/setup-env$' -> '<PROJECT_ROOT>/packages/react-native/src/setup-env.js'
module.name_mapper='^react-native/\(.*\)$' -> '<PROJECT_ROOT>/packages/react-native/\1'
module.name_mapper='^@react-native/dev-middleware$' -> '<PROJECT_ROOT>/packages/dev-middleware'
; [macOS Resolve workspace self-references (incl. @react-native/fantom) in yarn pnpm mode
Expand Down
43 changes: 36 additions & 7 deletions .github/actions/test-ios-rntester/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,18 @@ inputs:
required: false
default: false
use-frameworks:
description: Whether we have to build with Dynamic Frameworks. If this is set to true, it builds from source
description: Whether we have to build with Dynamic Frameworks.
required: false
default: false
use-prebuilds:
description: >-
Whether to consume the prebuilt ReactCore/ReactNativeDependencies
artifacts. 'auto' (default) keeps the historical coupling: prebuilds for
static, source for dynamic frameworks. Pass 'true' with
use-frameworks:true for the prebuilt + dynamic-frameworks lane (the
config of the 2026-07-03 SocketRocket dual-copy regression).
required: false
default: auto

runs:
using: composite
Expand All @@ -41,33 +50,53 @@ runs:
- name: Prepare IOS Tests
if: ${{ inputs.run-unit-tests == 'true' }}
uses: ./.github/actions/prepare-ios-tests
- name: Resolve prebuilds mode
id: prebuilds
shell: bash
run: |
if [[ "${{ inputs.use-prebuilds }}" == "auto" ]]; then
# Historical coupling: prebuilds for static, source for dynamic frameworks.
if [[ "${{ inputs.use-frameworks }}" == "true" ]]; then
echo "enabled=false" >> "$GITHUB_OUTPUT"
else
echo "enabled=true" >> "$GITHUB_OUTPUT"
fi
elif [[ "${{ inputs.use-prebuilds }}" == "true" ]]; then
echo "enabled=true" >> "$GITHUB_OUTPUT"
elif [[ "${{ inputs.use-prebuilds }}" == "false" ]]; then
echo "enabled=false" >> "$GITHUB_OUTPUT"
else
# Don't silently treat a typo as 'disabled' — surface it.
echo "::warning::Unexpected use-prebuilds value '${{ inputs.use-prebuilds }}' (expected auto/true/false); treating as disabled."
echo "enabled=false" >> "$GITHUB_OUTPUT"
fi
- name: Download ReactNativeDependencies
if: ${{ inputs.use-frameworks == 'false' }}
if: ${{ steps.prebuilds.outputs.enabled == 'true' }}
uses: actions/download-artifact@v7
with:
name: ReactNativeDependencies${{ inputs.flavor }}.xcframework.tar.gz
path: /tmp/third-party/
- name: Print third-party folder
if: ${{ inputs.use-frameworks == 'false' }}
if: ${{ steps.prebuilds.outputs.enabled == 'true' }}
shell: bash
run: ls -lR /tmp/third-party
- name: Download React Native Prebuilds
if: ${{ inputs.use-frameworks == 'false' }}
if: ${{ steps.prebuilds.outputs.enabled == 'true' }}
uses: actions/download-artifact@v7
with:
name: ReactCore${{ inputs.flavor }}.xcframework.tar.gz
path: /tmp/ReactCore
- name: Print ReactCore folder
if: ${{ inputs.use-frameworks == 'false' }}
if: ${{ steps.prebuilds.outputs.enabled == 'true' }}
shell: bash
run: ls -lR /tmp/ReactCore
- name: Install CocoaPods dependencies
shell: bash
run: |
if [[ ${{ inputs.use-frameworks }} == "true" ]]; then
export USE_FRAMEWORKS=dynamic
else
# If use-frameworks is false, let's use prebuilds
fi
if [[ "${{ steps.prebuilds.outputs.enabled }}" == "true" ]]; then
export RCT_USE_LOCAL_RN_DEP="/tmp/third-party/ReactNativeDependencies${{ inputs.flavor }}.xcframework.tar.gz"
export RCT_TESTONLY_RNCORE_TARBALL_PATH="/tmp/ReactCore/ReactCore${{ inputs.flavor }}.xcframework.tar.gz"
fi
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/microsoft-npm-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Publish to npm
on:
push:
branches:
- "*-stable"
- '*-stable'

concurrency:
# Serialize release lines because they share the latest and next tags.
Expand Down Expand Up @@ -36,7 +36,7 @@ jobs:
- name: Setup toolchain
uses: ./.github/actions/microsoft-setup-toolchain
with:
node-version: "22"
node-version: '22'

- name: Install dependencies
run: yarn install --immutable
Expand Down
10 changes: 9 additions & 1 deletion .github/workflows/microsoft-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,15 @@ name: PR
on:
pull_request:
types: [opened, synchronize, edited]
branches: ['main', '*-stable', 'release/*', '*-merge', 'review/**', 'saadnajmi/0-85-redbox2-merge']
branches:
[
'main',
'*-stable',
'release/*',
'*-merge',
'review/**',
'saadnajmi/0-85-redbox2-merge',
]

concurrency:
# Ensure single build of a pull request. `main` should not be affected.
Expand Down
37 changes: 34 additions & 3 deletions .github/workflows/prebuild-ios-core.yml
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ jobs:
uses: actions/cache/restore@v5
with:
path: packages/react-native/.build/output/xcframeworks
key: v2-ios-core-xcframework-${{ matrix.flavor }}-${{ hashFiles('packages/react-native/Package.swift', 'packages/react-native/scripts/ios-prebuild/*.js', 'packages/react-native/scripts/ios-prebuild.js', 'packages/react-native/React/**/*', 'packages/react-native/ReactCommon/**/*', 'packages/react-native/Libraries/**/*') }}
key: v3-ios-core-xcframework-${{ matrix.flavor }}-${{ hashFiles('packages/react-native/Package.swift', 'packages/react-native/scripts/ios-prebuild/*.js', 'packages/react-native/scripts/ios-prebuild.js', 'packages/react-native/React/**/*', 'packages/react-native/ReactCommon/**/*', 'packages/react-native/Libraries/**/*') }}
- name: Setup node.js
if: steps.restore-ios-xcframework.outputs.cache-hit != 'true'
uses: ./.github/actions/setup-node
Expand All @@ -157,6 +157,24 @@ jobs:
pattern: prebuild-ios-core-headers-${{ matrix.flavor }}-*
path: packages/react-native/.build/headers
merge-multiple: true
- name: Download ReactNativeDependencies
if: steps.restore-ios-xcframework.outputs.cache-hit != 'true'
uses: actions/download-artifact@v7
with:
name: ReactNativeDependencies${{ matrix.flavor }}.xcframework.tar.gz
path: /tmp/third-party/
- name: Extract ReactNativeDependencies
if: steps.restore-ios-xcframework.outputs.cache-hit != 'true'
shell: bash
run: |
# ReactNativeHeaders.xcframework is pure-RN (the deps namespaces ship
# in the ReactNativeDependenciesHeaders sidecar built by the deps
# prebuild), but the headers-verify compile gates still need the deps
# headers on their include path (folly/glog/... reached from RN's
# public headers), so the deps artifact is staged here too.
tar -xzf /tmp/third-party/ReactNativeDependencies${{ matrix.flavor }}.xcframework.tar.gz -C /tmp/third-party/
mkdir -p packages/react-native/third-party/
mv /tmp/third-party/packages/react-native/third-party/ReactNativeDependencies.xcframework packages/react-native/third-party/ReactNativeDependencies.xcframework
- name: Setup Keychain
if: ${{ steps.restore-ios-xcframework.outputs.cache-hit != 'true' && env.REACT_ORG_CODE_SIGNING_P12_CERT != '' }}
uses: apple-actions/import-codesign-certs@v3 # https://github.com/marketplace/actions/import-code-signing-certificates
Expand All @@ -173,11 +191,24 @@ jobs:
run: |
cd packages/react-native
node scripts/ios-prebuild -c -f "${{ matrix.flavor }}" -i "React Org"
- name: Verify composed headers
if: steps.restore-ios-xcframework.outputs.cache-hit != 'true'
run: |
# Generator-time header gate: include-health ratchet, structural
# byte-compare of module maps/umbrellas against the spec render, and
# compile smokes (React module + every namespace module + the
# privileged-consumer/Expo fixtures). Catches consumer-facing header
# regressions here instead of in downstream builds.
cd packages/react-native
node scripts/ios-prebuild/headers-verify.js --flavor "${{ matrix.flavor }}"
- name: Compress and Rename XCFramework
if: steps.restore-ios-xcframework.outputs.cache-hit != 'true'
run: |
cd packages/react-native/.build/output/xcframeworks/${{matrix.flavor}}
tar -cz -f ../ReactCore${{matrix.flavor}}.xcframework.tar.gz React.xcframework
# Ship BOTH xcframeworks: React-Core-prebuilt's prepare_command flattens
# ReactNativeHeaders.xcframework's Headers (incl. module.modulemap) into the
# pod. Omitting it leaves consumers without React-Core-prebuilt/Headers/module.modulemap.
tar -cz -f ../ReactCore${{matrix.flavor}}.xcframework.tar.gz React.xcframework ReactNativeHeaders.xcframework
- name: Compress and Rename dSYM
if: steps.restore-ios-xcframework.outputs.cache-hit != 'true'
run: |
Expand All @@ -200,4 +231,4 @@ jobs:
path: |
packages/react-native/.build/output/xcframeworks/ReactCore${{matrix.flavor}}.xcframework.tar.gz
packages/react-native/.build/output/xcframeworks/ReactCore${{matrix.flavor}}.framework.dSYM.tar.gz
key: v2-ios-core-xcframework-${{ matrix.flavor }}-${{ hashFiles('packages/react-native/Package.swift', 'packages/react-native/scripts/ios-prebuild/*.js', 'packages/react-native/scripts/ios-prebuild.js', 'packages/react-native/React/**/*', 'packages/react-native/ReactCommon/**/*', 'packages/react-native/Libraries/**/*') }}
key: v3-ios-core-xcframework-${{ matrix.flavor }}-${{ hashFiles('packages/react-native/Package.swift', 'packages/react-native/scripts/ios-prebuild/*.js', 'packages/react-native/scripts/ios-prebuild.js', 'packages/react-native/React/**/*', 'packages/react-native/ReactCommon/**/*', 'packages/react-native/Libraries/**/*') }}
7 changes: 4 additions & 3 deletions .github/workflows/prebuild-ios-dependencies.yml
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ jobs:
with:
path: |
packages/react-native/third-party/
key: v3-ios-dependencies-xcframework-${{ matrix.flavor }}-${{ hashfiles('scripts/releases/ios-prebuild/configuration.js') }}
key: v5-ios-dependencies-xcframework-${{ matrix.flavor }}-${{ hashfiles('scripts/releases/ios-prebuild/configuration.js', 'scripts/releases/ios-prebuild/compose-framework.js', 'packages/react-native/scripts/ios-prebuild/headers-xcframework.js', 'packages/react-native/scripts/ios-prebuild/headers-spec.js') }}
# If cache hit, we already have our binary. We don't need to do anything.
- name: Yarn Install
if: steps.restore-xcframework.outputs.cache-hit != 'true'
Expand Down Expand Up @@ -164,7 +164,8 @@ jobs:
if: steps.restore-xcframework.outputs.cache-hit != 'true'
run: |
tar -cz -f packages/react-native/third-party/ReactNativeDependencies${{ matrix.flavor }}.xcframework.tar.gz \
packages/react-native/third-party/ReactNativeDependencies.xcframework
packages/react-native/third-party/ReactNativeDependencies.xcframework \
packages/react-native/third-party/ReactNativeDependenciesHeaders.xcframework
- name: Show Symbol folder content
if: steps.restore-xcframework.outputs.cache-hit != 'true'
run: ls -lR packages/react-native/third-party/Symbols
Expand Down Expand Up @@ -192,4 +193,4 @@ jobs:
path: |
packages/react-native/third-party/ReactNativeDependencies${{ matrix.flavor }}.xcframework.tar.gz
packages/react-native/third-party/ReactNativeDependencies${{ matrix.flavor }}.framework.dSYM.tar.gz
key: v3-ios-dependencies-xcframework-${{ matrix.flavor }}-${{ hashfiles('scripts/releases/ios-prebuild/configuration.js') }}
key: v5-ios-dependencies-xcframework-${{ matrix.flavor }}-${{ hashfiles('scripts/releases/ios-prebuild/configuration.js', 'scripts/releases/ios-prebuild/compose-framework.js', 'packages/react-native/scripts/ios-prebuild/headers-xcframework.js', 'packages/react-native/scripts/ios-prebuild/headers-spec.js') }}
10 changes: 8 additions & 2 deletions .github/workflows/test-all.yml
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,12 @@ jobs:
uses: ./.github/actions/test-ios-rntester
with:
use-frameworks: ${{ matrix.frameworks }}
# Consume the prebuilt artifacts in the dynamic-frameworks cells too:
# prebuilt + use_frameworks is the config of the 2026-07-03
# SocketRocket dual-copy regression, previously covered by no lane
# (source-built dynamic frameworks stay covered by
# test_ios_rntester_dynamic_frameworks).
use-prebuilds: true
flavor: ${{ matrix.flavor }}

test_e2e_ios_rntester:
Expand Down Expand Up @@ -471,9 +477,9 @@ jobs:
- name: Flow
shell: bash
run: yarn flow-check
- name: TypeScript
- name: TypeScript (legacy deep imports / manual types)
shell: bash
run: yarn test-typescript
run: yarn test-typescript-legacy

test_js:
runs-on: ubuntu-latest
Expand Down
10 changes: 5 additions & 5 deletions .yarnrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,16 @@ packageExtensions:
'@babel/plugin-syntax-flow': '^7.25.0'
'@react-native/core-cli-utils@*':
dependencies:
'metro': '^0.83.3'
'metro': '^0.87.0'
'@react-native/metro-babel-transformer@*':
dependencies:
'metro-babel-transformer': '^0.83.3'
'metro-babel-transformer': '^0.87.0'
'@react-native/compatibility-check@*':
dependencies:
'invariant': '^2.2.4'
'@react-native/tester@*':
dependencies:
'metro-config': '^0.83.3'
'metro-config': '^0.87.0'
'@react-native/eslint-plugin-monorepo@*':
dependencies:
'hermes-estree': '0.29.1'
Expand All @@ -39,8 +39,8 @@ packageExtensions:
'istanbul-lib-coverage': '^3.2.0'
'jest-docblock': '^29.7.0'
'jest-message-util': '^29.7.0'
'metro': '^0.84.3'
'metro-config': '^0.84.3'
'metro': '^0.87.0'
'metro-config': '^0.87.0'
'source-map': '^0.6.1'
'@typescript-eslint/type-utils@*':
dependencies:
Expand Down
3 changes: 3 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ module.exports = {
},
// [macOS
moduleNameMapper: {
// `resolver.js` strips `exports`; match this before the broad fork mapper.
'^react-native/setup-env$':
'<rootDir>/packages/react-native/src/setup-env.js',
// These mappers allow out-of-tree platforms tests to resolve RN imports
'^react-native/(.*)': '<rootDir>/packages/react-native/$1',
'^react-native$': '<rootDir>/packages/react-native/index.js',
Expand Down
13 changes: 7 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@
"test-release-local-clean": "node ./scripts/release-testing/test-release-local-clean.js",
"test-release-local": "node ./scripts/release-testing/test-release-local.js",
"test-ios": "./scripts/objc-test.sh test",
"test-typescript": "tsc -p packages/react-native/types/tsconfig.json",
"test-generated-typescript": "tsc -p packages/react-native/types_generated/tsconfig.test.json",
"test-typescript-legacy": "tsc -p packages/react-native/__typetests__/tsconfig.legacy.json",
"test-generated-typescript": "tsc -p packages/react-native/__typetests__/tsconfig.json && tsc -p packages/react-native/__typetests__/tsconfig.macos-public-api.json",
"test": "jest",
"fantom": "./scripts/fantom.sh",
"fantom-cli": "./scripts/fantom-cli.sh",
Expand All @@ -48,6 +48,7 @@
"workspaces": [
"packages/*",
"tools/*",
"packages/react-native-test-library/*",
"private/*",
"!packages/helloworld",
"!packages/hermes-inspector-msggen",
Expand Down Expand Up @@ -128,11 +129,11 @@
"markdownlint-cli2": "^0.22.0",
"markdownlint-rule-relative-links": "^3.0.0",
"memfs": "^4.38.2",
"metro": "^0.84.3",
"metro-babel-register": "^0.86.0",
"metro-config": "^0.84.3",
"metro": "^0.87.0",
"metro-babel-register": "^0.87.0",
"metro-config": "^0.87.0",
"metro-memory-fs": "^0.82.5",
"metro-transform-plugins": "^0.86.0",
"metro-transform-plugins": "^0.87.0",
"micromatch": "^4.0.4",
"node-fetch": "^2.2.0",
"nullthrows": "^1.1.1",
Expand Down
6 changes: 3 additions & 3 deletions packages/community-cli-plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@
"chalk": "^4.0.0",
"debug": "^4.4.0",
"invariant": "^2.2.4",
"metro": "^0.86.0",
"metro-config": "^0.86.0",
"metro": "^0.87.0",
"metro-config": "^0.87.0",
"semver": "^7.1.3"
},
"devDependencies": {
"metro-resolver": "^0.86.0"
"metro-resolver": "^0.87.0"
},
"peerDependencies": {
"@react-native-community/cli": "*",
Expand Down
25 changes: 17 additions & 8 deletions packages/community-cli-plugin/src/utils/loadMetroConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import type {InputConfigT} from 'metro-config';
import {CLIError} from './errors';
import {reactNativePlatformResolver} from './metroPlatformResolver';
import {loadConfig, resolveConfig} from 'metro';
import path from 'path';

const debug = require('debug')('ReactNative:CommunityCliPlugin');

Expand All @@ -25,7 +24,6 @@ export type {Config};

export type ConfigLoadingContext = Readonly<{
root: Config['root'],
reactNativePath: Config['reactNativePath'],
platforms: Config['platforms'],
...
}>;
Expand Down Expand Up @@ -61,16 +59,13 @@ function getCommunityCliDefaultConfig(
return {
resolver,
serializer: {
// We can include multiple copies of InitializeCore here because metro will
// We can include multiple copies of setup-env here because Metro will
// only add ones that are already part of the bundle
getModulesRunBeforeMainModule: () => [
require.resolve(
path.join(ctx.reactNativePath, 'Libraries/Core/InitializeCore'),
{paths: [ctx.root]},
),
resolveSetupEnv(ctx.root), // [macOS]
...outOfTreePlatforms.map(platform =>
require.resolve(
`${ctx.platforms[platform].npmPackageName}/Libraries/Core/InitializeCore`,
`${ctx.platforms[platform].npmPackageName}/setup-env`,
{paths: [ctx.root]},
),
),
Expand All @@ -79,6 +74,20 @@ function getCommunityCliDefaultConfig(
};
}

// [macOS] Main workspaces have only the fork; release apps can have both.
function resolveSetupEnv(projectRoot: string): string {
try {
return require.resolve('react-native/setup-env', {paths: [projectRoot]});
} catch (error) {
if (error.code !== 'MODULE_NOT_FOUND') {
throw error;
}
return require.resolve('react-native-macos/setup-env', {
paths: [projectRoot],
});
}
}

/**
* Load Metro config.
*
Expand Down
Loading
Loading