diff --git a/.changeset/config.json b/.changeset/config.json index d94a90f458c1..f23d33ad5ae2 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -1,12 +1,12 @@ { "$schema": "https://unpkg.com/@changesets/config@3.1.1/schema.json", "access": "public", - "baseBranch": "origin/main", + "baseBranch": "origin/0.84-stable", "bumpVersionsWithWorkspaceProtocolOnly": true, "changelog": "@changesets/cli/changelog", "commit": false, "fixed": [["react-native-macos", "@react-native-macos/virtualized-lists"]], - "ignore": ["react-native-macos", "@react-native/tester"], + "ignore": [], "privatePackages": { "version": false, "tag": false diff --git a/.github/actions/build-android/action.yml b/.github/actions/build-android/action.yml index 0aba8b032dfd..89ca4c49b284 100644 --- a/.github/actions/build-android/action.yml +++ b/.github/actions/build-android/action.yml @@ -16,10 +16,17 @@ runs: uses: ./.github/actions/setup-node - name: Install node dependencies uses: ./.github/actions/yarn-install + - name: Read current RNVersion + shell: bash + id: read-rn-version + run: | + echo "rn-version=$(jq -r '.version' packages/react-native/package.json)" >> $GITHUB_OUTPUT - name: Set React Native Version # We don't want to set the version for stable branches, because this has been # already set from the 'create release' commits on the release branch. - if: ${{ !endsWith(github.ref_name, '-stable') }} + # For testing RC.0, though, the version has not been set yet. In that case, we are on Stable branch and + # it is the only case when the version is still 1000.0.0 + if: ${{ !endsWith(github.ref_name, '-stable') || endsWith(github.ref_name, '-stable') && steps.read-rn-version.outputs.rn-version == '1000.0.0' }} shell: bash run: node ./scripts/releases/set-rn-artifacts-version.js --build-type ${{ inputs.release-type }} - name: Setup gradle diff --git a/.github/actions/setup-node/action.yml b/.github/actions/setup-node/action.yml index abb7e3f740c9..7b5aa82470a4 100644 --- a/.github/actions/setup-node/action.yml +++ b/.github/actions/setup-node/action.yml @@ -4,7 +4,7 @@ inputs: node-version: description: 'The node.js version to use' required: false - default: '22.11.0' + default: '22.14.0' runs: using: "composite" steps: diff --git a/.github/actions/test-ios-rntester/action.yml b/.github/actions/test-ios-rntester/action.yml index ae665e477116..5201b810de5c 100644 --- a/.github/actions/test-ios-rntester/action.yml +++ b/.github/actions/test-ios-rntester/action.yml @@ -6,7 +6,7 @@ inputs: default: 2.6.10 run-unit-tests: description: whether unit tests should run or not. - default: "true" + default: false flavor: description: The flavor of the build. Must be one of "Debug", "Release". default: Debug diff --git a/.github/scripts/__tests__/__fixtures__/resolve-hermes.cjs b/.github/scripts/__tests__/__fixtures__/resolve-hermes.cjs index be2320fd112a..4a5c05761d44 100644 --- a/.github/scripts/__tests__/__fixtures__/resolve-hermes.cjs +++ b/.github/scripts/__tests__/__fixtures__/resolve-hermes.cjs @@ -54,6 +54,14 @@ const propertiesPath = path.resolve( ); const readFileSync = fs.readFileSync; fs.readFileSync = function (file, ...args) { + if (process.env.HERMES_TEST_REFS != null) { + const refs = JSON.parse(process.env.HERMES_TEST_REFS); + for (const [tagFile, ref] of Object.entries(refs)) { + if (file === path.resolve(propertiesPath, '../..', tagFile)) { + return ref; + } + } + } if (file === propertiesPath && process.env.HERMES_TEST_PROPERTIES != null) { if (process.env.HERMES_TEST_PROPERTIES === 'MISSING') { throw Object.assign(new Error(`ENOENT: ${propertiesPath}`), { diff --git a/.github/scripts/__tests__/resolve-hermes-test.js b/.github/scripts/__tests__/resolve-hermes-test.js index 87e4182686c6..9b87f5d6de0a 100644 --- a/.github/scripts/__tests__/resolve-hermes-test.js +++ b/.github/scripts/__tests__/resolve-hermes-test.js @@ -19,7 +19,8 @@ const { } = require('../../../packages/react-native/scripts/ios-prebuild/hermes-version'); const root = path.resolve(__dirname, '../../..'); -const {version: v1Version} = readHermesMetadata('legacy-default', '1'); +const {version: v0Version} = readHermesMetadata('v1-default', '0'); +const {version: v1Version} = readHermesMetadata('v1-default', '1'); const script = path.join(root, '.github/scripts/resolve-hermes.mts'); const preload = path.join(__dirname, '__fixtures__/resolve-hermes.cjs'); const sourceCommit = '1234567890abcdef1234567890abcdef12345678'; @@ -43,6 +44,7 @@ function run(command, overrides = {}) { 'HERMES_TEST_DOWNLOAD', 'HERMES_TEST_COMMIT', 'HERMES_TEST_SOURCE_ERROR', + 'HERMES_TEST_REFS', ]) { delete env[key]; } @@ -75,9 +77,11 @@ function run(command, overrides = {}) { } test.each([ - [undefined, '123.4.56', 'HERMES_VERSION_NAME', 'Debug'], - ['0', '123.4.56', 'HERMES_VERSION_NAME', 'Debug'], + [undefined, v1Version, 'HERMES_V1_VERSION_NAME', 'Debug'], + ['0', v0Version, 'HERMES_VERSION_NAME', 'Debug'], ['1', v1Version, 'HERMES_V1_VERSION_NAME', 'Release'], + ['', v1Version, 'HERMES_V1_VERSION_NAME', 'Debug'], + ['true', v1Version, 'HERMES_V1_VERSION_NAME', 'Debug'], ])( 'CI downloads flag %s with the selected key and version', (flag, version, key, flavor) => { @@ -112,11 +116,30 @@ test.each([ }, ); -test('CI snapshot fallback uses the five-argument URL helper contract', () => { +test.each([ + [undefined, '250829098.0.9'], + ['0', '0.15.1'], + ['1', '250829098.0.9'], +])('CI downloads checked-in stable metadata with flag %s', (flag, version) => { + const result = run(['download-hermes'], { + ...(flag == null ? {} : {RCT_HERMES_V1_ENABLED: flag}), + HERMES_TEST_DOWNLOAD: 'release', + }); + expect(result.status).toBe(0); + expect(result.output).toContain(`version=${version}\n`); + expect(result.output).toMatch(/^tarball=.+$/m); + expect(result.urls).toEqual([ + `https://central.sonatype.com/repository/maven-snapshots/com/facebook/hermes/hermes-ios/${version}-SNAPSHOT/maven-metadata.xml`, + `https://repo1.maven.org/maven2/com/facebook/hermes/hermes-ios/${version}/hermes-ios-${version}-hermes-ios-debug.tar.gz`, + ]); + expect(result.calls.source).toEqual([]); +}); + +test('CI snapshot fallback uses the five-argument Hermes URL helper contract', () => { const version = '123.4.56'; const result = run(['download-hermes'], { HERMES_TEST_DOWNLOAD: 'snapshot', - HERMES_TEST_PROPERTIES: `HERMES_VERSION_NAME=${version}`, + HERMES_TEST_PROPERTIES: `HERMES_V1_VERSION_NAME=${version}`, }); expect(result.status).toBe(0); expect(result.output).toContain(`version=${version}\n`); @@ -135,7 +158,7 @@ test('CI snapshot fallback uses the five-argument URL helper contract', () => { test('CI can still select source when valid pinned artifacts are unavailable', () => { const result = run(['download-hermes'], { - HERMES_TEST_PROPERTIES: 'HERMES_VERSION_NAME=123.4.56', + HERMES_TEST_PROPERTIES: 'HERMES_V1_VERSION_NAME=123.4.56', }); expect(result.status).toBe(0); expect(result.output).toBe(''); @@ -145,12 +168,16 @@ test('CI can still select source when valid pinned artifacts are unavailable', ( }); const invalidMetadata = [ - ['', 'Expected one exact HERMES_VERSION_NAME'], + ['', 'Expected one exact HERMES_V1_VERSION_NAME'], ['UNREADABLE', 'EACCES'], - ['HERMES_VERSION_NAME=^1.2.3', 'Expected one exact HERMES_VERSION_NAME'], [ - 'HERMES_VERSION_NAME=1.2.3\nHERMES_VERSION_NAME=1.2.3', - 'Expected one exact HERMES_VERSION_NAME', + 'HERMES_V1_VERSION_NAME=^1.2.3', + 'Expected one exact HERMES_V1_VERSION_NAME', + ], + ['HERMES_VERSION_NAME=1.2.3', 'Expected one exact HERMES_V1_VERSION_NAME'], + [ + 'HERMES_V1_VERSION_NAME=1.2.3\nHERMES_V1_VERSION_NAME=1.2.3', + 'Expected one exact HERMES_V1_VERSION_NAME', ], ]; @@ -193,17 +220,17 @@ test('CI selects source without a download when version.properties is missing', }); test.each([ - [undefined, 'HERMES_VERSION_NAME', undefined], - ['0', 'HERMES_VERSION_NAME', undefined], - [ - '1', - 'HERMES_V1_VERSION_NAME', - 'HERMES_VERSION_NAME=123.4.56\nHERMES_V1_VERSION_NAME=1000.0.0', - ], -])('CI selected sentinel for flag %s', (flag, key, properties) => { + [undefined, 'HERMES_V1_VERSION_NAME'], + ['0', 'HERMES_VERSION_NAME'], + ['1', 'HERMES_V1_VERSION_NAME'], + ['', 'HERMES_V1_VERSION_NAME'], + ['true', 'HERMES_V1_VERSION_NAME'], +])('CI selected sentinel for flag %s', (flag, key) => { const overrides = { ...(flag == null ? {} : {RCT_HERMES_V1_ENABLED: flag}), - ...(properties == null ? {} : {HERMES_TEST_PROPERTIES: properties}), + HERMES_TEST_PROPERTIES: + `${key}=1000.0.0\n` + + `${key === 'HERMES_VERSION_NAME' ? 'HERMES_V1_VERSION_NAME' : 'HERMES_VERSION_NAME'}=123.4.56`, }; const download = run(['download-hermes'], overrides); @@ -224,7 +251,10 @@ test.each([ test('CI source resolution uses the current helper SHA for the cache output', () => { const commit = 'abcdef1234567890abcdef1234567890abcdef12'; - const result = run(['resolve-commit'], {HERMES_TEST_COMMIT: commit}); + const result = run(['resolve-commit'], { + HERMES_TEST_COMMIT: commit, + HERMES_TEST_PROPERTIES: 'HERMES_V1_VERSION_NAME=1000.0.0', + }); expect(result.status).toBe(0); expect(result.output).toBe(`hermes-commit=${commit}\n`); expect(result.calls).toEqual({source: [[]], nightly: []}); @@ -232,6 +262,7 @@ test('CI source resolution uses the current helper SHA for the cache output', () test('CI fails source resolution without falling back to a tag', () => { const result = run(['resolve-commit'], { + HERMES_TEST_PROPERTIES: 'HERMES_V1_VERSION_NAME=1000.0.0', HERMES_TEST_SOURCE_ERROR: 'Cannot resolve merge-base timestamp', }); expect(result.status).toBe(1); @@ -241,15 +272,15 @@ test('CI fails source resolution without falling back to a tag', () => { expect(result.calls).toEqual({source: [[]], nightly: []}); }); -test('CI resolve-commit emits the checked-in V1 SHA for concrete metadata', () => { +test('CI resolve-commit emits the checked-in stable V1 tag', () => { const ref = fs .readFileSync( path.join(root, 'packages/react-native/sdks/.hermesv1version'), 'utf8', ) .trim(); - expect(ref).toMatch(/^[0-9a-fA-F]{40}$/); - expect(v1Version).not.toBe('1000.0.0'); + expect(ref).toBe('hermes-v250829098.0.9'); + expect(v1Version).toBe('250829098.0.9'); const result = run(['resolve-commit'], {RCT_HERMES_V1_ENABLED: '1'}); expect(result.status).toBe(0); @@ -259,17 +290,51 @@ test('CI resolve-commit emits the checked-in V1 SHA for concrete metadata', () = expect(result.calls).toEqual({source: [], nightly: []}); }); +describe.each(['release/custom-hermes', sourceCommit])('source ref %s', ref => { + test.each([ + [undefined, '.hermesv1version'], + ['0', '.hermesversion'], + ['1', '.hermesv1version'], + ['', '.hermesv1version'], + ['true', '.hermesv1version'], + ])('CI reads the selected file for flag %s', (flag, tagFile) => { + const result = run(['resolve-commit'], { + ...(flag == null ? {} : {RCT_HERMES_V1_ENABLED: flag}), + HERMES_TEST_PROPERTIES: + 'HERMES_VERSION_NAME=123.4.56\nHERMES_V1_VERSION_NAME=234.5.67', + HERMES_TEST_REFS: JSON.stringify({ + '.hermesversion': 'unselected-legacy-ref', + '.hermesv1version': 'unselected-v1-ref', + [tagFile]: ` ${ref}\n`, + }), + }); + expect(result.status).toBe(0); + expect(result.output).toBe(`hermes-commit=${ref}\n`); + expect(result.urls).toEqual([]); + expect(result.calls).toEqual({source: [], nightly: []}); + }); +}); + test.each([ - [undefined, '.hermesversion', 'MISSING'], + [undefined, '.hermesv1version', 'MISSING'], ['0', '.hermesversion', 'MISSING'], ['1', '.hermesv1version', 'MISSING'], - [undefined, '.hermesversion', 'HERMES_VERSION_NAME=123.4.56'], + [undefined, '.hermesv1version', 'HERMES_V1_VERSION_NAME=123.4.56'], + [ + undefined, + '.hermesv1version', + 'HERMES_VERSION_NAME=1000.0.0\nHERMES_V1_VERSION_NAME=123.4.56', + ], [ '0', '.hermesversion', 'HERMES_VERSION_NAME=123.4.56\nHERMES_V1_VERSION_NAME=1000.0.0', ], + [undefined, '.hermesv1version', undefined], + ['0', '.hermesversion', undefined], ['1', '.hermesv1version', undefined], + ['', '.hermesv1version', undefined], + ['true', '.hermesv1version', undefined], ])( 'CI resolve-commit reads flag %s tag %s independently of metadata %s', (flag, tagFile, properties) => { diff --git a/.github/scripts/resolve-hermes.mts b/.github/scripts/resolve-hermes.mts index 206039893e60..afc79516e1b1 100644 --- a/.github/scripts/resolve-hermes.mts +++ b/.github/scripts/resolve-hermes.mts @@ -40,10 +40,11 @@ function setActionOutput(key: string, value: string) { * * Uses the same version key and validation as the local prebuild script. * A missing file permits a source build; malformed metadata must fail CI. + * Selects V1 unless RCT_HERMES_V1_ENABLED=0, matching React Native 0.84. */ function resolveHermesArtifactVersion(): string | null { try { - const {version, versionKey} = readHermesMetadata('legacy-default'); + const {version, versionKey} = readHermesMetadata('v1-default'); echo(`Using ${versionKey}=${version}`); return version; } catch (error: any) { @@ -56,12 +57,12 @@ function resolveHermesArtifactVersion(): string | null { /** * Reads the pinned Hermes ref from packages/react-native/sdks/.hermesversion - * (or .hermesv1version when RCT_HERMES_V1_ENABLED=1). The value is a tag or commit in + * (or .hermesv1version unless V1 is explicitly disabled). The value is a tag or commit in * facebook/hermes. Returns null if the file is missing or empty. */ function resolveHermesTag(): string | null { const {tagFile} = selectHermesMetadata( - 'legacy-default', process.env.RCT_HERMES_V1_ENABLED, + 'v1-default', process.env.RCT_HERMES_V1_ENABLED, ); const tagPath = path.resolve( import.meta.dirname!, '..', '..', diff --git a/.github/workflows/bump-podfile-lock.yml b/.github/workflows/bump-podfile-lock.yml index bdf3edbbfe7b..46ef02ac0b4e 100644 --- a/.github/workflows/bump-podfile-lock.yml +++ b/.github/workflows/bump-podfile-lock.yml @@ -37,8 +37,9 @@ jobs: - name: Bump podfile.lock run: | cd packages/rn-tester + rm Podfile.lock bundle install - bundle exec pod update hermes-engine --no-repo-update + bundle exec pod install - name: Commit changes run: | git add packages/rn-tester/Podfile.lock diff --git a/.github/workflows/cache-reaper.yml b/.github/workflows/cache-reaper.yml index 59feda574c19..190e4d376459 100644 --- a/.github/workflows/cache-reaper.yml +++ b/.github/workflows/cache-reaper.yml @@ -8,7 +8,7 @@ on: jobs: cache-cleaner: - if: github.repository == 'facebook/react-native' + if: github.repository == 'react/react-native' runs-on: ubuntu-latest env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/check-for-reproducer.yml b/.github/workflows/check-for-reproducer.yml index e986259a3a23..72b122a905fb 100644 --- a/.github/workflows/check-for-reproducer.yml +++ b/.github/workflows/check-for-reproducer.yml @@ -8,7 +8,7 @@ jobs: check-for-reproducer: runs-on: ubuntu-latest if: | - github.repository == 'facebook/react-native' && github.event.issue.pull_request == null && github.event.issue.state == 'open' && !contains(github.event.issue.labels.*.name, ':open_umbrella: Umbrella') + github.repository == 'react/react-native' && github.event.issue.pull_request == null && github.event.issue.state == 'open' && !contains(github.event.issue.labels.*.name, ':open_umbrella: Umbrella') steps: - uses: actions/checkout@v6 - uses: actions/github-script@v8 diff --git a/.github/workflows/close-pr.yml b/.github/workflows/close-pr.yml index 5d0489f170b7..6ffd382347d9 100644 --- a/.github/workflows/close-pr.yml +++ b/.github/workflows/close-pr.yml @@ -9,7 +9,7 @@ permissions: jobs: comment-and-label: runs-on: ubuntu-latest - if: github.repository == 'facebook/react-native' + if: github.repository == 'react/react-native' steps: - uses: actions/github-script@v8 with: diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index 464e9eb3f86c..dfce6b95e154 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -19,7 +19,7 @@ on: jobs: create_release: - if: github.repository == 'facebook/react-native' + if: github.repository == 'react/react-native' runs-on: ubuntu-latest steps: - name: Checkout diff --git a/.github/workflows/danger-pr.yml b/.github/workflows/danger-pr.yml index ce41f6f602cd..2eb4836b4cf7 100644 --- a/.github/workflows/danger-pr.yml +++ b/.github/workflows/danger-pr.yml @@ -15,7 +15,7 @@ permissions: jobs: danger: runs-on: ubuntu-latest - if: github.repository == 'facebook/react-native' + if: github.repository == 'react/react-native' steps: - name: Check out PR branch uses: actions/checkout@v6 diff --git a/.github/workflows/monitor-new-issues.yml b/.github/workflows/monitor-new-issues.yml index 36abe0bb4cfa..858a60c2b7ba 100644 --- a/.github/workflows/monitor-new-issues.yml +++ b/.github/workflows/monitor-new-issues.yml @@ -12,7 +12,7 @@ on: jobs: monitor-issues: runs-on: ubuntu-latest - if: github.repository == 'facebook/react-native' + if: github.repository == 'react/react-native' steps: - name: Checkout uses: actions/checkout@v6 @@ -34,7 +34,7 @@ jobs: git_secret: ${{ secrets.GITHUB_TOKEN }} notifier: "discord" fetch_data_interval: 6 - repo_owner: "facebook" + repo_owner: "react" repo_name: "react-native" discord_webhook_url: "${{ secrets.DISCORD_WEBHOOK_URL }}" discord_id_type: "user" diff --git a/.github/workflows/needs-attention.yml b/.github/workflows/needs-attention.yml index 0da88efd6d24..bd28e261fe97 100644 --- a/.github/workflows/needs-attention.yml +++ b/.github/workflows/needs-attention.yml @@ -14,7 +14,7 @@ jobs: issues: write # for react-native-community/needs-attention to label issues name: Apply Needs Attention Label runs-on: ubuntu-latest - if: github.repository == 'facebook/react-native' + if: github.repository == 'react/react-native' steps: - uses: actions/checkout@v6 - name: Apply Needs Attention Label diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 420439705e14..a955e32b370d 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -9,7 +9,7 @@ on: jobs: set_release_type: runs-on: ubuntu-latest - if: github.repository == 'facebook/react-native' + if: github.repository == 'react/react-native' outputs: RELEASE_TYPE: ${{ steps.set_release_type.outputs.RELEASE_TYPE }} env: @@ -22,7 +22,7 @@ jobs: echo "RELEASE_TYPE=nightly" >> $GITHUB_OUTPUT prebuild_apple_dependencies: - if: github.repository == 'facebook/react-native' + if: github.repository == 'react/react-native' uses: ./.github/workflows/prebuild-ios-dependencies.yml secrets: inherit @@ -35,11 +35,11 @@ jobs: needs: [prebuild_apple_dependencies] build_android: - runs-on: 8-core-ubuntu - if: github.repository == 'facebook/react-native' + runs-on: ubuntu-latest + if: github.repository == 'react/react-native' needs: [set_release_type] container: - image: reactnativecommunity/react-native-android:latest + image: reactnativecommunity/react-native-android:v20.0 env: TERM: "dumb" GRADLE_OPTS: "-Dorg.gradle.daemon=false" @@ -57,7 +57,7 @@ jobs: gradle-cache-encryption-key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }} build_npm_package: - runs-on: 8-core-ubuntu + runs-on: ubuntu-latest needs: [ set_release_type, @@ -66,7 +66,7 @@ jobs: prebuild_react_native_core, ] container: - image: reactnativecommunity/react-native-android:latest + image: reactnativecommunity/react-native-android:v20.0 env: TERM: "dumb" GRADLE_OPTS: "-Dorg.gradle.daemon=false" diff --git a/.github/workflows/on-issue-labeled.yml b/.github/workflows/on-issue-labeled.yml index 7500d9ce3d3b..b59f9afdbdfa 100644 --- a/.github/workflows/on-issue-labeled.yml +++ b/.github/workflows/on-issue-labeled.yml @@ -13,7 +13,7 @@ jobs: # then invokes actOnLabel to react to any added labels triage-issue: runs-on: ubuntu-latest - if: "${{ github.repository == 'facebook/react-native' && contains(github.event.label.name, 'Needs: Triage :mag:') }}" + if: "${{ github.repository == 'react/react-native' && contains(github.event.label.name, 'Needs: Triage :mag:') }}" steps: - name: Checkout code uses: actions/checkout@v6 @@ -49,7 +49,7 @@ jobs: # Reacts to the label that triggered this workflow (added manually or via other workflows) act-on-label: runs-on: ubuntu-latest - if: github.repository == 'facebook/react-native' + if: github.repository == 'react/react-native' steps: - uses: actions/checkout@v6 - uses: actions/github-script@v8 diff --git a/.github/workflows/prebuild-ios-core.yml b/.github/workflows/prebuild-ios-core.yml index aff263a75bdc..1eeccfeaf501 100644 --- a/.github/workflows/prebuild-ios-core.yml +++ b/.github/workflows/prebuild-ios-core.yml @@ -50,9 +50,11 @@ jobs: shell: bash run: | if [ "${{ inputs.use-hermes-nightly }}" == "true" ]; then - HERMES_VERSION="nightly" + # We are not publishing nightly versions of Hermes V1 yet. + # For now, we can use the latest version of Hermes V1 published on maven and npm. + HERMES_VERSION="latest-v1" else - HERMES_VERSION=$(sed -n 's/^HERMES_VERSION_NAME=//p' packages/react-native/sdks/hermes-engine/version.properties) + HERMES_VERSION=$(sed -n 's/^HERMES_V1_VERSION_NAME=//p' packages/react-native/sdks/hermes-engine/version.properties) fi echo "Using Hermes version: $HERMES_VERSION" echo "HERMES_VERSION=$HERMES_VERSION" >> $GITHUB_ENV @@ -144,8 +146,6 @@ jobs: - name: Setup xcode if: steps.restore-ios-xcframework.outputs.cache-hit != 'true' uses: ./.github/actions/setup-xcode - with: - xcode-version: '16.2.0' - name: Yarn Install if: steps.restore-ios-xcframework.outputs.cache-hit != 'true' uses: ./.github/actions/yarn-install diff --git a/.github/workflows/prebuild-ios-dependencies.yml b/.github/workflows/prebuild-ios-dependencies.yml index 275b3b8bec53..3152cb98be48 100644 --- a/.github/workflows/prebuild-ios-dependencies.yml +++ b/.github/workflows/prebuild-ios-dependencies.yml @@ -124,8 +124,6 @@ jobs: uses: ./.github/actions/setup-node - name: Setup xcode uses: ./.github/actions/setup-xcode - with: - xcode-version: '16.1' - name: Restore XCFramework id: restore-xcframework uses: actions/cache/restore@v5 diff --git a/.github/workflows/publish-bumped-packages.yml b/.github/workflows/publish-bumped-packages.yml index cf0b69b8c354..612a86917631 100644 --- a/.github/workflows/publish-bumped-packages.yml +++ b/.github/workflows/publish-bumped-packages.yml @@ -9,7 +9,7 @@ on: jobs: publish_bumped_packages: runs-on: ubuntu-latest - if: github.repository == 'facebook/react-native' + if: github.repository == 'react/react-native' env: GHA_NPM_TOKEN: ${{ secrets.GHA_NPM_TOKEN }} steps: diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index 99e3b94fc9b4..9da2a6ed1bc8 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -7,7 +7,7 @@ on: jobs: set_release_type: runs-on: ubuntu-latest - if: github.repository == 'facebook/react-native' + if: github.repository == 'react/react-native' outputs: RELEASE_TYPE: ${{ steps.set_release_type.outputs.RELEASE_TYPE }} env: @@ -21,7 +21,7 @@ jobs: set_hermes_versions: runs-on: ubuntu-latest - if: github.repository == 'facebook/react-native' + if: github.repository == 'react/react-native' outputs: HERMES_VERSION: ${{ steps.set_hermes_versions.outputs.HERMES_VERSION }} HERMES_V1_VERSION: ${{ steps.set_hermes_versions.outputs.HERMES_V1_VERSION }} @@ -42,7 +42,7 @@ jobs: echo "HERMES_V1_VERSION=${{ steps.set_hermes_versions.outputs.HERMES_V1_VERSION }}" prebuild_apple_dependencies: - if: github.repository == 'facebook/react-native' + if: github.repository == 'react/react-native' uses: ./.github/workflows/prebuild-ios-dependencies.yml secrets: inherit @@ -52,7 +52,7 @@ jobs: needs: [prebuild_apple_dependencies] build_npm_package: - runs-on: 8-core-ubuntu + runs-on: ubuntu-latest needs: [ set_release_type, @@ -60,7 +60,7 @@ jobs: prebuild_react_native_core, ] container: - image: reactnativecommunity/react-native-android:latest + image: reactnativecommunity/react-native-android:v20.0 env: TERM: "dumb" GRADLE_OPTS: "-Dorg.gradle.daemon=false" diff --git a/.github/workflows/retry-workflow.yml b/.github/workflows/retry-workflow.yml index d943d657d825..d3da630924d7 100644 --- a/.github/workflows/retry-workflow.yml +++ b/.github/workflows/retry-workflow.yml @@ -9,7 +9,7 @@ on: jobs: rerun: runs-on: ubuntu-latest - if: github.repository == 'facebook/react-native' + if: github.repository == 'react/react-native' steps: - name: rerun ${{ inputs.run_id }} env: diff --git a/.github/workflows/stale-bot.yml b/.github/workflows/stale-bot.yml index f4c2fa8d353f..de04b05601f1 100644 --- a/.github/workflows/stale-bot.yml +++ b/.github/workflows/stale-bot.yml @@ -5,7 +5,7 @@ on: jobs: stale: runs-on: ubuntu-latest - if: github.repository == 'facebook/react-native' + if: github.repository == 'react/react-native' permissions: issues: write pull-requests: write @@ -22,7 +22,7 @@ jobs: exempt-pr-labels: 'Help Wanted :octocat:, Never gets stale' stale-asc: runs-on: ubuntu-latest - if: github.repository == 'facebook/react-native' + if: github.repository == 'react/react-native' permissions: issues: write pull-requests: write @@ -40,7 +40,7 @@ jobs: exempt-pr-labels: 'Help Wanted :octocat:, Never gets stale' stale-needs-author-feedback: runs-on: ubuntu-latest - if: github.repository == 'facebook/react-native' + if: github.repository == 'react/react-native' permissions: issues: write pull-requests: write @@ -58,7 +58,7 @@ jobs: exempt-pr-labels: "Help Wanted :octocat:, Never gets stale" stale-needs-author-feedback-asc: runs-on: ubuntu-latest - if: github.repository == 'facebook/react-native' + if: github.repository == 'react/react-native' permissions: issues: write pull-requests: write diff --git a/.github/workflows/test-all.yml b/.github/workflows/test-all.yml index 2e237ce6526d..dacc1d61cc87 100644 --- a/.github/workflows/test-all.yml +++ b/.github/workflows/test-all.yml @@ -11,7 +11,7 @@ on: jobs: set_release_type: runs-on: ubuntu-latest - if: github.repository == 'facebook/react-native' + if: github.repository == 'react/react-native' outputs: RELEASE_TYPE: ${{ steps.set_release_type.outputs.RELEASE_TYPE }} env: @@ -34,7 +34,7 @@ jobs: echo "Should I run E2E tests? ${{ inputs.run-e2e-tests }}" prebuild_apple_dependencies: - if: github.repository == 'facebook/react-native' + if: github.repository == 'react/react-native' uses: ./.github/workflows/prebuild-ios-dependencies.yml secrets: inherit @@ -195,7 +195,7 @@ jobs: export RCT_USE_LOCAL_RN_DEP=/tmp/third-party/ReactNativeDependencies${{ matrix.flavor }}.xcframework.tar.gz # Disable prebuilds for now, as they are causing issues with E2E tests for 0.82-stable branch - # export RCT_TESTONLY_RNCORE_TARBALL_PATH="/tmp/ReactCore/ReactCore${{ matrix.flavor }}.xcframework.tar.gz" + export RCT_TESTONLY_RNCORE_TARBALL_PATH="/tmp/ReactCore/ReactCore${{ matrix.flavor }}.xcframework.tar.gz" RCT_NEW_ARCH_ENABLED=$NEW_ARCH_ENABLED bundle exec pod install xcodebuild \ @@ -215,7 +215,7 @@ jobs: working-directory: /tmp/RNTestProject test_e2e_android_templateapp: - runs-on: 4-core-ubuntu + runs-on: ubuntu-latest needs: build_npm_package strategy: fail-fast: false @@ -283,10 +283,10 @@ jobs: working-directory: /tmp/RNTestProject run_fantom_tests: - runs-on: 8-core-ubuntu + runs-on: ubuntu-latest needs: [set_release_type] container: - image: reactnativecommunity/react-native-android:latest + image: reactnativecommunity/react-native-android:v20.0 env: TERM: "dumb" GRADLE_OPTS: "-Dorg.gradle.daemon=false" @@ -302,10 +302,10 @@ jobs: gradle-cache-encryption-key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }} build_android: - runs-on: 8-core-ubuntu + runs-on: ubuntu-latest needs: [set_release_type] container: - image: reactnativecommunity/react-native-android:latest + image: reactnativecommunity/react-native-android:v20.0 env: TERM: "dumb" GRADLE_OPTS: "-Dorg.gradle.daemon=false" @@ -321,7 +321,7 @@ jobs: gradle-cache-encryption-key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }} test_e2e_android_rntester: - runs-on: 4-core-ubuntu + runs-on: ubuntu-latest needs: [build_android] strategy: fail-fast: false @@ -351,7 +351,7 @@ jobs: flavor: ${{ matrix.flavor }} build_npm_package: - runs-on: 8-core-ubuntu + runs-on: ubuntu-latest needs: [ set_release_type, @@ -360,7 +360,7 @@ jobs: prebuild_react_native_core, ] container: - image: reactnativecommunity/react-native-android:latest + image: reactnativecommunity/react-native-android:v20.0 env: TERM: "dumb" GRADLE_OPTS: "-Dorg.gradle.daemon=false" @@ -374,10 +374,10 @@ jobs: gradle-cache-encryption-key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }} test_android_helloworld: - runs-on: 4-core-ubuntu + runs-on: ubuntu-latest needs: build_npm_package container: - image: reactnativecommunity/react-native-android:latest + image: reactnativecommunity/react-native-android:v20.0 env: # Set the encoding to resolve a known character encoding issue with decompressing tar.gz files in conatiners # via Gradle: https://github.com/gradle/gradle/issues/23391#issuecomment-1878979127 @@ -475,11 +475,11 @@ jobs: test_js: runs-on: ubuntu-latest - if: github.repository == 'facebook/react-native' + if: github.repository == 'react/react-native' strategy: fail-fast: false matrix: - node-version: ["24", "22.11.0"] + node-version: ["24", "22", "20.19.4"] steps: - name: Checkout uses: actions/checkout@v6 @@ -490,7 +490,7 @@ jobs: lint: runs-on: ubuntu-latest - if: github.repository == 'facebook/react-native' + if: github.repository == 'react/react-native' env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: diff --git a/.github/workflows/test-hermes-v1-android.yml b/.github/workflows/test-hermes-v1-android.yml index 1c7b7eedf12b..e30421f3d3c7 100644 --- a/.github/workflows/test-hermes-v1-android.yml +++ b/.github/workflows/test-hermes-v1-android.yml @@ -12,7 +12,7 @@ on: jobs: test-hermes-v1-android: name: Test Hermes V1 on Android - runs-on: 4-core-ubuntu + runs-on: ubuntu-latest strategy: matrix: flavor: [debug, release] diff --git a/.github/workflows/test-hermes-v1-ios.yml b/.github/workflows/test-hermes-v1-ios.yml index 44437ebb36a2..bdafd9181b81 100644 --- a/.github/workflows/test-hermes-v1-ios.yml +++ b/.github/workflows/test-hermes-v1-ios.yml @@ -40,8 +40,6 @@ jobs: - name: Setup xcode uses: maxim-lobanov/setup-xcode@v1 - with: - xcode-version: 16.4.0 - name: Build iOS with retry uses: nick-fields/retry@v3 diff --git a/.github/workflows/test-hermes-v1.yml b/.github/workflows/test-hermes-v1.yml index d11e444e5ff6..8afa7cbc6d49 100644 --- a/.github/workflows/test-hermes-v1.yml +++ b/.github/workflows/test-hermes-v1.yml @@ -14,7 +14,7 @@ concurrency: jobs: check-nightly: runs-on: ubuntu-latest - if: github.repository == 'facebook/react-native' + if: github.repository == 'react/react-native' steps: - name: Checkout uses: actions/checkout@v6 diff --git a/.github/workflows/validate-dotslash-artifacts.yml b/.github/workflows/validate-dotslash-artifacts.yml index 1526ee0e9cfd..10b4e5842252 100644 --- a/.github/workflows/validate-dotslash-artifacts.yml +++ b/.github/workflows/validate-dotslash-artifacts.yml @@ -27,7 +27,7 @@ on: jobs: validate-dotslash-artifacts: runs-on: ubuntu-latest - if: github.repository == 'facebook/react-native' + if: github.repository == 'react/react-native' steps: - name: Checkout repository uses: actions/checkout@v6 diff --git a/build.gradle.kts b/build.gradle.kts index 657f109c454c..b6e1ee36b6c1 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -118,8 +118,7 @@ if (project.findProperty("react.internal.useHermesStable")?.toString()?.toBoolea val hermesVersionPropertiesFile = File("./packages/react-native/sdks/hermes-engine/version.properties") hermesVersionPropertiesFile.inputStream().use { hermesVersions.load(it) } - val selectedHermesVersion = hermesVersions["HERMES_VERSION_NAME"] as String - + val selectedHermesVersion = hermesVersions["HERMES_V1_VERSION_NAME"] as String hermesSubstitution = selectedHermesVersion to "Users opted to use stable hermes release" } else if ( project.findProperty("react.internal.useHermesNightly")?.toString()?.toBoolean() == true diff --git a/gradle.properties b/gradle.properties index f494dd4fe8c1..3e7127618758 100644 --- a/gradle.properties +++ b/gradle.properties @@ -19,11 +19,11 @@ reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 # Controls whether to use Hermes from stable builds. This will force hermes version # set in the sdks/hermes-engine/version.properties file to be used. This has a higher # priority than react.internal.useHermesNightly. -react.internal.useHermesStable=false +react.internal.useHermesStable=true # Controls whether to use Hermes from nightly builds. This will speed up builds # but should NOT be turned on for CI or release builds. -react.internal.useHermesNightly=true +react.internal.useHermesNightly=false # Controls whether to use Hermes 1.0. Clean and rebuild when changing. -hermesV1Enabled=false +hermesV1Enabled=true diff --git a/packages/assets/package.json b/packages/assets/package.json index 0f2a3a200703..109e21c99291 100644 --- a/packages/assets/package.json +++ b/packages/assets/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/assets-registry", - "version": "0.84.0-main", + "version": "0.84.1", "private": true, "description": "Asset support code for React Native.", "license": "MIT", diff --git a/packages/babel-plugin-codegen/package.json b/packages/babel-plugin-codegen/package.json index 65d670b61e13..527681a3f591 100644 --- a/packages/babel-plugin-codegen/package.json +++ b/packages/babel-plugin-codegen/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/babel-plugin-codegen", - "version": "0.84.0-main", + "version": "0.84.1", "private": true, "description": "Babel plugin to generate native module and view manager code for React Native.", "license": "MIT", diff --git a/packages/community-cli-plugin/package.json b/packages/community-cli-plugin/package.json index bbe55a190fc8..0a2a9d783a13 100644 --- a/packages/community-cli-plugin/package.json +++ b/packages/community-cli-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/community-cli-plugin", - "version": "0.84.0-main", + "version": "0.84.1", "private": true, "description": "Core CLI commands for React Native", "keywords": [ diff --git a/packages/community-cli-plugin/src/commands/bundle/assetPathUtils.js b/packages/community-cli-plugin/src/commands/bundle/assetPathUtils.js index ced3d4b92a89..1037e200a6ce 100644 --- a/packages/community-cli-plugin/src/commands/bundle/assetPathUtils.js +++ b/packages/community-cli-plugin/src/commands/bundle/assetPathUtils.js @@ -75,7 +75,7 @@ function getResourceIdentifier(asset: PackagerAsset): string { .toLowerCase() .replace(/\//g, '_') // Encode folder structure in file name .replace(/([^a-z0-9_])/g, '') // Remove illegal chars - .replace(/^assets_/, ''); // Remove "assets_" prefix + .replace(/^(?:assets|assetsunstable_path)_/, ''); // Remove "assets_" or "assetsunstable_path_" prefix } function getBasePath(asset: PackagerAsset): string { diff --git a/packages/core-cli-utils/package.json b/packages/core-cli-utils/package.json index 93636a615784..202a67ca1e9a 100644 --- a/packages/core-cli-utils/package.json +++ b/packages/core-cli-utils/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/core-cli-utils", - "version": "0.84.0-main", + "version": "0.84.1", "private": true, "description": "React Native CLI library for Frameworks to build on", "license": "MIT", diff --git a/packages/debugger-frontend/BUILD_INFO b/packages/debugger-frontend/BUILD_INFO index 77ccb86aa35c..9cf877e7f31a 100644 --- a/packages/debugger-frontend/BUILD_INFO +++ b/packages/debugger-frontend/BUILD_INFO @@ -1,9 +1,9 @@ -@generated SignedSource<> -Git revision: 1f006e22bfad4d66df4786d6d775c15101c66e5d +@generated SignedSource<<4506db882ae105b6b912fa2f47f998fb>> +Git revision: 7b445c13d1349d49f7289d786857177308ba8272 Built with --nohooks: false Is local checkout: false Remote URL: https://github.com/facebook/react-native-devtools-frontend -Remote branch: main +Remote branch: 0.84-stable GN build args (overrides only): is_official_build = true Git status in checkout: diff --git a/packages/debugger-frontend/dist/third-party/front_end/panels/network/components/components.js b/packages/debugger-frontend/dist/third-party/front_end/panels/network/components/components.js index c4c4e92a7670..a3202b1b5c12 100644 --- a/packages/debugger-frontend/dist/third-party/front_end/panels/network/components/components.js +++ b/packages/debugger-frontend/dist/third-party/front_end/panels/network/components/components.js @@ -124,7 +124,7 @@ import*as e from"../../../ui/components/helpers/helpers.js";import*as t from"../ `:t.nothing} - `,this.#e,{host:this})}}customElements.define("devtools-network-event-coverage-infobar",P);var j=Object.freeze({__proto__:null,NetworkEventCoverageInfobar:P}),z={cssText:`:host{display:block}devtools-header-section-row:last-of-type{margin-bottom:10px}devtools-header-section-row:first-of-type{margin-top:2px}.call-to-action{background-color:var(--sys-color-neutral-container);padding:8px;border-radius:5px;margin:4px}.call-to-action-body{padding:6px 0;margin-left:9.5px;border-left:2px solid var(--issue-color-yellow);padding-left:18px;line-height:20px}.call-to-action .explanation{font-weight:bold}.call-to-action code{font-size:90%}.call-to-action .example .comment::before{content:" — "}.link,\n.devtools-link{color:var(--sys-color-primary);text-decoration:underline;cursor:pointer;outline-offset:2px}.explanation .link{font-weight:normal}.inline-icon{vertical-align:middle}@media (forced-colors: active){.link,\n .devtools-link{color:linktext;text-decoration-color:linktext}}\n/*# sourceURL=${import.meta.resolve("./RequestHeaderSection.css")} */\n`};const W=new CSSStyleSheet;W.replaceSync(z.cssText);const{render:B,html:G}=t,K={learnMore:"Learn more",provisionalHeadersAreShownDisableCache:"Provisional headers are shown. Disable cache to see full headers.",onlyProvisionalHeadersAre:"Only provisional headers are available because this request was not sent over the network and instead was served from a local cache, which doesn’t store the original request headers. Disable cache to see full request headers.",provisionalHeadersAreShown:"Provisional headers are shown."},X=d.i18n.registerUIStrings("panels/network/components/RequestHeaderSection.ts",K),Y=d.i18n.getLocalizedString.bind(void 0,X);class J extends HTMLElement{#e=this.attachShadow({mode:"open"});#E;#H=[];connectedCallback(){this.#e.adoptedStyleSheets=[W]}set data(e){this.#E=e.request,this.#H=this.#E.requestHeaders().map((e=>({name:l.StringUtilities.toLowerCaseString(e.name),value:e.value,valueEditable:2}))),this.#H.sort(((e,t)=>l.StringUtilities.compare(e.name,t.name))),"Request"===e.toReveal?.section&&this.#H.filter((t=>t.name===e.toReveal?.header?.toLowerCase())).forEach((e=>{e.highlight=!0})),this.#r()}#r(){this.#E&&B(G` + `,this.#e,{host:this})}}customElements.get("devtools-network-event-coverage-infobar")||customElements.define("devtools-network-event-coverage-infobar",P);var j=Object.freeze({__proto__:null,NetworkEventCoverageInfobar:P}),z={cssText:`:host{display:block}devtools-header-section-row:last-of-type{margin-bottom:10px}devtools-header-section-row:first-of-type{margin-top:2px}.call-to-action{background-color:var(--sys-color-neutral-container);padding:8px;border-radius:5px;margin:4px}.call-to-action-body{padding:6px 0;margin-left:9.5px;border-left:2px solid var(--issue-color-yellow);padding-left:18px;line-height:20px}.call-to-action .explanation{font-weight:bold}.call-to-action code{font-size:90%}.call-to-action .example .comment::before{content:" — "}.link,\n.devtools-link{color:var(--sys-color-primary);text-decoration:underline;cursor:pointer;outline-offset:2px}.explanation .link{font-weight:normal}.inline-icon{vertical-align:middle}@media (forced-colors: active){.link,\n .devtools-link{color:linktext;text-decoration-color:linktext}}\n/*# sourceURL=${import.meta.resolve("./RequestHeaderSection.css")} */\n`};const W=new CSSStyleSheet;W.replaceSync(z.cssText);const{render:B,html:G}=t,K={learnMore:"Learn more",provisionalHeadersAreShownDisableCache:"Provisional headers are shown. Disable cache to see full headers.",onlyProvisionalHeadersAre:"Only provisional headers are available because this request was not sent over the network and instead was served from a local cache, which doesn’t store the original request headers. Disable cache to see full request headers.",provisionalHeadersAreShown:"Provisional headers are shown."},X=d.i18n.registerUIStrings("panels/network/components/RequestHeaderSection.ts",K),Y=d.i18n.getLocalizedString.bind(void 0,X);class J extends HTMLElement{#e=this.attachShadow({mode:"open"});#E;#H=[];connectedCallback(){this.#e.adoptedStyleSheets=[W]}set data(e){this.#E=e.request,this.#H=this.#E.requestHeaders().map((e=>({name:l.StringUtilities.toLowerCaseString(e.name),value:e.value,valueEditable:2}))),this.#H.sort(((e,t)=>l.StringUtilities.compare(e.name,t.name))),"Request"===e.toReveal?.section&&this.#H.filter((t=>t.name===e.toReveal?.header?.toLowerCase())).forEach((e=>{e.highlight=!0})),this.#r()}#r(){this.#E&&B(G` ${this.#$()} ${this.#H.map((e=>G` `:H.nothing} - `,this.#i,{host:this})}}customElements.define("devtools-network-event-coverage-infobar",Yt);class Qt{parentView;activeGroups;constructor(e){this.parentView=e,this.activeGroups=new Map}groupNodeForRequest(e){const t=n.ResourceTreeModel.ResourceTreeModel.frameForRequest(e);if(!t||t.isOutermostFrame())return null;let i=this.activeGroups.get(t);return i||(i=new Zt(this.parentView,t),this.activeGroups.set(t,i),i)}reset(){this.activeGroups.clear()}}class Zt extends fe{frame;constructor(e,t){super(e),this.frame=t}displayName(){return new t.ParsedURL.ParsedURL(this.frame.url).domain()||this.frame.name||"