Compare commits

..
Author SHA1 Message Date
Devmate BotandFacebook GitHub Bot b476c8234d xplat/js/react-native-github/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/animated/InterpolationAnimatedNode.kt
Reviewed By: javache

Differential Revision: D83948964
2025-10-08 11:35:13 -07:00
1164 changed files with 38642 additions and 51640 deletions
-3
View File
@@ -35,9 +35,6 @@ module.exports = {
// Flow handles these checks for us, so they aren't required
'no-undef': 'off',
'no-unreachable': 'off',
// Throwing from function or rejecting promises with non-error values could result in unclear error stack traces and lead to harder debugging
'prefer-promise-reject-errors': 'error',
'no-throw-literal': 'error',
},
},
{
+1 -1
View File
@@ -98,4 +98,4 @@ untyped-import
untyped-type-import
[version]
^0.289.0
^0.287.0
@@ -0,0 +1,103 @@
name: build-apple-slices-hermes
description: This action builds hermesc for Apple platforms
inputs:
hermes-version:
required: true
description: The version of Hermes
react-native-version:
required: true
description: The version of Hermes
slice:
required: true
description: The slice of hermes you want to build. It could be iphone, iphonesimulator, macos, catalyst, appletvos, appletvsimulator, xros, or xrossimulator
flavor:
required: true
description: The flavor we want to build. It can be Debug or Release
runs:
using: composite
steps:
- name: Setup xcode
uses: ./.github/actions/setup-xcode
- name: Restore Hermes workspace
uses: ./.github/actions/restore-hermes-workspace
- name: Restore HermesC Artifact
uses: actions/download-artifact@v4
with:
name: hermesc-apple
path: ./packages/react-native/sdks/hermes/build_host_hermesc
- name: Restore Slice From Cache
id: restore-slice-cache
uses: actions/cache/restore@v4
with:
path: ./packages/react-native/sdks/hermes/build_${{ inputs.slice }}_${{ inputs.flavor }}
key: v6-hermes-apple-${{ inputs.hermes-version }}-${{ inputs.react-native-version }}-${{ hashfiles('packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh') }}-${{ inputs.slice }}-${{ inputs.flavor }}
- name: Build the Hermes ${{ inputs.slice }} frameworks
shell: bash
run: |
cd ./packages/react-native/sdks/hermes || exit 1
SLICE=${{ inputs.slice }}
FLAVOR=${{ inputs.flavor }}
FINAL_PATH=build_"$SLICE"_"$FLAVOR"
echo "Final path for this slice is: $FINAL_PATH"
if [[ -d "$FINAL_PATH" ]]; then
echo "[HERMES] Skipping! Found the requested slice at $FINAL_PATH".
exit 0
fi
if [[ "$ARTIFACTS_EXIST" ]]; then
echo "[HERMES] Skipping! Artifacts exists already."
exit 0
fi
export RELEASE_VERSION=${{ inputs.react-native-version }}
# HermesC is used to build hermes, so it has to be executable
chmod +x ./build_host_hermesc/bin/hermesc
if [[ "$SLICE" == "macosx" ]]; then
echo "[HERMES] Building Hermes for MacOS"
chmod +x ./utils/build-mac-framework.sh
BUILD_TYPE="${{ inputs.flavor }}" ./utils/build-mac-framework.sh
else
echo "[HERMES] Building Hermes for iOS: $SLICE"
chmod +x ./utils/build-ios-framework.sh
BUILD_TYPE="${{ inputs.flavor }}" ./utils/build-ios-framework.sh "$SLICE"
fi
echo "Moving from build_$SLICE to $FINAL_PATH"
mv build_"$SLICE" "$FINAL_PATH"
# check whether everything is there
if [[ -d "$FINAL_PATH/lib/hermesvm.framework" ]]; then
echo "Successfully built hermesvm.framework for $SLICE in $FLAVOR"
else
echo "Failed to built hermesvm.framework for $SLICE in $FLAVOR"
exit 1
fi
if [[ -d "$FINAL_PATH/lib/hermesvm.framework.dSYM" ]]; then
echo "Successfully built hermesvm.framework.dSYM for $SLICE in $FLAVOR"
else
echo "Failed to built hermesvm.framework.dSYM for $SLICE in $FLAVOR"
echo "Please try again"
exit 1
fi
- name: Compress slices to preserve Symlinks
shell: bash
run: |
cd ./packages/react-native/sdks/hermes
tar -czv -f build_${{ matrix.slice }}_${{ matrix.flavor }}.tar.gz build_${{ matrix.slice }}_${{ matrix.flavor }}
- name: Upload Artifact for Slice (${{ inputs.slice }}, ${{ inputs.flavor }}}
uses: actions/upload-artifact@v4.3.4
with:
name: slice-${{ inputs.slice }}-${{ inputs.flavor }}
path: ./packages/react-native/sdks/hermes/build_${{ inputs.slice }}_${{ inputs.flavor }}.tar.gz
- name: Save slice cache
if: ${{ github.ref == 'refs/heads/main' || contains(github.ref, '-stable') }} # To avoid that the cache explode.
uses: actions/cache/save@v4
with:
path: ./packages/react-native/sdks/hermes/build_${{ inputs.slice }}_${{ inputs.flavor }}
key: v6-hermes-apple-${{ inputs.hermes-version }}-${{ inputs.react-native-version }}-${{ hashfiles('packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh') }}-${{ inputs.SLICE }}-${{ inputs.FLAVOR }}
@@ -0,0 +1,227 @@
name: build-hermes-macos
description: This action builds hermesc for Apple platforms
inputs:
hermes-version:
required: true
description: The version of Hermes
react-native-version:
required: true
description: The version of React Native
flavor:
required: true
description: The flavor we want to build. It can be Debug or Release
runs:
using: composite
steps:
- name: Setup xcode
uses: ./.github/actions/setup-xcode
- name: Restore Hermes workspace
uses: ./.github/actions/restore-hermes-workspace
- name: Restore Cached Artifacts
uses: actions/cache/restore@v4
with:
key: v4-hermes-artifacts-${{ inputs.flavor }}-${{ inputs.hermes-version }}-${{ inputs.react-native-version }}-${{ hashFiles('./packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh') }}
path: |
/tmp/hermes/osx-bin/${{ inputs.flavor }}
/tmp/hermes/dSYM/${{ inputs.flavor }}
/tmp/hermes/hermes-runtime-darwin/hermes-ios-${{ inputs.flavor }}.tar.gz
- name: Check if the required artifacts already exist
id: check_if_apple_artifacts_are_there
shell: bash
run: |
FLAVOR="${{ inputs.flavor }}"
echo "Flavor is $FLAVOR"
OSX_BIN="/tmp/hermes/osx-bin/$FLAVOR"
DSYM="/tmp/hermes/dSYM/$FLAVOR"
HERMES="/tmp/hermes/hermes-runtime-darwin/hermes-ios-$FLAVOR.tar.gz"
if [[ -d "$OSX_BIN" ]] && \
[[ -d "$DSYM" ]] && \
[[ -f "$HERMES" ]]; then
echo "Artifacts are there!"
echo "ARTIFACTS_EXIST=true" >> $GITHUB_ENV
echo "ARTIFACTS_EXIST=true" >> $GITHUB_OUTPUT
fi
- name: Setup node.js
uses: ./.github/actions/setup-node
- name: Yarn- Install Dependencies
if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }}
uses: ./.github/actions/yarn-install
- name: Slice cache macosx
if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }}
uses: actions/download-artifact@v4
with:
path: ./packages/react-native/sdks/hermes/
name: slice-macosx-${{ inputs.flavor }}
- name: Slice cache iphoneos
if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }}
uses: actions/download-artifact@v4
with:
path: ./packages/react-native/sdks/hermes/
name: slice-iphoneos-${{ inputs.flavor }}
- name: Slice cache iphonesimulator
if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }}
uses: actions/download-artifact@v4
with:
path: ./packages/react-native/sdks/hermes/
name: slice-iphonesimulator-${{ inputs.flavor }}
- name: Slice cache appletvos
if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }}
uses: actions/download-artifact@v4
with:
path: ./packages/react-native/sdks/hermes/
name: slice-appletvos-${{ inputs.flavor }}
- name: Slice cache appletvsimulator
if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }}
uses: actions/download-artifact@v4
with:
path: ./packages/react-native/sdks/hermes/
name: slice-appletvsimulator-${{ inputs.flavor }}
- name: Slice cache catalyst
if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }}
uses: actions/download-artifact@v4
with:
path: ./packages/react-native/sdks/hermes/
name: slice-catalyst-${{ inputs.flavor }}
- name: Slice cache xros
if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }}
uses: actions/download-artifact@v4
with:
path: ./packages/react-native/sdks/hermes/
name: slice-xros-${{ inputs.flavor }}
- name: Slice cache xrsimulator
if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }}
uses: actions/download-artifact@v4
with:
path: ./packages/react-native/sdks/hermes/
name: slice-xrsimulator-${{ inputs.flavor }}
- name: Unzip slices
shell: bash
if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }}
run: |
cd ./packages/react-native/sdks/hermes
ls -l .
tar -xzv -f build_catalyst_${{ matrix.flavor }}.tar.gz
tar -xzv -f build_iphoneos_${{ matrix.flavor }}.tar.gz
tar -xzv -f build_iphonesimulator_${{ matrix.flavor }}.tar.gz
tar -xzv -f build_appletvos_${{ matrix.flavor }}.tar.gz
tar -xzv -f build_appletvsimulator_${{ matrix.flavor }}.tar.gz
tar -xzv -f build_macosx_${{ matrix.flavor }}.tar.gz
tar -xzv -f build_xros_${{ matrix.flavor }}.tar.gz
tar -xzv -f build_xrsimulator_${{ matrix.flavor }}.tar.gz
- name: Move back build folders
if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }}
shell: bash
run: |
ls -l ./packages/react-native/sdks/hermes
cd ./packages/react-native/sdks/hermes || exit 1
mv build_macosx_${{ inputs.flavor }} build_macosx
mv build_iphoneos_${{ inputs.flavor }} build_iphoneos
mv build_iphonesimulator_${{ inputs.flavor }} build_iphonesimulator
mv build_appletvos_${{ inputs.flavor }} build_appletvos
mv build_appletvsimulator_${{ inputs.flavor }} build_appletvsimulator
mv build_catalyst_${{ inputs.flavor }} build_catalyst
mv build_xros_${{ inputs.flavor }} build_xros
mv build_xrsimulator_${{ inputs.flavor }} build_xrsimulator
- name: Prepare destroot folder
if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }}
shell: bash
run: |
cd ./packages/react-native/sdks/hermes || exit 1
chmod +x ./utils/build-apple-framework.sh
. ./utils/build-apple-framework.sh
prepare_dest_root_for_ci
- name: Create fat framework for iOS
if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }}
shell: bash
run: |
cd ./packages/react-native/sdks/hermes || exit 1
echo "[HERMES] Creating the universal framework"
chmod +x ./utils/build-ios-framework.sh
./utils/build-ios-framework.sh build_framework
chmod +x ./destroot/bin/hermesc
- name: Package the Hermes Apple frameworks
if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }}
shell: bash
run: |
BUILD_TYPE="${{ inputs.flavor }}"
echo "Packaging Hermes Apple frameworks for $BUILD_TYPE build type"
TARBALL_OUTPUT_DIR=$(mktemp -d /tmp/hermes-tarball-output-XXXXXXXX)
TARBALL_FILENAME=$(node ./packages/react-native/scripts/hermes/get-tarball-name.js --buildType "$BUILD_TYPE")
echo "Packaging Hermes Apple frameworks for $BUILD_TYPE build type"
TARBALL_OUTPUT_PATH=$(node ./packages/react-native/scripts/hermes/create-tarball.js \
--inputDir ./packages/react-native/sdks/hermes \
--buildType "$BUILD_TYPE" \
--outputDir $TARBALL_OUTPUT_DIR)
echo "Hermes tarball saved to $TARBALL_OUTPUT_PATH"
mkdir -p $HERMES_TARBALL_ARTIFACTS_DIR
cp $TARBALL_OUTPUT_PATH $HERMES_TARBALL_ARTIFACTS_DIR/.
mkdir -p /tmp/hermes/osx-bin/${{ inputs.flavor }}
cp ./packages/react-native/sdks/hermes/build_macosx/bin/* /tmp/hermes/osx-bin/${{ inputs.flavor }}
ls -lR /tmp/hermes/osx-bin/
- name: Create dSYM archive
if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }}
shell: bash
run: |
FLAVOR=${{ inputs.flavor }}
WORKING_DIR="/tmp/hermes_tmp/dSYM/$FLAVOR"
mkdir -p "$WORKING_DIR/macosx"
mkdir -p "$WORKING_DIR/catalyst"
mkdir -p "$WORKING_DIR/iphoneos"
mkdir -p "$WORKING_DIR/iphonesimulator"
mkdir -p "$WORKING_DIR/appletvos"
mkdir -p "$WORKING_DIR/appletvsimulator"
mkdir -p "$WORKING_DIR/xros"
mkdir -p "$WORKING_DIR/xrsimulator"
cd ./packages/react-native/sdks/hermes || exit 1
DSYM_FILE_PATH=lib/hermesvm.framework.dSYM
cp -r build_macosx/$DSYM_FILE_PATH "$WORKING_DIR/macosx/"
cp -r build_catalyst/$DSYM_FILE_PATH "$WORKING_DIR/catalyst/"
cp -r build_iphoneos/$DSYM_FILE_PATH "$WORKING_DIR/iphoneos/"
cp -r build_iphonesimulator/$DSYM_FILE_PATH "$WORKING_DIR/iphonesimulator/"
cp -r build_appletvos/$DSYM_FILE_PATH "$WORKING_DIR/appletvos/"
cp -r build_appletvsimulator/$DSYM_FILE_PATH "$WORKING_DIR/appletvsimulator/"
cp -r build_xros/$DSYM_FILE_PATH "$WORKING_DIR/xros/"
cp -r build_xrsimulator/$DSYM_FILE_PATH "$WORKING_DIR/xrsimulator/"
DEST_DIR="/tmp/hermes/dSYM/$FLAVOR"
tar -C "$WORKING_DIR" -czvf "hermesvm.framework.dSYM" .
mkdir -p "$DEST_DIR"
mv "hermesvm.framework.dSYM" "$DEST_DIR"
- name: Upload hermes dSYM artifacts
uses: actions/upload-artifact@v4.3.4
with:
name: hermes-dSYM-${{ inputs.flavor }}
path: /tmp/hermes/dSYM/${{ inputs.flavor }}
- name: Upload hermes Runtime artifacts
uses: actions/upload-artifact@v4.3.4
with:
name: hermes-darwin-bin-${{ inputs.flavor }}
path: /tmp/hermes/hermes-runtime-darwin/hermes-ios-${{ inputs.flavor }}.tar.gz
- name: Upload hermes osx artifacts
uses: actions/upload-artifact@v4.3.4
with:
name: hermes-osx-bin-${{ inputs.flavor }}
path: /tmp/hermes/osx-bin/${{ inputs.flavor }}
- name: Upload Hermes Artifacts
uses: actions/cache/save@v4
if: ${{ github.ref == 'refs/heads/main' || contains(github.ref, '-stable') }} # To avoid that the cache explode.
with:
key: v4-hermes-artifacts-${{ inputs.flavor }}-${{ inputs.hermes-version }}-${{ inputs.react-native-version }}-${{ hashFiles('./packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh') }}
path: |
/tmp/hermes/osx-bin/${{ inputs.flavor }}
/tmp/hermes/dSYM/${{ inputs.flavor }}
/tmp/hermes/hermes-runtime-darwin/hermes-ios-${{ inputs.flavor }}.tar.gz
@@ -0,0 +1,39 @@
name: build-hermesc-apple
description: This action builds hermesc for Apple platforms
inputs:
hermes-version:
required: true
description: The version of Hermes
react-native-version:
required: true
description: The version of React Native
runs:
using: composite
steps:
- name: Setup xcode
uses: ./.github/actions/setup-xcode
- name: Restore Hermes workspace
uses: ./.github/actions/restore-hermes-workspace
- name: Hermes apple cache
uses: actions/cache/restore@v4
with:
path: ./packages/react-native/sdks/hermes/build_host_hermesc
key: v2-hermesc-apple-${{ inputs.hermes-version }}-${{ inputs.react-native-version }}
- name: Build HermesC Apple
shell: bash
run: |
cd ./packages/react-native/sdks/hermes || exit 1
. ./utils/build-apple-framework.sh
build_host_hermesc_if_needed
- name: Upload HermesC Artifact
uses: actions/upload-artifact@v4.3.4
with:
name: hermesc-apple
path: ./packages/react-native/sdks/hermes/build_host_hermesc
- name: Cache hermesc apple
uses: actions/cache/save@v4
if: ${{ github.ref == 'refs/heads/main' || contains(github.ref, '-stable') }} # To avoid that the cache explode.
with:
path: ./packages/react-native/sdks/hermes/build_host_hermesc
key: v2-hermesc-apple-${{ inputs.hermes-version }}-${{ inputs.react-native-version }}
enableCrossOsArchive: true
@@ -0,0 +1,53 @@
name: build-hermesc-linux
description: This action builds hermesc for linux platforms
inputs:
hermes-version:
required: True
description: The version of Hermes
react-native-version:
required: True
description: The version of React Native
runs:
using: composite
steps:
- name: Install dependencies
shell: bash
run: |
sudo apt update
sudo apt install -y git openssh-client build-essential \
libreadline-dev libicu-dev jq zip python3
# Install cmake 3.28.3-1build7
sudo apt-get install cmake=3.28.3-1build7
sudo ln -sf /usr/bin/cmake /usr/local/bin/cmake
- name: Restore Hermes workspace
uses: ./.github/actions/restore-hermes-workspace
- name: Linux cache
uses: actions/cache@v4
with:
key: v1-hermes-${{ github.job }}-linux-${{ inputs.hermes-version }}-${{ inputs.react-native-version }}
path: |
/tmp/hermes/linux64-bin/
/tmp/hermes/hermes/destroot/
- name: Set up workspace
shell: bash
run: |
mkdir -p /tmp/hermes/linux64-bin
- name: Build HermesC for Linux
shell: bash
run: |
if [ -f /tmp/hermes/linux64-bin/hermesc ]; then
echo 'Skipping; Clean "/tmp/hermes/linux64-bin" to rebuild.'
else
cd /tmp/hermes
cmake -S hermes -B build -DHERMES_STATIC_LINK=ON -DCMAKE_BUILD_TYPE=Release -DHERMES_ENABLE_TEST_SUITE=OFF \
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=True -DCMAKE_CXX_FLAGS=-s -DCMAKE_C_FLAGS=-s \
-DCMAKE_EXE_LINKER_FLAGS="-Wl,--whole-archive -lpthread -Wl,--no-whole-archive"
cmake --build build --target hermesc -j 4
cp /tmp/hermes/build/bin/hermesc /tmp/hermes/linux64-bin/.
fi
- name: Upload linux artifacts
uses: actions/upload-artifact@v4.3.4
with:
name: hermes-linux-bin
path: /tmp/hermes/linux64-bin
@@ -0,0 +1,86 @@
name: build-hermesc-windows
description: This action builds hermesc for Windows platforms
inputs:
hermes-version:
required: True
description: The version of Hermes
react-native-version:
required: True
description: The version of React Native
runs:
using: composite
steps:
- name: Download Previous Artifacts
uses: actions/download-artifact@v4
with:
name: hermes-workspace
path: 'C:\tmp\hermes'
- name: Set up workspace
shell: powershell
run: |
mkdir -p C:\tmp\hermes\osx-bin
mkdir -p .\packages\react-native\sdks\hermes
cp -r -Force C:\tmp\hermes\hermes\* .\packages\react-native\sdks\hermes\.
cp -r -Force .\packages\react-native\sdks\hermes-engine\utils\* .\packages\react-native\sdks\hermes\.
- name: Windows cache
uses: actions/cache@v4
with:
key: v3-hermes-${{ github.job }}-windows-${{ inputs.hermes-version }}-${{ inputs.react-native-version }}
path: |
C:\tmp\hermes\win64-bin\
C:\tmp\hermes\hermes\icu\
C:\tmp\hermes\hermes\deps\
C:\tmp\hermes\hermes\build_release\
- name: setup-msbuild
uses: microsoft/setup-msbuild@v1.3.2
- name: Set up workspace
shell: powershell
run: |
New-Item -ItemType Directory -ErrorAction SilentlyContinue $Env:HERMES_WS_DIR\icu
New-Item -ItemType Directory -ErrorAction SilentlyContinue $Env:HERMES_WS_DIR\deps
New-Item -ItemType Directory -ErrorAction SilentlyContinue $Env:HERMES_WS_DIR\win64-bin
- name: Downgrade CMake
shell: powershell
run: choco install cmake --version 3.31.6 --force
- name: Build HermesC for Windows
shell: powershell
run: |
if (-not(Test-Path -Path $Env:HERMES_WS_DIR\win64-bin\hermesc.exe)) {
cd $Env:HERMES_WS_DIR\icu
# If Invoke-WebRequest shows a progress bar, it will fail with
# Win32 internal error "Access is denied" 0x5 occurred [...]
$progressPreference = 'silentlyContinue'
Invoke-WebRequest -Uri "$Env:ICU_URL" -OutFile "icu.zip"
Expand-Archive -Path "icu.zip" -DestinationPath "."
cd $Env:HERMES_WS_DIR
Copy-Item -Path "icu\bin64\icu*.dll" -Destination "deps"
# Include MSVC++ 2015 redistributables
Copy-Item -Path "c:\windows\system32\msvcp140.dll" -Destination "deps"
Copy-Item -Path "c:\windows\system32\vcruntime140.dll" -Destination "deps"
Copy-Item -Path "c:\windows\system32\vcruntime140_1.dll" -Destination "deps"
$Env:PATH += ";$Env:CMAKE_DIR;$Env:MSBUILD_DIR"
$Env:ICU_ROOT = "$Env:HERMES_WS_DIR\icu"
cmake -S hermes -B build_release -G 'Visual Studio 17 2022' -Ax64 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=True -DHERMES_ENABLE_WIN10_ICU_FALLBACK=OFF
if (-not $?) { throw "Failed to configure Hermes" }
echo "Running windows build..."
cd build_release
cmake --build . --target hermesc --config Release
if (-not $?) { throw "Failed to build Hermes" }
echo "Copying hermesc.exe to win64-bin"
cd $Env:HERMES_WS_DIR
Copy-Item -Path "build_release\bin\Release\hermesc.exe" -Destination "win64-bin"
# Include Windows runtime dependencies
Copy-Item -Path "deps\*" -Destination "win64-bin"
}
else {
Write-Host "Skipping; Clean c:\tmp\hermes\win64-bin to rebuild."
}
- name: Upload windows artifacts
uses: actions/upload-artifact@v4.3.4
with:
name: hermes-win64-bin
path: C:\tmp\hermes\win64-bin\
@@ -4,6 +4,9 @@ inputs:
release-type:
required: true
description: The type of release we are building. It could be nightly, release or dry-run
hermes-ws-dir:
required: 'true'
description: The workspace for hermes
gha-npm-token:
required: false
description: The GHA npm token, required only to publish to npm
@@ -17,6 +20,87 @@ runs:
- name: Setup git safe folders
shell: bash
run: git config --global --add safe.directory '*'
- name: Create /tmp/hermes/osx-bin directory
shell: bash
run: mkdir -p /tmp/hermes/osx-bin
- name: Download osx-bin release artifacts
uses: actions/download-artifact@v4
with:
name: hermes-osx-bin-Release
path: /tmp/hermes/osx-bin/Release
- name: Download osx-bin debug artifacts
uses: actions/download-artifact@v4
with:
name: hermes-osx-bin-Debug
path: /tmp/hermes/osx-bin/Debug
- name: Download darwin-bin release artifacts
uses: actions/download-artifact@v4
with:
name: hermes-darwin-bin-Release
path: /tmp/hermes/hermes-runtime-darwin
- name: Download darwin-bin debug artifacts
uses: actions/download-artifact@v4
with:
name: hermes-darwin-bin-Debug
path: /tmp/hermes/hermes-runtime-darwin
- name: Download hermes dSYM debug artifacts
uses: actions/download-artifact@v4
with:
name: hermes-dSYM-Debug
path: /tmp/hermes/dSYM/Debug
- name: Download hermes dSYM release vartifacts
uses: actions/download-artifact@v4
with:
name: hermes-dSYM-Release
path: /tmp/hermes/dSYM/Release
- name: Download windows-bin artifacts
uses: actions/download-artifact@v4
with:
name: hermes-win64-bin
path: /tmp/hermes/win64-bin
- name: Download linux-bin artifacts
uses: actions/download-artifact@v4
with:
name: hermes-linux-bin
path: /tmp/hermes/linux64-bin
- name: Show /tmp/hermes directory
shell: bash
run: ls -lR /tmp/hermes
- name: Copy Hermes binaries
shell: bash
run: |
mkdir -p ./packages/react-native/sdks/hermesc ./packages/react-native/sdks/hermesc/osx-bin ./packages/react-native/sdks/hermesc/win64-bin ./packages/react-native/sdks/hermesc/linux64-bin
# When build_hermes_macos runs as a matrix, it outputs
if [[ -d ${{ inputs.hermes-ws-dir }}/osx-bin/Release ]]; then
cp -r ${{ inputs.hermes-ws-dir }}/osx-bin/Release/* ./packages/react-native/sdks/hermesc/osx-bin/.
elif [[ -d ${{ inputs.hermes-ws-dir }}/osx-bin/Debug ]]; then
cp -r ${{ inputs.hermes-ws-dir }}/osx-bin/Debug/* ./packages/react-native/sdks/hermesc/osx-bin/.
else
ls ${{ inputs.hermes-ws-dir }}/osx-bin || echo "hermesc macOS artifacts directory missing."
echo "Could not locate macOS hermesc binary."; exit 1;
fi
# Sometimes, GHA creates artifacts with lowercase Debug/Release. Make sure that if it happen, we uppercase them.
if [[ -f "${{ inputs.hermes-ws-dir }}/hermes-runtime-darwin/hermes-ios-debug.tar.gz" ]]; then
mv "${{ inputs.hermes-ws-dir }}/hermes-runtime-darwin/hermes-ios-debug.tar.gz" "${{ inputs.hermes-ws-dir }}/hermes-runtime-darwin/hermes-ios-Debug.tar.gz"
fi
if [[ -f "${{ inputs.hermes-ws-dir }}/hermes-runtime-darwin/hermes-ios-release.tar.gz" ]]; then
mv "${{ inputs.hermes-ws-dir }}/hermes-runtime-darwin/hermes-ios-release.tar.gz" "${{ inputs.hermes-ws-dir }}/hermes-runtime-darwin/hermes-ios-Release.tar.gz"
fi
cp -r ${{ inputs.hermes-ws-dir }}/win64-bin/* ./packages/react-native/sdks/hermesc/win64-bin/.
cp -r ${{ inputs.hermes-ws-dir }}/linux64-bin/* ./packages/react-native/sdks/hermesc/linux64-bin/.
# Make sure the hermesc files are actually executable.
chmod -R +x packages/react-native/sdks/hermesc/*
mkdir -p ./packages/react-native/ReactAndroid/external-artifacts/artifacts/
cp ${{ inputs.hermes-ws-dir }}/hermes-runtime-darwin/hermes-ios-Debug.tar.gz ./packages/react-native/ReactAndroid/external-artifacts/artifacts/hermes-ios-debug.tar.gz
cp ${{ inputs.hermes-ws-dir }}/hermes-runtime-darwin/hermes-ios-Release.tar.gz ./packages/react-native/ReactAndroid/external-artifacts/artifacts/hermes-ios-release.tar.gz
cp ${{ inputs.hermes-ws-dir }}/dSYM/Debug/hermesvm.framework.dSYM ./packages/react-native/ReactAndroid/external-artifacts/artifacts/hermes-framework-dSYM-debug.tar.gz
cp ${{ inputs.hermes-ws-dir }}/dSYM/Release/hermesvm.framework.dSYM ./packages/react-native/ReactAndroid/external-artifacts/artifacts/hermes-framework-dSYM-release.tar.gz
- name: Download ReactNativeDependencies
uses: actions/download-artifact@v4
with:
@@ -0,0 +1,99 @@
name: prepare-hermes-workspace
description: This action prepares the hermes workspace with the right hermes and react-native versions.
inputs:
hermes-ws-dir:
required: true
description: The hermes dir we need to use to setup the workspace
hermes-version-file:
required: true
description: the path to the file that will contain the hermes version
outputs:
hermes-version:
description: the version of Hermes tied to this run
value: ${{ steps.hermes-version.outputs.VERSION }}
react-native-version:
description: the version of React Native tied to this run
value: ${{ steps.react-native-version.outputs.VERSION }}
runs:
using: composite
steps:
- name: Setup hermes version
shell: bash
id: hermes-version
run: |
mkdir -p "/tmp/hermes" "/tmp/hermes/download" "/tmp/hermes/hermes"
if [ -f "${{ inputs.hermes-version-file }}" ]; then
echo "Hermes Version file found! Using this version for the build:"
echo "VERSION=$(cat ${{ inputs.hermes-version-file }})" >> "$GITHUB_OUTPUT"
else
echo "Hermes Version file not found!!!"
echo "Using the last commit from main for the build:"
HERMES_TAG_SHA=$(git ls-remote https://github.com/facebook/hermes main | cut -f 1 | tr -d '[:space:]')
echo "VERSION=$HERMES_TAG_SHA" >> "$GITHUB_OUTPUT"
fi
echo "Hermes commit is $HERMES_TAG_SHA"
- name: Get react-native version
shell: bash
id: react-native-version
run: |
VERSION=$(cat packages/react-native/package.json | jq -r '.version')
# Save the react native version we are building in an output variable so we can use that file as part of the cache key.
echo "VERSION=$VERSION" >> "$GITHUB_OUTPUT"
echo "React Native Version is $VERSION"
- name: Cache hermes workspace
id: restore-hermes
uses: actions/cache/restore@v4
with:
path: |
/tmp/hermes/download/
/tmp/hermes/hermes/
key: v1-hermes-${{ steps.hermes-version.outputs.version }}
enableCrossOsArchive: true
# It happened while testing that a cache was created from the right folders
# but those folders where empty. Thus, the next check ensures that we can work with those caches.
- name: Check if cache was meaningful
id: meaningful-cache
shell: bash
run: |
if [[ -d /tmp/hermes/hermes ]] && [[ -n "$(ls -A /tmp/hermes/hermes)" ]]; then
echo "Found a good hermes cache"
echo "HERMES_CACHED=true" >> "$GITHUB_OUTPUT"
fi
- name: Setup node.js
uses: ./.github/actions/setup-node
- name: Yarn- Install Dependencies
if: ${{ steps.meaningful-cache.outputs.HERMES_CACHED != 'true' }}
uses: ./.github/actions/yarn-install
- name: Download Hermes tarball
if: ${{ steps.meaningful-cache.outputs.HERMES_CACHED != 'true' }}
shell: bash
run: |
node packages/react-native/scripts/hermes/prepare-hermes-for-build ${{ github.event.pull_request.html_url }}
cp packages/react-native/sdks/download/* ${{ inputs.hermes-ws-dir }}/download/.
cp -r packages/react-native/sdks/hermes/* ${{ inputs.hermes-ws-dir }}/hermes/.
echo ${{ steps.hermes-version.outputs.version }}
- name: Upload Hermes artifact
uses: actions/upload-artifact@v4.3.4
with:
name: hermes-workspace
path: |
/tmp/hermes/download/
/tmp/hermes/hermes/
- name: Cache hermes workspace
uses: actions/cache/save@v4
if: ${{ github.ref == 'refs/heads/main' }} # To avoid that the cache explode.
with:
path: |
/tmp/hermes/download/
/tmp/hermes/hermes/
key: v1-hermes-${{ steps.hermes-version.outputs.version }}
enableCrossOsArchive: true
@@ -0,0 +1,16 @@
name: restore-hermes-workspace
description: "Restore hermes workspace that has been created in Prepare Hermes Workspace"
runs:
using: composite
steps:
- name: Download Previous Artifacts
uses: actions/download-artifact@v4
with:
name: hermes-workspace
path: /tmp/hermes
- name: Set up workspace
shell: bash
run: |
mkdir -p $HERMES_OSXBIN_ARTIFACTS_DIR ./packages/react-native/sdks/hermes
cp -r $HERMES_WS_DIR/hermes/* ./packages/react-native/sdks/hermes/.
cp -r ./packages/react-native/sdks/hermes-engine/utils ./packages/react-native/sdks/hermes/.
-22
View File
@@ -5,10 +5,6 @@ inputs:
description: 'The xcode version to use'
required: false
default: '16.2.0'
platform:
description: 'The platform to use. Valid values are: ios, ios-simulator, macos, mac-catalyst, tvos, tvos-simulator, xros, xros-simulator'
required: false
default: 'macos'
runs:
using: "composite"
steps:
@@ -16,21 +12,3 @@ runs:
uses: maxim-lobanov/setup-xcode@60606e260d2fc5762a71e64e74b2174e8ea3c8bd
with:
xcode-version: ${{ inputs.xcode-version }}
- name: Setup Platform ${{ inputs.platform }}
if: ${{ inputs.platform != 'macos' && inputs.platform != 'mac-catalyst' }}
shell: bash
run: |
# https://github.com/actions/runner-images/issues/12541
sudo xcodebuild -runFirstLaunch
sudo xcrun simctl list
# Install platform based on the platform
if [[ "${{ inputs.platform }}" == "xros" || "${{ inputs.platform }}" == "xros-simulator" ]]; then
sudo xcodebuild -downloadPlatform visionOS
elif [[ "${{ inputs.platform }}" == "tvos" || "${{ inputs.platform }}" == "tvos-simulator" ]]; then
sudo xcodebuild -downloadPlatform tvOS
else
sudo xcodebuild -downloadPlatform iOS
fi
sudo xcodebuild -runFirstLaunch
+31 -8
View File
@@ -10,27 +10,36 @@ inputs:
flavor:
description: The flavor of the build. Must be one of "Debug", "Release".
default: Debug
hermes-version:
description: The version of hermes
required: true
react-native-version:
description: The version of react-native
required: true
runs:
using: composite
steps:
- name: Setup xcode
uses: ./.github/actions/setup-xcode
with:
platform: ios
- name: Setup node.js
uses: ./.github/actions/setup-node
- name: Run yarn install
uses: ./.github/actions/yarn-install
- name: Create Hermes folder
shell: bash
run: mkdir -p "$HERMES_WS_DIR"
- name: Download Hermes
uses: actions/download-artifact@v4
with:
name: hermes-darwin-bin-${{ inputs.flavor }}
path: /tmp/hermes/hermes-runtime-darwin/
- name: Print Downloaded hermes
shell: bash
run: ls -lR "$HERMES_WS_DIR"
- name: Setup ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ inputs.ruby-version }}
- name: Set nightly Hermes versions
shell: bash
run: |
node ./scripts/releases/use-hermes-nightly.js
- name: Run yarn install again, with the correct hermes version
uses: ./.github/actions/yarn-install
- name: Download ReactNativeDependencies
uses: actions/download-artifact@v4
with:
@@ -57,6 +66,20 @@ runs:
args+=(--frameworks dynamic)
fi
# Tarball is restored with capital flavors suffix, but somehow the tarball name from JS at line 96 returns as lowercased.
# Let's ensure that the tarballs have the right names
if [[ -f "$HERMES_WS_DIR/hermes-runtime-darwin/hermes-ios-Debug.tar.gz" ]]; then
mv "$HERMES_WS_DIR/hermes-runtime-darwin/hermes-ios-Debug.tar.gz" "$HERMES_WS_DIR/hermes-runtime-darwin/hermes-ios-debug.tar.gz"
fi
if [[ -f "$HERMES_WS_DIR/hermes-runtime-darwin/hermes-ios-Release.tar.gz" ]]; then
mv "$HERMES_WS_DIR/hermes-runtime-darwin/hermes-ios-Release.tar.gz" "$HERMES_WS_DIR/hermes-runtime-darwin/hermes-ios-release.tar.gz"
fi
BUILD_TYPE="${{ inputs.flavor }}"
TARBALL_FILENAME=$(node ../../packages/react-native/scripts/hermes/get-tarball-name.js --buildType "$BUILD_TYPE")
export HERMES_ENGINE_TARBALL_PATH="$HERMES_WS_DIR/hermes-runtime-darwin/$TARBALL_FILENAME"
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"
+54 -9
View File
@@ -10,9 +10,18 @@ inputs:
run-unit-tests:
description: whether unit tests should run or not.
default: "false"
hermes-tarball-artifacts-dir:
description: The directory where the hermes tarball artifacts are stored
default: /tmp/hermes/hermes-runtime-darwin
flavor:
description: The flavor of the build. Must be one of "Debug", "Release".
default: Debug
hermes-version:
description: The version of hermes
required: true
react-native-version:
description: The version of react-native
required: true
run-e2e-tests:
description: Whether we want to run E2E tests or not
required: false
@@ -23,25 +32,60 @@ runs:
steps:
- name: Setup xcode
uses: ./.github/actions/setup-xcode
with:
platform: ios
- name: Setup node.js
uses: ./.github/actions/setup-node
- name: Run yarn
uses: ./.github/actions/yarn-install
- name: Download Hermes
uses: actions/download-artifact@v4
with:
name: hermes-darwin-bin-${{ inputs.flavor }}
path: ${{ inputs.hermes-tarball-artifacts-dir }}
- name: Setup ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ inputs.ruby-version }}
- name: Set nightly Hermes versions
shell: bash
run: |
node ./scripts/releases/use-hermes-nightly.js
- name: Run yarn install again, with the correct hermes version
uses: ./.github/actions/yarn-install
- name: Prepare IOS Tests
if: ${{ inputs.run-unit-tests == 'true' }}
uses: ./.github/actions/prepare-ios-tests
- name: Set HERMES_ENGINE_TARBALL_PATH envvar if Hermes tarball is present
shell: bash
run: |
HERMES_TARBALL_ARTIFACTS_DIR=${{ inputs.hermes-tarball-artifacts-dir }}
if [ ! -d $HERMES_TARBALL_ARTIFACTS_DIR ]; then
echo "Hermes tarball artifacts dir not present ($HERMES_TARBALL_ARTIFACTS_DIR). Build Hermes from source."
exit 0
fi
TARBALL_FILENAME=$(node ./packages/react-native/scripts/hermes/get-tarball-name.js --buildType "${{ inputs.flavor }}")
TARBALL_PATH=$HERMES_TARBALL_ARTIFACTS_DIR/$TARBALL_FILENAME
echo "Looking for $TARBALL_FILENAME in $HERMES_TARBALL_ARTIFACTS_DIR"
echo "$TARBALL_PATH"
if [ ! -f $TARBALL_PATH ]; then
echo "Hermes tarball not present ($TARBALL_PATH). Build Hermes from source."
exit 0
fi
echo "Found Hermes tarball at $TARBALL_PATH"
echo "HERMES_ENGINE_TARBALL_PATH=$TARBALL_PATH" >> $GITHUB_ENV
- name: Print Hermes version
shell: bash
run: |
HERMES_TARBALL_ARTIFACTS_DIR=${{ inputs.hermes-tarball-artifacts-dir }}
TARBALL_FILENAME=$(node ./packages/react-native/scripts/hermes/get-tarball-name.js --buildType "${{ inputs.flavor }}")
TARBALL_PATH=$HERMES_TARBALL_ARTIFACTS_DIR/$TARBALL_FILENAME
if [[ -e $TARBALL_PATH ]]; then
tar -xf $TARBALL_PATH
echo 'print(HermesInternal?.getRuntimeProperties?.()["OSS Release Version"])' > test.js
chmod +x ./destroot/bin/hermes
./destroot/bin/hermes test.js
rm test.js
rm -rf destroot
else
echo 'No Hermes tarball found.'
fi
- name: Download ReactNativeDependencies
uses: actions/download-artifact@v4
with:
@@ -61,6 +105,7 @@ runs:
- name: Install CocoaPods dependencies
shell: bash
run: |
export HERMES_ENGINE_TARBALL_PATH=$HERMES_ENGINE_TARBALL_PATH
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"
@@ -71,7 +116,7 @@ runs:
cd packages/rn-tester
bundle install
bundle exec pod update hermes-engine --no-repo-update
bundle exec pod install
- name: Build RNTester
shell: bash
run: |
@@ -121,7 +121,7 @@ describe('Create Draft Release', () => {
});
describe('#_computeBody', () => {
it('computes body for release when no hermes versions are passed', async () => {
it('computes body for release', async () => {
const version = '0.77.1';
const changelog = `## v${version}
### Breaking Changes
@@ -134,83 +134,20 @@ describe('Create Draft Release', () => {
#### iOS
- [PR #3436](https://github.com/facebook/react-native/pull/3436) - Some other change
- [PR #3437](https://github.com/facebook/react-native/pull/3437) - Some other change`;
const body = _computeBody(changelog, version);
const body = _computeBody(version, changelog);
expect(body).toEqual(`${changelog}
---
Hermes dSYMS:
- [Debug](https://repo1.maven.org/maven2/com/facebook/hermes/hermes-ios/${version}/hermes-ios-${version}-hermes-framework-dSYM-debug.tar.gz)
- [Release](https://repo1.maven.org/maven2/com/facebook/hermes/hermes-ios/${version}/hermes-ios-${version}-hermes-framework-dSYM-release.tar.gz)
Hermes V1 dSYMS:
- [Debug](https://repo1.maven.org/maven2/com/facebook/hermes/hermes-ios/${version}/hermes-ios-${version}-hermes-framework-dSYM-debug.tar.gz)
- [Release](https://repo1.maven.org/maven2/com/facebook/hermes/hermes-ios/${version}/hermes-ios-${version}-hermes-framework-dSYM-release.tar.gz)
- [Debug](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-hermes-framework-dSYM-debug.tar.gz)
- [Release](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-hermes-framework-dSYM-release.tar.gz)
ReactNativeDependencies dSYMs:
- [Debug](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-reactnative-dependencies-dSYM-debug.tar.gz)
- [Release](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-reactnative-dependencies-dSYM-release.tar.gz)
ReactNative Core dSYMs:
- [Debug](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-reactnative-core-debug.tar.gz)
- [Release](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-reactnative-core-release.tar.gz)
---
You can file issues or pick requests against this release [here](https://github.com/reactwg/react-native-releases/issues/new/choose).
---
To help you upgrade to this version, you can use the [Upgrade Helper](https://react-native-community.github.io/upgrade-helper/) ⚛️.
---
View the whole changelog in the [CHANGELOG.md file](https://github.com/facebook/react-native/blob/main/CHANGELOG.md).`);
});
it('computes body for release when hermes versions are passed', async () => {
const version = '0.77.1';
const hermesVersion = '0.15.0';
const hermesV1Version = '250829098.0.2';
const changelog = `## v${version}
### Breaking Changes
- [PR #9012](https://github.com/facebook/react-native/pull/9012) - Some other change
#### Android
- [PR #3456](https://github.com/facebook/react-native/pull/3456) - Some other change
- [PR #3457](https://github.com/facebook/react-native/pull/3457) - Some other change
#### iOS
- [PR #3436](https://github.com/facebook/react-native/pull/3436) - Some other change
- [PR #3437](https://github.com/facebook/react-native/pull/3437) - Some other change`;
const body = _computeBody(
changelog,
version,
hermesVersion,
hermesV1Version,
);
expect(body).toEqual(`${changelog}
---
Hermes dSYMS:
- [Debug](https://repo1.maven.org/maven2/com/facebook/hermes/hermes-ios/${hermesVersion}/hermes-ios-${hermesVersion}-hermes-framework-dSYM-debug.tar.gz)
- [Release](https://repo1.maven.org/maven2/com/facebook/hermes/hermes-ios/${hermesVersion}/hermes-ios-${hermesVersion}-hermes-framework-dSYM-release.tar.gz)
Hermes V1 dSYMS:
- [Debug](https://repo1.maven.org/maven2/com/facebook/hermes/hermes-ios/${hermesV1Version}/hermes-ios-${hermesV1Version}-hermes-framework-dSYM-debug.tar.gz)
- [Release](https://repo1.maven.org/maven2/com/facebook/hermes/hermes-ios/${hermesV1Version}/hermes-ios-${hermesV1Version}-hermes-framework-dSYM-release.tar.gz)
ReactNativeDependencies dSYMs:
- [Debug](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-reactnative-dependencies-dSYM-debug.tar.gz)
- [Release](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-reactnative-dependencies-dSYM-release.tar.gz)
ReactNative Core dSYMs:
- [Debug](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-reactnative-core-debug.tar.gz)
- [Release](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-reactnative-core-release.tar.gz)
---
You can file issues or pick requests against this release [here](https://github.com/reactwg/react-native-releases/issues/new/choose).
+5 -21
View File
@@ -40,29 +40,19 @@ function _extractChangelog(version) {
return changelog.slice(changelogStarts, changelogEnds).join('\n').trim();
}
function _computeBody(changelog, version, hermesVersion, hermesV1Version) {
hermesVersion = hermesVersion ?? version;
hermesV1Version = hermesV1Version ?? version;
function _computeBody(version, changelog) {
return `${changelog}
---
Hermes dSYMS:
- [Debug](https://repo1.maven.org/maven2/com/facebook/hermes/hermes-ios/${hermesVersion}/hermes-ios-${hermesVersion}-hermes-framework-dSYM-debug.tar.gz)
- [Release](https://repo1.maven.org/maven2/com/facebook/hermes/hermes-ios/${hermesVersion}/hermes-ios-${hermesVersion}-hermes-framework-dSYM-release.tar.gz)
Hermes V1 dSYMS:
- [Debug](https://repo1.maven.org/maven2/com/facebook/hermes/hermes-ios/${hermesV1Version}/hermes-ios-${hermesV1Version}-hermes-framework-dSYM-debug.tar.gz)
- [Release](https://repo1.maven.org/maven2/com/facebook/hermes/hermes-ios/${hermesV1Version}/hermes-ios-${hermesV1Version}-hermes-framework-dSYM-release.tar.gz)
- [Debug](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-hermes-framework-dSYM-debug.tar.gz)
- [Release](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-hermes-framework-dSYM-release.tar.gz)
ReactNativeDependencies dSYMs:
- [Debug](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-reactnative-dependencies-dSYM-debug.tar.gz)
- [Release](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-reactnative-dependencies-dSYM-release.tar.gz)
ReactNative Core dSYMs:
- [Debug](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-reactnative-core-debug.tar.gz)
- [Release](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-reactnative-core-release.tar.gz)
---
You can file issues or pick requests against this release [here](https://github.com/reactwg/react-native-releases/issues/new/choose).
@@ -123,13 +113,7 @@ function moveToChangelogBranch(version) {
run(`git checkout -b changelog/v${version}`);
}
async function createDraftRelease(
version,
latest,
token,
hermesVersion,
hermesV1Version,
) {
async function createDraftRelease(version, latest, token) {
if (version.startsWith('v')) {
version = version.substring(1);
}
@@ -137,7 +121,7 @@ async function createDraftRelease(
_verifyTagExists(version);
moveToChangelogBranch(version);
const changelog = _extractChangelog(version);
const body = _computeBody(changelog, version, hermesVersion, hermesV1Version);
const body = _computeBody(version, changelog);
const release = await _createDraftReleaseOnGitHub(
version,
body,
+1 -1
View File
@@ -162,7 +162,7 @@ async function main() {
console.info(`WORKING_DIRECTORY: ${WORKING_DIRECTORY}`);
console.info('==============================\n');
const simulatorName = 'iPhone 16 Pro';
const simulatorName = 'iPhone 15 Pro';
launchSimulator(simulatorName);
installAppOnSimulator(APP_PATH);
const udid = extractSimulatorUDID();
+1 -1
View File
@@ -21,7 +21,7 @@ jobs:
- name: Setup xcode
uses: ./.github/actions/setup-xcode
with:
platform: 'ios'
xcode-version: '16.2.0'
- name: Extract branch name
run: |
TAG="${{ github.ref_name }}";
+1 -10
View File
@@ -2,15 +2,6 @@ name: Create Draft Release
on:
workflow_call:
inputs:
hermesVersion:
required: false
type: string
description: The version of Hermes to use for this release (eg. 0.15.0). If not specified, it will use React Native Version
hermesV1Version:
required: false
type: string
description: The version of Hermes V1 to use for this release (eg. 250829098.0.2). If not specified, it will use React Native Version
jobs:
create-draft-release:
@@ -36,7 +27,7 @@ jobs:
const {createDraftRelease} = require('./.github/workflow-scripts/createDraftRelease.js');
const version = '${{ github.ref_name }}';
const {isLatest} = require('./.github/workflow-scripts/publishTemplate.js');
return (await createDraftRelease(version, isLatest(), '${{secrets.REACT_NATIVE_BOT_GITHUB_TOKEN}}', ${{ inputs.hermesVersion }}, ${{ inputs.hermesV1Version }})).id;
return (await createDraftRelease(version, isLatest(), '${{secrets.REACT_NATIVE_BOT_GITHUB_TOKEN}}')).id;
result-encoding: string
- name: Upload release assets for DotSlash
uses: actions/github-script@v6
+121 -3
View File
@@ -21,6 +21,86 @@ jobs:
echo "Setting release type to nightly"
echo "RELEASE_TYPE=nightly" >> $GITHUB_OUTPUT
prepare_hermes_workspace:
runs-on: ubuntu-latest
if: github.repository == 'facebook/react-native'
env:
HERMES_WS_DIR: /tmp/hermes
HERMES_VERSION_FILE: packages/react-native/sdks/.hermesversion
outputs:
react-native-version: ${{ steps.prepare-hermes-workspace.outputs.react-native-version }}
hermes-version: ${{ steps.prepare-hermes-workspace.outputs.hermes-version }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Prepare Hermes Workspace
id: prepare-hermes-workspace
uses: ./.github/actions/prepare-hermes-workspace
with:
hermes-ws-dir: ${{ env.HERMES_WS_DIR }}
hermes-version-file: ${{ env.HERMES_VERSION_FILE }}
build_hermesc_apple:
runs-on: macos-14
needs: prepare_hermes_workspace
env:
HERMES_WS_DIR: /tmp/hermes
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build HermesC Apple
uses: ./.github/actions/build-hermesc-apple
with:
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
build_apple_slices_hermes:
runs-on: macos-14
needs: [build_hermesc_apple, prepare_hermes_workspace]
env:
HERMES_WS_DIR: /tmp/hermes
HERMES_TARBALL_ARTIFACTS_DIR: /tmp/hermes/hermes-runtime-darwin
HERMES_OSXBIN_ARTIFACTS_DIR: /tmp/hermes/osx-bin
IOS_DEPLOYMENT_TARGET: "15.1"
XROS_DEPLOYMENT_TARGET: "1.0"
MAC_DEPLOYMENT_TARGET: "10.15"
strategy:
fail-fast: false
matrix:
flavor: [Debug, Release]
slice: [macosx, iphoneos, iphonesimulator, appletvos, appletvsimulator, catalyst, xros, xrsimulator]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build Slice
uses: ./.github/actions/build-apple-slices-hermes
with:
flavor: ${{ matrix.flavor }}
slice: ${{ matrix.slice }}
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
build_hermes_macos:
runs-on: macos-14
needs: [build_apple_slices_hermes, prepare_hermes_workspace]
env:
HERMES_WS_DIR: /tmp/hermes
HERMES_TARBALL_ARTIFACTS_DIR: /tmp/hermes/hermes-runtime-darwin
continue-on-error: true
strategy:
fail-fast: false
matrix:
flavor: [Debug, Release]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build Hermes MacOS
uses: ./.github/actions/build-hermes-macos
with:
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
flavor: ${{ matrix.flavor }}
prebuild_apple_dependencies:
if: github.repository == 'facebook/react-native'
uses: ./.github/workflows/prebuild-ios-dependencies.yml
@@ -28,10 +108,42 @@ jobs:
prebuild_react_native_core:
uses: ./.github/workflows/prebuild-ios-core.yml
with:
use-hermes-nightly: true
secrets: inherit
needs: [prebuild_apple_dependencies]
needs: [prebuild_apple_dependencies, build_hermes_macos]
build_hermesc_linux:
runs-on: ubuntu-latest
needs: prepare_hermes_workspace
env:
HERMES_WS_DIR: /tmp/hermes
HERMES_TARBALL_ARTIFACTS_DIR: /tmp/hermes/hermes-runtime-darwin
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build HermesC Linux
uses: ./.github/actions/build-hermesc-linux
with:
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
build_hermesc_windows:
runs-on: windows-2025
needs: prepare_hermes_workspace
env:
HERMES_WS_DIR: 'C:\tmp\hermes'
HERMES_TARBALL_ARTIFACTS_DIR: 'C:\tmp\hermes\hermes-runtime-darwin'
HERMES_OSXBIN_ARTIFACTS_DIR: 'C:\tmp\hermes\osx-bin'
ICU_URL: "https://github.com/unicode-org/icu/releases/download/release-64-2/icu4c-64_2-Win64-MSVC2017.zip"
MSBUILD_DIR: 'C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin'
CMAKE_DIR: 'C:\Program Files\CMake\bin'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build HermesC Windows
uses: ./.github/actions/build-hermesc-windows
with:
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
build_android:
runs-on: 8-core-ubuntu
@@ -60,6 +172,10 @@ jobs:
needs:
[
set_release_type,
prepare_hermes_workspace,
build_hermes_macos,
build_hermesc_linux,
build_hermesc_windows,
build_android,
prebuild_apple_dependencies,
prebuild_react_native_core,
@@ -72,6 +188,7 @@ jobs:
# By default we only build ARM64 to save time/resources. For release/nightlies, we override this value to build all archs.
ORG_GRADLE_PROJECT_reactNativeArchitectures: "arm64-v8a"
env:
HERMES_WS_DIR: /tmp/hermes
GHA_NPM_TOKEN: ${{ secrets.GHA_NPM_TOKEN }}
ORG_GRADLE_PROJECT_SIGNING_PWD: ${{ secrets.ORG_GRADLE_PROJECT_SIGNING_PWD }}
ORG_GRADLE_PROJECT_SIGNING_KEY: ${{ secrets.ORG_GRADLE_PROJECT_SIGNING_KEY }}
@@ -83,6 +200,7 @@ jobs:
- name: Build and Publish NPM Package
uses: ./.github/actions/build-npm-package
with:
hermes-ws-dir: ${{ env.HERMES_WS_DIR }}
release-type: ${{ needs.set_release_type.outputs.RELEASE_TYPE }}
gha-npm-token: ${{ env.GHA_NPM_TOKEN }}
gradle-cache-encryption-key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }}
+30 -16
View File
@@ -2,16 +2,11 @@ name: Prebuild iOS Dependencies
on:
workflow_call: # this directive allow us to call this workflow from other workflows
inputs:
use-hermes-nightly:
description: 'Whether to use the hermes nightly build or read the version from the versions.properties file'
type: boolean
required: false
default: false
jobs:
build-rn-slice:
runs-on: macos-15
runs-on: macos-14
strategy:
fail-fast: false
matrix:
@@ -37,20 +32,39 @@ jobs:
if: steps.restore-ios-slice.outputs.cache-hit != 'true'
uses: ./.github/actions/setup-xcode
with:
platform: ${{ matrix.slice }}
xcode-version: '16.2.0'
- name: Yarn Install
if: steps.restore-ios-slice.outputs.cache-hit != 'true'
uses: ./.github/actions/yarn-install
- name: Set Hermes version
- name: Download Hermes
if: steps.restore-ios-slice.outputs.cache-hit != 'true'
uses: actions/download-artifact@v4
with:
name: hermes-darwin-bin-${{ matrix.flavor }}
path: /tmp/hermes/hermes-runtime-darwin
- name: Extract Hermes
if: steps.restore-ios-slice.outputs.cache-hit != 'true'
shell: bash
run: |
if [ "${{ inputs.use-hermes-nightly }}" == "true" ]; then
HERMES_VERSION="nightly"
else
HERMES_VERSION=$(sed -n 's/^HERMES_VERSION_NAME=//p' packages/react-native/sdks/hermes-engine/version.properties)
HERMES_TARBALL_ARTIFACTS_DIR=/tmp/hermes/hermes-runtime-darwin
if [ ! -d $HERMES_TARBALL_ARTIFACTS_DIR ]; then
echo "Hermes tarball artifacts dir not present ($HERMES_TARBALL_ARTIFACTS_DIR)."
exit 0
fi
echo "Using Hermes version: $HERMES_VERSION"
echo "HERMES_VERSION=$HERMES_VERSION" >> $GITHUB_ENV
TARBALL_FILENAME=$(node ./packages/react-native/scripts/hermes/get-tarball-name.js --buildType "${{ matrix.flavor }}")
TARBALL_PATH=$HERMES_TARBALL_ARTIFACTS_DIR/$TARBALL_FILENAME
echo "Looking for $TARBALL_FILENAME in $HERMES_TARBALL_ARTIFACTS_DIR"
echo "$TARBALL_PATH"
if [ ! -f $TARBALL_PATH ]; then
echo "Hermes tarball not present ($TARBALL_PATH). Build Hermes from source."
exit 0
fi
echo "Found Hermes tarball at $TARBALL_PATH"
echo "HERMES_ENGINE_TARBALL_PATH=$TARBALL_PATH" >> $GITHUB_ENV
- name: Download ReactNativeDependencies
uses: actions/download-artifact@v4
with:
@@ -109,7 +123,7 @@ jobs:
packages/react-native/.build/headers
compose-xcframework:
runs-on: macos-15
runs-on: macos-14
needs: [build-rn-slice]
strategy:
fail-fast: false
+21 -15
View File
@@ -7,7 +7,7 @@ on:
jobs:
prepare_workspace:
name: Prepare workspace
runs-on: macos-15
runs-on: macos-14
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -18,7 +18,7 @@ jobs:
uses: actions/cache/restore@v4
with:
path: packages/react-native/third-party/
key: v3-ios-dependencies-${{ hashfiles('scripts/releases/ios-prebuild/configuration.js') }}
key: v2-ios-dependencies-${{ hashfiles('scripts/releases/ios-prebuild/configuration.js') }}
enableCrossOsArchive: true
- name: Yarn Install
if: steps.restore-ios-prebuilds.outputs.cache-hit != 'true'
@@ -40,13 +40,13 @@ jobs:
uses: actions/cache/save@v4
if: ${{ github.ref == 'refs/heads/main' }} # To avoid that the cache explode
with:
key: v3-ios-dependencies-${{ hashfiles('scripts/releases/ios-prebuild/configuration.js') }}
key: v2-ios-dependencies-${{ hashfiles('scripts/releases/ios-prebuild/configuration.js') }}
enableCrossOsArchive: true
path: packages/react-native/third-party/
build-apple-slices:
name: Build Apple Slice
runs-on: macos-15
runs-on: macos-14
needs: [prepare_workspace]
strategy:
fail-fast: false
@@ -65,17 +65,16 @@ jobs:
uses: actions/checkout@v4
- name: Setup node.js
uses: ./.github/actions/setup-node
- name: Setup xcode
uses: ./.github/actions/setup-xcode
with:
xcode-version: '16.1'
- name: Restore slice folder
id: restore-slice-folder
uses: actions/cache/restore@v4
with:
path: packages/react-native/third-party/.build/Build/Products
key: v3-ios-dependencies-slice-folder-${{ matrix.slice }}-${{ matrix.flavor }}-${{ hashfiles('scripts/releases/ios-prebuild/configuration.js') }}
- name: Setup xcode
if: steps.restore-slice-folder.outputs.cache-hit != 'true'
uses: ./.github/actions/setup-xcode
with:
platform: ${{ matrix.slice }}
key: v2-ios-dependencies-slice-folder-${{ matrix.slice }}-${{ matrix.flavor }}-${{ hashfiles('scripts/releases/ios-prebuild/configuration.js') }}
- name: Yarn Install
if: steps.restore-slice-folder.outputs.cache-hit != 'true'
uses: ./.github/actions/yarn-install
@@ -86,8 +85,15 @@ jobs:
name: ios-prebuilds-workspace
path: packages/react-native/third-party/
- name: Print third-party folder structure
if: steps.restore-slice-folder.outputs.cache-hit != 'true'
run: ls -lR packages/react-native/third-party
- name: Install VisionOS
if: ${{ steps.restore-slice-folder.outputs.cache-hit != 'true' && (matrix.slice == 'xros' || matrix.slice == 'xros-simulator') }}
run: |
# https://github.com/actions/runner-images/issues/10559
sudo xcodebuild -runFirstLaunch
sudo xcrun simctl list
sudo xcodebuild -downloadPlatform visionOS
sudo xcodebuild -runFirstLaunch
- name: Build slice ${{ matrix.slice }} for ${{ matrix.flavor }}
if: steps.restore-slice-folder.outputs.cache-hit != 'true'
run: node scripts/releases/prepare-ios-prebuilds.js -b -p ${{ matrix.slice }} -r ${{ matrix.flavor }}
@@ -101,14 +107,14 @@ jobs:
uses: actions/cache/save@v4
if: ${{ github.ref == 'refs/heads/main' }} # To avoid that the cache explode
with:
key: v3-ios-dependencies-slice-folder-${{ matrix.slice }}-${{ matrix.flavor }}-${{ hashfiles('scripts/releases/ios-prebuild/configuration.js') }}
key: v2-ios-dependencies-slice-folder-${{ matrix.slice }}-${{ matrix.flavor }}-${{ hashfiles('scripts/releases/ios-prebuild/configuration.js') }}
enableCrossOsArchive: true
path: |
packages/react-native/third-party/.build/Build/Products
create-xcframework:
name: Prepare XCFramework
runs-on: macos-15
runs-on: macos-14
needs: [build-apple-slices]
strategy:
fail-fast: false
@@ -132,7 +138,7 @@ jobs:
with:
path: |
packages/react-native/third-party/
key: v3-ios-dependencies-xcframework-${{ matrix.flavor }}-${{ hashfiles('scripts/releases/ios-prebuild/configuration.js') }}
key: v2-ios-dependencies-xcframework-${{ matrix.flavor }}-${{ hashfiles('scripts/releases/ios-prebuild/configuration.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'
@@ -194,4 +200,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: v2-ios-dependencies-xcframework-${{ matrix.flavor }}-${{ hashfiles('scripts/releases/ios-prebuild/configuration.js') }}
+113 -19
View File
@@ -19,27 +19,84 @@ jobs:
echo "Setting release type to release"
echo "RELEASE_TYPE=release" >> $GITHUB_OUTPUT
set_hermes_versions:
prepare_hermes_workspace:
runs-on: ubuntu-latest
if: github.repository == 'facebook/react-native'
env:
HERMES_WS_DIR: /tmp/hermes
HERMES_VERSION_FILE: packages/react-native/sdks/.hermesversion
outputs:
HERMES_VERSION: ${{ steps.set_hermes_versions.outputs.HERMES_VERSION }}
HERMES_V1_VERSION: ${{ steps.set_hermes_versions.outputs.HERMES_V1_VERSION }}
react-native-version: ${{ steps.prepare-hermes-workspace.outputs.react-native-version }}
hermes-version: ${{ steps.prepare-hermes-workspace.outputs.hermes-version }}
steps:
- name: Checkout
uses: actions/checkout@v4
- id: set_hermes_versions
run: |
echo "Setting hermes versions to latest"
hermes_version=$(grep -oE 'HERMES_VERSION_NAME=([0-9]+\.[0-9]+\.[0-9]+)' packages/react-native/sdks/hermes-engine/version.properties | cut -d'=' -f2)
hermes_v1_version=$(grep -oE 'HERMES_V1_VERSION_NAME=([0-9]+\.[0-9]+\.[0-9]+)' packages/react-native/sdks/hermes-engine/version.properties | cut -d'=' -f2)
- name: Prepare Hermes Workspace
id: prepare-hermes-workspace
uses: ./.github/actions/prepare-hermes-workspace
with:
hermes-ws-dir: ${{ env.HERMES_WS_DIR }}
hermes-version-file: ${{ env.HERMES_VERSION_FILE }}
echo "HERMES_VERSION=$hermes_version" >> $GITHUB_OUTPUT
echo "HERMES_V1_VERSION=$hermes_v1_version" >> $GITHUB_OUTPUT
- name: Print hermes versions
run: |
echo "HERMES_VERSION=${{ steps.set_hermes_versions.outputs.HERMES_VERSION }}"
echo "HERMES_V1_VERSION=${{ steps.set_hermes_versions.outputs.HERMES_V1_VERSION }}"
build_hermesc_apple:
runs-on: macos-14
needs: prepare_hermes_workspace
env:
HERMES_WS_DIR: /tmp/hermes
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build HermesC Apple
uses: ./.github/actions/build-hermesc-apple
with:
hermes-version: ${{ needs.prepare_hermes_workspace.output.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.output.react-native-version }}
build_apple_slices_hermes:
runs-on: macos-14
needs: [build_hermesc_apple, prepare_hermes_workspace]
env:
HERMES_WS_DIR: /tmp/hermes
HERMES_TARBALL_ARTIFACTS_DIR: /tmp/hermes/hermes-runtime-darwin
HERMES_OSXBIN_ARTIFACTS_DIR: /tmp/hermes/osx-bin
IOS_DEPLOYMENT_TARGET: "15.1"
XROS_DEPLOYMENT_TARGET: "1.0"
MAC_DEPLOYMENT_TARGET: "10.15"
strategy:
fail-fast: false
matrix:
flavor: [Debug, Release]
slice: [macosx, iphoneos, iphonesimulator, appletvos, appletvsimulator, catalyst, xros, xrsimulator]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build Slice
uses: ./.github/actions/build-apple-slices-hermes
with:
flavor: ${{ matrix.flavor }}
slice: ${{ matrix.slice}}
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
build_hermes_macos:
runs-on: macos-14
needs: [build_apple_slices_hermes, prepare_hermes_workspace]
env:
HERMES_WS_DIR: /tmp/hermes
HERMES_TARBALL_ARTIFACTS_DIR: /tmp/hermes/hermes-runtime-darwin
continue-on-error: true
strategy:
fail-fast: false
matrix:
flavor: [Debug, Release]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build Hermes MacOS
uses: ./.github/actions/build-hermes-macos
with:
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
flavor: ${{ matrix.flavor }}
prebuild_apple_dependencies:
if: github.repository == 'facebook/react-native'
@@ -49,13 +106,51 @@ jobs:
prebuild_react_native_core:
uses: ./.github/workflows/prebuild-ios-core.yml
secrets: inherit
needs: [prebuild_apple_dependencies]
needs: [prebuild_apple_dependencies, build_hermes_macos]
build_hermesc_linux:
runs-on: ubuntu-latest
needs: prepare_hermes_workspace
env:
HERMES_WS_DIR: /tmp/hermes
HERMES_TARBALL_ARTIFACTS_DIR: /tmp/hermes/hermes-runtime-darwin
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build HermesC Linux
uses: ./.github/actions/build-hermesc-linux
with:
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
build_hermesc_windows:
runs-on: windows-2025
needs: prepare_hermes_workspace
env:
HERMES_WS_DIR: 'C:\tmp\hermes'
HERMES_TARBALL_ARTIFACTS_DIR: 'C:\tmp\hermes\hermes-runtime-darwin'
HERMES_OSXBIN_ARTIFACTS_DIR: 'C:\tmp\hermes\osx-bin'
ICU_URL: "https://github.com/unicode-org/icu/releases/download/release-64-2/icu4c-64_2-Win64-MSVC2017.zip"
MSBUILD_DIR: 'C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin'
CMAKE_DIR: 'C:\Program Files\CMake\bin'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build HermesC Windows
uses: ./.github/actions/build-hermesc-windows
with:
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
build_npm_package:
runs-on: 8-core-ubuntu
needs:
[
set_release_type,
prepare_hermes_workspace,
build_hermes_macos,
build_hermesc_linux,
build_hermesc_windows,
prebuild_apple_dependencies,
prebuild_react_native_core,
]
@@ -67,6 +162,7 @@ jobs:
# By default we only build ARM64 to save time/resources. For release/nightlies, we override this value to build all archs.
ORG_GRADLE_PROJECT_reactNativeArchitectures: "arm64-v8a"
env:
HERMES_WS_DIR: /tmp/hermes
GHA_NPM_TOKEN: ${{ secrets.GHA_NPM_TOKEN }}
ORG_GRADLE_PROJECT_SIGNING_PWD: ${{ secrets.ORG_GRADLE_PROJECT_SIGNING_PWD }}
ORG_GRADLE_PROJECT_SIGNING_KEY: ${{ secrets.ORG_GRADLE_PROJECT_SIGNING_KEY }}
@@ -82,6 +178,7 @@ jobs:
- name: Build and Publish NPM Package
uses: ./.github/actions/build-npm-package
with:
hermes-ws-dir: ${{ env.HERMES_WS_DIR }}
release-type: ${{ needs.set_release_type.outputs.RELEASE_TYPE }}
gha-npm-token: ${{ env.GHA_NPM_TOKEN }}
gradle-cache-encryption-key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }}
@@ -139,9 +236,6 @@ jobs:
secrets: inherit
create_draft_release:
needs: [generate_changelog, set_hermes_versions]
needs: generate_changelog
uses: ./.github/workflows/create-draft-release.yml
secrets: inherit
with:
hermesVersion: ${{ needs.set_hermes_versions.outputs.HERMES_VERSION }}
hermesV1Version: ${{ needs.set_hermes_versions.outputs.HERMES_V1_VERSION }}
+163 -24
View File
@@ -33,6 +33,86 @@ jobs:
echo "Should I run E2E tests? ${{ inputs.run-e2e-tests }}"
prepare_hermes_workspace:
runs-on: ubuntu-latest
if: github.repository == 'facebook/react-native'
env:
HERMES_WS_DIR: /tmp/hermes
HERMES_VERSION_FILE: packages/react-native/sdks/.hermesversion
outputs:
react-native-version: ${{ steps.prepare-hermes-workspace.outputs.react-native-version }}
hermes-version: ${{ steps.prepare-hermes-workspace.outputs.hermes-version }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Prepare Hermes Workspace
id: prepare-hermes-workspace
uses: ./.github/actions/prepare-hermes-workspace
with:
hermes-ws-dir: ${{ env.HERMES_WS_DIR }}
hermes-version-file: ${{ env.HERMES_VERSION_FILE }}
build_hermesc_apple:
runs-on: macos-14
needs: prepare_hermes_workspace
env:
HERMES_WS_DIR: /tmp/hermes
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build HermesC Apple
uses: ./.github/actions/build-hermesc-apple
with:
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
build_apple_slices_hermes:
runs-on: macos-14
needs: [build_hermesc_apple, prepare_hermes_workspace]
env:
HERMES_WS_DIR: /tmp/hermes
HERMES_TARBALL_ARTIFACTS_DIR: /tmp/hermes/hermes-runtime-darwin
HERMES_OSXBIN_ARTIFACTS_DIR: /tmp/hermes/osx-bin
IOS_DEPLOYMENT_TARGET: "15.1"
XROS_DEPLOYMENT_TARGET: "1.0"
MAC_DEPLOYMENT_TARGET: "10.15"
strategy:
fail-fast: false
matrix:
flavor: [Debug, Release]
slice: [macosx, iphoneos, iphonesimulator, appletvos, appletvsimulator, catalyst, xros, xrsimulator]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build Slice
uses: ./.github/actions/build-apple-slices-hermes
with:
flavor: ${{ matrix.flavor }}
slice: ${{ matrix.slice}}
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
build_hermes_macos:
runs-on: macos-14
needs: [build_apple_slices_hermes, prepare_hermes_workspace]
env:
HERMES_WS_DIR: /tmp/hermes
HERMES_TARBALL_ARTIFACTS_DIR: /tmp/hermes/hermes-runtime-darwin
continue-on-error: true
strategy:
fail-fast: false
matrix:
flavor: [Debug, Release]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build Hermes MacOS
uses: ./.github/actions/build-hermes-macos
with:
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
flavor: ${{ matrix.flavor }}
prebuild_apple_dependencies:
if: github.repository == 'facebook/react-native'
uses: ./.github/workflows/prebuild-ios-dependencies.yml
@@ -40,15 +120,16 @@ jobs:
prebuild_react_native_core:
uses: ./.github/workflows/prebuild-ios-core.yml
with:
use-hermes-nightly: ${{ !endsWith(github.ref_name, '-stable') }}
secrets: inherit
needs: [prebuild_apple_dependencies]
needs: [prebuild_apple_dependencies, build_hermes_macos]
test_ios_rntester_ruby_3_2_0:
runs-on: macos-15
runs-on: macos-14
needs:
[prebuild_apple_dependencies, prebuild_react_native_core]
[build_apple_slices_hermes, prepare_hermes_workspace, build_hermes_macos, prebuild_apple_dependencies, prebuild_react_native_core]
env:
HERMES_WS_DIR: /tmp/hermes
HERMES_TARBALL_ARTIFACTS_DIR: /tmp/hermes/hermes-runtime-darwin
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -56,12 +137,17 @@ jobs:
uses: ./.github/actions/test-ios-rntester
with:
ruby-version: "3.2.0"
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
flavor: Debug
test_ios_rntester:
runs-on: macos-15-large
runs-on: macos-14-large
needs:
[prebuild_apple_dependencies, prebuild_react_native_core]
[build_apple_slices_hermes, prepare_hermes_workspace, build_hermes_macos, prebuild_apple_dependencies, prebuild_react_native_core]
env:
HERMES_WS_DIR: /tmp/hermes
HERMES_TARBALL_ARTIFACTS_DIR: /tmp/hermes/hermes-runtime-darwin
continue-on-error: true
strategy:
fail-fast: false
@@ -75,12 +161,17 @@ jobs:
uses: ./.github/actions/test-ios-rntester
with:
use-frameworks: ${{ matrix.frameworks }}
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
flavor: ${{ matrix.flavor }}
test_e2e_ios_rntester:
runs-on: macos-15-large
runs-on: macos-14-large
needs:
[test_ios_rntester]
env:
HERMES_WS_DIR: /tmp/hermes
HERMES_TARBALL_ARTIFACTS_DIR: /tmp/hermes/hermes-runtime-darwin
strategy:
fail-fast: false
matrix:
@@ -99,8 +190,6 @@ jobs:
run: ls -lR /tmp/RNTesterBuild
- name: Setup xcode
uses: ./.github/actions/setup-xcode
with:
platform: ios
- name: Run E2E Tests
uses: ./.github/actions/maestro-ios
with:
@@ -110,8 +199,11 @@ jobs:
flavor: ${{ matrix.flavor }}
test_e2e_ios_templateapp:
runs-on: macos-15-large
runs-on: macos-14-large
needs: [build_npm_package, prebuild_apple_dependencies]
env:
HERMES_WS_DIR: /tmp/hermes
HERMES_TARBALL_ARTIFACTS_DIR: /tmp/hermes/hermes-runtime-darwin
strategy:
fail-fast: false
matrix:
@@ -121,8 +213,6 @@ jobs:
uses: actions/checkout@v4
- name: Setup xcode
uses: ./.github/actions/setup-xcode
with:
platform: ios
- name: Setup node.js
uses: ./.github/actions/setup-node
- name: Run yarn
@@ -131,6 +221,11 @@ jobs:
uses: ruby/setup-ruby@v1
with:
ruby-version: 2.6.10
- name: Download Hermes
uses: actions/download-artifact@v4
with:
name: hermes-darwin-bin-${{matrix.flavor}}
path: /tmp/react-native-tmp
- name: Download React Native Package
uses: actions/download-artifact@v4
with:
@@ -164,6 +259,9 @@ jobs:
REACT_NATIVE_PKG=$(find /tmp/react-native-tmp -type f -name "*.tgz")
echo "React Native tgs is $REACT_NATIVE_PKG"
HERMES_PATH=$(find /tmp/react-native-tmp -type f -name "*.tar.gz")
echo "Hermes path is $HERMES_PATH"
# For stable branches, we want to use the stable branch of the template
# In all the other cases, we want to use "main"
BRANCH=${{ github.ref_name }}
@@ -180,7 +278,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"
RCT_NEW_ARCH_ENABLED=$NEW_ARCH_ENABLED bundle exec pod install
HERMES_ENGINE_TARBALL_PATH=$HERMES_PATH RCT_NEW_ARCH_ENABLED=$NEW_ARCH_ENABLED bundle exec pod install
xcodebuild \
-scheme "RNTestProject" \
@@ -266,6 +364,21 @@ jobs:
flavor: ${{ matrix.flavor }}
working-directory: /tmp/RNTestProject
build_hermesc_linux:
runs-on: ubuntu-latest
needs: prepare_hermes_workspace
env:
HERMES_WS_DIR: /tmp/hermes
HERMES_TARBALL_ARTIFACTS_DIR: /tmp/hermes/hermes-runtime-darwin
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build HermesC Linux
uses: ./.github/actions/build-hermesc-linux
with:
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
run_fantom_tests:
runs-on: 8-core-ubuntu
needs: [set_release_type]
@@ -285,6 +398,25 @@ jobs:
release-type: ${{ needs.set_release_type.outputs.RELEASE_TYPE }}
gradle-cache-encryption-key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }}
build_hermesc_windows:
runs-on: windows-2025
needs: prepare_hermes_workspace
env:
HERMES_WS_DIR: 'C:\tmp\hermes'
HERMES_TARBALL_ARTIFACTS_DIR: 'C:\tmp\hermes\hermes-runtime-darwin'
HERMES_OSXBIN_ARTIFACTS_DIR: 'C:\tmp\hermes\osx-bin'
ICU_URL: "https://github.com/unicode-org/icu/releases/download/release-64-2/icu4c-64_2-Win64-MSVC2017.zip"
MSBUILD_DIR: 'C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin'
CMAKE_DIR: 'C:\Program Files\CMake\bin'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build HermesC Windows
uses: ./.github/actions/build-hermesc-windows
with:
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
build_android:
runs-on: 8-core-ubuntu
needs: [set_release_type]
@@ -339,6 +471,10 @@ jobs:
needs:
[
set_release_type,
prepare_hermes_workspace,
build_hermes_macos,
build_hermesc_linux,
build_hermesc_windows,
build_android,
prebuild_apple_dependencies,
prebuild_react_native_core,
@@ -348,12 +484,15 @@ jobs:
env:
TERM: "dumb"
GRADLE_OPTS: "-Dorg.gradle.daemon=false"
env:
HERMES_WS_DIR: /tmp/hermes
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build NPM Package
uses: ./.github/actions/build-npm-package
with:
hermes-ws-dir: ${{ env.HERMES_WS_DIR }}
release-type: ${{ needs.set_release_type.outputs.RELEASE_TYPE }}
gradle-cache-encryption-key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }}
@@ -396,12 +535,6 @@ jobs:
cache-encryption-key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }}
- name: Run yarn install
uses: ./.github/actions/yarn-install
- name: Set nightly Hermes versions
shell: bash
run: |
node ./scripts/releases/use-hermes-nightly.js
- name: Run yarn install again, with the correct hermes version
uses: ./.github/actions/yarn-install
- name: Prepare the Helloworld application
shell: bash
run: node ./scripts/e2e/init-project-e2e.js --useHelloWorld --pathToLocalReactNative "$GITHUB_WORKSPACE/build/$(cat build/react-native-package-version)"
@@ -422,10 +555,11 @@ jobs:
compression-level: 0
test_ios_helloworld_with_ruby_3_2_0:
runs-on: macos-15
needs: [prebuild_apple_dependencies, prebuild_react_native_core]
runs-on: macos-14
needs: [prepare_hermes_workspace, build_hermes_macos, prebuild_apple_dependencies, prebuild_react_native_core] # prepare_hermes_workspace must be there because we need its reference to retrieve a couple of outputs
env:
PROJECT_NAME: iOSTemplateProject
HERMES_WS_DIR: /tmp/hermes
YARN_ENABLE_IMMUTABLE_INSTALLS: false
steps:
- name: Checkout
@@ -434,10 +568,12 @@ jobs:
with:
ruby-version: 3.2.0
flavor: Debug
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
test_ios_helloworld:
runs-on: macos-15
needs: [prebuild_apple_dependencies, prebuild_react_native_core]
runs-on: macos-14
needs: [prepare_hermes_workspace, build_hermes_macos, prebuild_apple_dependencies, prebuild_react_native_core] # prepare_hermes_workspace must be there because we need its reference to retrieve a couple of outputs
strategy:
matrix:
flavor: [Debug, Release]
@@ -448,6 +584,7 @@ jobs:
use_frameworks: StaticLibraries
env:
PROJECT_NAME: iOSTemplateProject
HERMES_WS_DIR: /tmp/hermes
YARN_ENABLE_IMMUTABLE_INSTALLS: false
steps:
- name: Checkout
@@ -456,6 +593,8 @@ jobs:
with:
flavor: ${{ matrix.flavor }}
use-frameworks: ${{ matrix.use_frameworks }}
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
test_js:
runs-on: ubuntu-latest
-9
View File
@@ -1,14 +1,5 @@
# Changelog (pre 0.80)
## v0.79.7
### Fixed
#### Android specific
- **Layout:** Make missing parent view state in updateLayout a soft error ([56ad8d9bfd](https://github.com/facebook/react-native/commit/56ad8d9bfd08ea70bc6f5726a2b4a6afb6d2d7c2) by [@javache](https://github.com/javache))
- **Layout:** Make missing parent view state in updateLayout a soft error ([f2e47d8dab](https://github.com/facebook/react-native/commit/f2e47d8dabcd61621ea81c86cd1e2488948c4229) by [@cipolleschi](https://github.com/cipolleschi))
## v0.79.6
### Added
-16
View File
@@ -1,17 +1,5 @@
# Changelog
## v0.82.1
### Fixed
#### Android specific
- Fixed representation of transforms when view is originally zero-sized ([a81e94a40c](https://github.com/facebook/react-native/commit/a81e94a40ca8dca9e57b562db21f8f235c5b25a0) by [@javache](https://github.com/javache))
#### iOS specific
- Fixed issue when using gnu coreutils cp command when using precompiled binaries causing compilation error ([068ec39aea](https://github.com/facebook/react-native/commit/068ec39aea543617e5159fe22274b294bfb29026) by [@chrfalch](https://github.com/chrfalch))
## v0.82.0
### Breaking
@@ -824,10 +812,6 @@
- **Text:** Selection range not respected when changing text or selection when selection is forced ([d32ea66e6a](https://github.com/facebook/react-native/commit/d32ea66e6a945dd84092532401b265b12d482668) by Olivier Bouillet)
- **TextInput:** Fix TextInput `onContentSizeChange` event being dispatched only once on iOS on the new architecture ([5fd5188172](https://github.com/facebook/react-native/commit/5fd51881727b2d86f87abf04db032940ac0ec8c4) by [@j-piasecki](https://github.com/j-piasecki))
## v0.79.7
See [CHANGELOG-0.7x](./CHANGELOG-0.7x.md#v0797)
## v0.79.6
See [CHANGELOG-0.7x](./CHANGELOG-0.7x.md#v0796)
+6 -1
View File
@@ -104,6 +104,10 @@ tasks.register("build") {
tasks.register("publishAllToMavenTempLocal") {
description = "Publish all the artifacts to be available inside a Maven Local repository on /tmp."
dependsOn(":packages:react-native:ReactAndroid:publishAllPublicationsToMavenTempLocalRepository")
// We don't publish the external-artifacts to Maven Local as ci is using it via workspace.
dependsOn(
":packages:react-native:ReactAndroid:hermes-engine:publishAllPublicationsToMavenTempLocalRepository"
)
}
tasks.register("publishAndroidToSonatype") {
@@ -131,7 +135,8 @@ if (project.findProperty("react.internal.useHermesNightly")?.toString()?.toBoole
configurations.all {
resolutionStrategy.dependencySubstitution {
substitute(project(":packages:react-native:ReactAndroid:hermes-engine"))
.using(module("com.facebook.hermes:hermes-android:0.+"))
// TODO: T237406039 update coordinates
.using(module("com.facebook.react:hermes-android:0.+"))
.because("Users opted to use hermes from nightly")
}
}
-7
View File
@@ -4,13 +4,6 @@ org.gradle.caching=true
android.useAndroidX=true
# Those 2 properties are needed to make our project compatible with
# AGP 9.0.0 for the time being. Ideally we should not opt-out of
# builtInKotlin and newDsl once AGP 9.0.0 hits stable.
# More on this: https://developer.android.com/build/releases/agp-preview#android-gradle-plugin-built-in-kotlin
android.builtInKotlin=false
android.newDsl=false
# Use this property to specify which architecture you want to build.
# You can also override it from the CLI using
# ./gradlew <task> -PreactNativeArchitectures=x86_64
+5 -4
View File
@@ -86,7 +86,7 @@
"eslint-plugin-relay": "^1.8.3",
"fb-dotslash": "0.5.8",
"flow-api-translator": "0.32.0",
"flow-bin": "^0.289.0",
"flow-bin": "^0.287.0",
"glob": "^7.1.1",
"hermes-eslint": "0.32.0",
"hermes-transform": "0.32.0",
@@ -108,8 +108,8 @@
"nullthrows": "^1.1.1",
"prettier": "3.6.2",
"prettier-plugin-hermes-parser": "0.32.0",
"react": "19.2.0",
"react-test-renderer": "19.2.0",
"react": "19.1.1",
"react-test-renderer": "19.1.1",
"rimraf": "^3.0.2",
"shelljs": "^0.8.5",
"signedsource": "^2.0.0",
@@ -120,7 +120,8 @@
"ws": "^7.5.10"
},
"resolutions": {
"react-is": "19.2.0",
"eslint-plugin-react-hooks": "6.1.0-canary-12bc60f5-20250613",
"react-is": "19.1.1",
"on-headers": "1.1.0",
"compression": "1.8.1"
}
+2 -2
View File
@@ -1,5 +1,5 @@
@generated SignedSource<<4bb67766e15e25a481c4c38873260a7a>>
Git revision: 7aa57d13e50ce9d74a91c9315c9b0ded00fbc19f
@generated SignedSource<<e0cc45c5c3854d0d3013f1c735e804b8>>
Git revision: 8cce39003f66f66a8fb4c0e581a2b5046cf9c1d1
Built with --nohooks: false
Is local checkout: false
Remote URL: https://github.com/facebook/react-native-devtools-frontend
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
import*as e from"../root/root.js";const t=e.Runtime.RNExperimentName,i={didInitializeExperiments:!1,isReactNativeEntryPoint:!1};class n{name;title;unstable;docLink;feedbackLink;enabledByDefault;constructor(e){this.name=e.name,this.title=e.title,this.unstable=e.unstable,this.docLink=e.docLink,this.feedbackLink=e.feedbackLink,this.enabledByDefault=function(e,t){if(null==e)return()=>t;if("boolean"==typeof e)return()=>e;return e}(e.enabledByDefault,!1)}}const r=new class{#e=new Map;#t=new Set;register(e){if(i.didInitializeExperiments)throw new Error("Experiments must be registered before constructing MainImpl");const{name:t}=e;if(this.#e.has(t))throw new Error(`React Native Experiment ${t} is already registered`);this.#e.set(t,new n(e))}enableExperimentsByDefault(e){if(i.didInitializeExperiments)throw new Error("Experiments must be configured before constructing MainImpl");for(const i of e)if(Object.prototype.hasOwnProperty.call(t,i)){const e=this.#e.get(i);if(!e)throw new Error(`React Native Experiment ${i} is not registered`);e.enabledByDefault=()=>!0}else this.#t.add(i)}copyInto(e,t=""){for(const[n,r]of this.#e)e.register(n,t+r.title,r.unstable,r.docLink,r.feedbackLink),r.enabledByDefault({isReactNativeEntryPoint:i.isReactNativeEntryPoint})&&e.enableExperimentsByDefault([n]);for(const t of this.#t)e.enableExperimentsByDefault([t]);i.didInitializeExperiments=!0}};r.register({name:t.JS_HEAP_PROFILER_ENABLE,title:"Enable Heap Profiler (Memory Panel)",unstable:!1,enabledByDefault:({isReactNativeEntryPoint:e})=>!e}),r.register({name:t.REACT_NATIVE_SPECIFIC_UI,title:"Show React Native-specific UI",unstable:!1,enabledByDefault:({isReactNativeEntryPoint:e})=>e}),r.register({name:t.ENABLE_NETWORK_PANEL,title:"Enable Network panel",unstable:!0,enabledByDefault:()=>!1});var a=Object.freeze({__proto__:null,Instance:r,RNExperimentName:t,setIsReactNativeEntryPoint:function(e){if(i.didInitializeExperiments)throw new Error("setIsReactNativeEntryPoint must be called before constructing MainImpl");i.isReactNativeEntryPoint=e}});export{a as RNExperimentsImpl};
import*as e from"../root/root.js";const t=e.Runtime.RNExperimentName,n={didInitializeExperiments:!1,isReactNativeEntryPoint:!1};class i{name;title;unstable;docLink;feedbackLink;enabledByDefault;constructor(e){this.name=e.name,this.title=e.title,this.unstable=e.unstable,this.docLink=e.docLink,this.feedbackLink=e.feedbackLink,this.enabledByDefault=function(e,t){if(null==e)return()=>t;if("boolean"==typeof e)return()=>e;return e}(e.enabledByDefault,!1)}}const r=new class{#e=new Map;#t=new Set;register(e){if(n.didInitializeExperiments)throw new Error("Experiments must be registered before constructing MainImpl");const{name:t}=e;if(this.#e.has(t))throw new Error(`React Native Experiment ${t} is already registered`);this.#e.set(t,new i(e))}enableExperimentsByDefault(e){if(n.didInitializeExperiments)throw new Error("Experiments must be configured before constructing MainImpl");for(const n of e)if(Object.prototype.hasOwnProperty.call(t,n)){const e=this.#e.get(n);if(!e)throw new Error(`React Native Experiment ${n} is not registered`);e.enabledByDefault=()=>!0}else this.#t.add(n)}copyInto(e,t=""){for(const[i,r]of this.#e)e.register(i,t+r.title,r.unstable,r.docLink,r.feedbackLink),r.enabledByDefault({isReactNativeEntryPoint:n.isReactNativeEntryPoint})&&e.enableExperimentsByDefault([i]);for(const t of this.#t)e.enableExperimentsByDefault([t]);n.didInitializeExperiments=!0}};r.register({name:t.JS_HEAP_PROFILER_ENABLE,title:"Enable Heap Profiler (Memory Panel)",unstable:!1,enabledByDefault:({isReactNativeEntryPoint:e})=>!e}),r.register({name:t.REACT_NATIVE_SPECIFIC_UI,title:"Show React Native-specific UI",unstable:!1,enabledByDefault:({isReactNativeEntryPoint:e})=>e}),r.register({name:t.ENABLE_PERFORMANCE_PANEL,title:"Enable Performance panel",unstable:!0,enabledByDefault:({isReactNativeEntryPoint:e})=>!e}),r.register({name:t.ENABLE_NETWORK_PANEL,title:"Enable Network panel",unstable:!0,enabledByDefault:()=>!1});var a=Object.freeze({__proto__:null,Instance:r,RNExperimentName:t,setIsReactNativeEntryPoint:function(e){if(n.didInitializeExperiments)throw new Error("setIsReactNativeEntryPoint must be called before constructing MainImpl");n.isReactNativeEntryPoint=e}});export{a as RNExperimentsImpl};
@@ -1 +1 @@
import*as e from"../platform/platform.js";const t=new URLSearchParams(location.search);let n,r,s="";function a(){return window.location.pathname}function i(e){return["node_app","js_app"].some((t=>e.includes(t)))}class o{constructor(){}static instance(e={forceNew:null}){const{forceNew:t}=e;return n&&!t||(n=new o),n}static removeInstance(){n=void 0}static queryParam(e){return t.get(e)}static setQueryParamForTesting(e,n){t.set(e,n)}static isNode(){return void 0===r&&(r=i(a())),r}static setPlatform(e){s=e}static platform(){return s}static isDescriptorEnabled(e){const{experiment:t}=e;if("*"===t)return!0;if(t&&t.startsWith("!")&&h.isEnabled(t.substring(1)))return!1;if(t&&!t.startsWith("!")&&!h.isEnabled(t))return!1;const{condition:n}=e;return!n||n(_)}loadLegacyModule(e){console.log("Loading legacy module: "+e);return import(`../../${e}`).then((t=>(console.log("Loaded legacy module: "+e),t)))}}class l{#e=[];#t=new Set;#n=new Set;#r=new Set;#s=new Set;#a=new c;allConfigurableExperiments(){const e=[];for(const t of this.#e)this.#n.has(t.name)||e.push(t);return e}register(t,n,r,s,a){if(this.#t.has(t))throw new Error(`Duplicate registration of experiment '${t}'`);this.#t.add(t),this.#e.push(new m(this,t,n,Boolean(r),s??e.DevToolsPath.EmptyUrlString,a??e.DevToolsPath.EmptyUrlString))}isEnabled(e){return this.checkExperiment(e),!1!==this.#a.get(e)&&(!(!this.#n.has(e)&&!this.#r.has(e))||(!!this.#s.has(e)||Boolean(this.#a.get(e))))}setEnabled(e,t){this.checkExperiment(e),this.#a.set(e,t)}enableExperimentsTransiently(e){for(const t of e)this.checkExperiment(t),this.#n.add(t)}enableExperimentsByDefault(e){for(const t of e)this.checkExperiment(t),this.#r.add(t)}setServerEnabledExperiments(e){for(const t of e)this.checkExperiment(t),this.#s.add(t)}enableForTest(e){this.checkExperiment(e),this.#n.add(e)}disableForTest(e){this.checkExperiment(e),this.#n.delete(e)}clearForTest(){this.#e=[],this.#t.clear(),this.#n.clear(),this.#r.clear(),this.#s.clear()}cleanUpStaleExperiments(){this.#a.cleanUpStaleExperiments(this.#t)}checkExperiment(e){if(!this.#t.has(e))throw new Error(`Unknown experiment '${e}'`)}}class c{#e={};constructor(){try{const e=self.localStorage?.getItem("experiments");e&&(this.#e=JSON.parse(e))}catch{console.error("Failed to parse localStorage['experiments']")}}get(e){return this.#e[e]}set(e,t){this.#e[e]=t,this.#i()}cleanUpStaleExperiments(e){for(const[t]of Object.entries(this.#e))e.has(t)||delete this.#e[t];this.#i()}#i(){self.localStorage?.setItem("experiments",JSON.stringify(this.#e))}}class m{name;title;unstable;docLink;feedbackLink;#e;constructor(e,t,n,r,s,a){this.name=t,this.title=n,this.unstable=r,this.docLink=s,this.feedbackLink=a,this.#e=e}isEnabled(){return this.#e.isEnabled(this.name)}setEnabled(e){this.#e.setEnabled(this.name,e)}}const h=new l;var E,p,d,u;!function(e){e.REACT_NATIVE_SPECIFIC_UI="react-native-specific-ui",e.JS_HEAP_PROFILER_ENABLE="js-heap-profiler-enable",e.ENABLE_NETWORK_PANEL="enable-network-panel"}(E||(E={})),function(e){e.NOT_SOURCES_HIDE_ADD_FOLDER="!sources.hide_add_folder",e.REACT_NATIVE_UNSTABLE_NETWORK_PANEL="unstable_enableNetworkPanel"}(p||(p={})),function(e){e[e.ALLOW=0]="ALLOW",e[e.ALLOW_WITHOUT_LOGGING=1]="ALLOW_WITHOUT_LOGGING",e[e.DISABLE=2]="DISABLE"}(d||(d={})),function(e){e.ALL_SCRIPTS="ALL_SCRIPTS",e.SIDE_EFFECT_FREE_SCRIPTS_ONLY="SIDE_EFFECT_FREE_SCRIPTS_ONLY",e.NO_SCRIPTS="NO_SCRIPTS"}(u||(u={}));const _=Object.create(null),f={canDock:()=>Boolean(o.queryParam("can_dock")),notSourcesHideAddFolder:()=>Boolean(o.queryParam(p.NOT_SOURCES_HIDE_ADD_FOLDER)),reactNativeUnstableNetworkPanel:()=>Boolean(o.queryParam(p.REACT_NATIVE_UNSTABLE_NETWORK_PANEL))||h.isEnabled("enable-network-panel")};var x=Object.freeze({__proto__:null,get ConditionName(){return p},Experiment:m,ExperimentsSupport:l,get GenAiEnterprisePolicyValue(){return d},get HostConfigFreestylerExecutionMode(){return u},get RNExperimentName(){return E},Runtime:o,conditions:f,experiments:h,getChromeVersion:()=>{const e=navigator.userAgent.match(/(?:^|\W)(?:Chrome|HeadlessChrome)\/(\S+)/);return e&&e.length>1?e[1]:""},getPathName:a,getRemoteBase:function(e=self.location.toString()){const t=new URL(e).searchParams.get("remoteBase");if(!t)return null;const n=/\/serve_file\/(@[0-9a-zA-Z]+)\/?$/.exec(t);return n?{base:`devtools://devtools/remote/serve_file/${n[1]}/`,version:n[1]}:null},hostConfig:_,isNodeEntry:i});export{x as Runtime};
import*as e from"../platform/platform.js";const t=new URLSearchParams(location.search);let n,r,s="";function a(){return window.location.pathname}function i(e){return["node_app","js_app"].some((t=>e.includes(t)))}class o{constructor(){}static instance(e={forceNew:null}){const{forceNew:t}=e;return n&&!t||(n=new o),n}static removeInstance(){n=void 0}static queryParam(e){return t.get(e)}static setQueryParamForTesting(e,n){t.set(e,n)}static isNode(){return void 0===r&&(r=i(a())),r}static setPlatform(e){s=e}static platform(){return s}static isDescriptorEnabled(e){const{experiment:t}=e;if("*"===t)return!0;if(t&&t.startsWith("!")&&h.isEnabled(t.substring(1)))return!1;if(t&&!t.startsWith("!")&&!h.isEnabled(t))return!1;const{condition:n}=e;return!n||n(_)}loadLegacyModule(e){console.log("Loading legacy module: "+e);return import(`../../${e}`).then((t=>(console.log("Loaded legacy module: "+e),t)))}}class l{#e=[];#t=new Set;#n=new Set;#r=new Set;#s=new Set;#a=new c;allConfigurableExperiments(){const e=[];for(const t of this.#e)this.#n.has(t.name)||e.push(t);return e}register(t,n,r,s,a){if(this.#t.has(t))throw new Error(`Duplicate registration of experiment '${t}'`);this.#t.add(t),this.#e.push(new m(this,t,n,Boolean(r),s??e.DevToolsPath.EmptyUrlString,a??e.DevToolsPath.EmptyUrlString))}isEnabled(e){return this.checkExperiment(e),!1!==this.#a.get(e)&&(!(!this.#n.has(e)&&!this.#r.has(e))||(!!this.#s.has(e)||Boolean(this.#a.get(e))))}setEnabled(e,t){this.checkExperiment(e),this.#a.set(e,t)}enableExperimentsTransiently(e){for(const t of e)this.checkExperiment(t),this.#n.add(t)}enableExperimentsByDefault(e){for(const t of e)this.checkExperiment(t),this.#r.add(t)}setServerEnabledExperiments(e){for(const t of e)this.checkExperiment(t),this.#s.add(t)}enableForTest(e){this.checkExperiment(e),this.#n.add(e)}disableForTest(e){this.checkExperiment(e),this.#n.delete(e)}clearForTest(){this.#e=[],this.#t.clear(),this.#n.clear(),this.#r.clear(),this.#s.clear()}cleanUpStaleExperiments(){this.#a.cleanUpStaleExperiments(this.#t)}checkExperiment(e){if(!this.#t.has(e))throw new Error(`Unknown experiment '${e}'`)}}class c{#e={};constructor(){try{const e=self.localStorage?.getItem("experiments");e&&(this.#e=JSON.parse(e))}catch{console.error("Failed to parse localStorage['experiments']")}}get(e){return this.#e[e]}set(e,t){this.#e[e]=t,this.#i()}cleanUpStaleExperiments(e){for(const[t]of Object.entries(this.#e))e.has(t)||delete this.#e[t];this.#i()}#i(){self.localStorage?.setItem("experiments",JSON.stringify(this.#e))}}class m{name;title;unstable;docLink;feedbackLink;#e;constructor(e,t,n,r,s,a){this.name=t,this.title=n,this.unstable=r,this.docLink=s,this.feedbackLink=a,this.#e=e}isEnabled(){return this.#e.isEnabled(this.name)}setEnabled(e){this.#e.setEnabled(this.name,e)}}const h=new l;var E,p,d,u;!function(e){e.REACT_NATIVE_SPECIFIC_UI="react-native-specific-ui",e.JS_HEAP_PROFILER_ENABLE="js-heap-profiler-enable",e.ENABLE_PERFORMANCE_PANEL="enable-performance-panel",e.ENABLE_NETWORK_PANEL="enable-network-panel"}(E||(E={})),function(e){e.NOT_SOURCES_HIDE_ADD_FOLDER="!sources.hide_add_folder",e.REACT_NATIVE_UNSTABLE_NETWORK_PANEL="unstable_enableNetworkPanel"}(p||(p={})),function(e){e[e.ALLOW=0]="ALLOW",e[e.ALLOW_WITHOUT_LOGGING=1]="ALLOW_WITHOUT_LOGGING",e[e.DISABLE=2]="DISABLE"}(d||(d={})),function(e){e.ALL_SCRIPTS="ALL_SCRIPTS",e.SIDE_EFFECT_FREE_SCRIPTS_ONLY="SIDE_EFFECT_FREE_SCRIPTS_ONLY",e.NO_SCRIPTS="NO_SCRIPTS"}(u||(u={}));const _=Object.create(null),f={canDock:()=>Boolean(o.queryParam("can_dock")),notSourcesHideAddFolder:()=>Boolean(o.queryParam(p.NOT_SOURCES_HIDE_ADD_FOLDER)),reactNativeUnstableNetworkPanel:()=>Boolean(o.queryParam(p.REACT_NATIVE_UNSTABLE_NETWORK_PANEL))||h.isEnabled("enable-network-panel")};var x=Object.freeze({__proto__:null,get ConditionName(){return p},Experiment:m,ExperimentsSupport:l,get GenAiEnterprisePolicyValue(){return d},get HostConfigFreestylerExecutionMode(){return u},get RNExperimentName(){return E},Runtime:o,conditions:f,experiments:h,getChromeVersion:()=>{const e=navigator.userAgent.match(/(?:^|\W)(?:Chrome|HeadlessChrome)\/(\S+)/);return e&&e.length>1?e[1]:""},getPathName:a,getRemoteBase:function(e=self.location.toString()){const t=new URL(e).searchParams.get("remoteBase");if(!t)return null;const n=/\/serve_file\/(@[0-9a-zA-Z]+)\/?$/.exec(t);return n?{base:`devtools://devtools/remote/serve_file/${n[1]}/`,version:n[1]}:null},hostConfig:_,isNodeEntry:i});export{x as Runtime};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -30,7 +30,7 @@
"eslint-plugin-ft-flow": "^2.0.1",
"eslint-plugin-jest": "^29.0.1",
"eslint-plugin-react": "^7.30.1",
"eslint-plugin-react-hooks": "^7.0.1",
"eslint-plugin-react-hooks": "^5.2.0",
"eslint-plugin-react-native": "^4.0.0"
},
"peerDependencies": {
@@ -14,6 +14,7 @@ import com.facebook.react.utils.KotlinStdlibCompatUtils.capitalizeCompat
import com.facebook.react.utils.NdkConfiguratorUtils.configureJsEnginePackagingOptions
import com.facebook.react.utils.NdkConfiguratorUtils.configureNewArchPackagingOptions
import com.facebook.react.utils.ProjectUtils.isHermesEnabled
import com.facebook.react.utils.ProjectUtils.isHermesV1Enabled
import com.facebook.react.utils.ProjectUtils.useThirdPartyJSC
import com.facebook.react.utils.detectedCliFile
import com.facebook.react.utils.detectedEntryFile
@@ -48,6 +49,7 @@ internal fun Project.configureReactTasks(variant: Variant, config: ReactExtensio
} else {
isHermesEnabledInProject
}
val isHermesV1Enabled = project.isHermesV1Enabled || rootProject.isHermesV1Enabled
val isDebuggableVariant =
config.debuggableVariants.get().any { it.equals(variant.name, ignoreCase = true) }
val useThirdPartyJSC = project.useThirdPartyJSC
@@ -78,6 +80,7 @@ internal fun Project.configureReactTasks(variant: Variant, config: ReactExtensio
task.jsBundleDir.set(jsBundleDir)
task.resourcesDir.set(resourcesDir)
task.hermesEnabled.set(isHermesEnabledInThisVariant)
task.hermesV1Enabled.set(isHermesV1Enabled)
task.minifyEnabled.set(!isHermesEnabledInThisVariant)
task.devEnabled.set(false)
task.jsIntermediateSourceMapsDir.set(jsIntermediateSourceMapsDir)
@@ -63,6 +63,8 @@ abstract class BundleHermesCTask : DefaultTask() {
@get:Input abstract val hermesEnabled: Property<Boolean>
@get:Input abstract val hermesV1Enabled: Property<Boolean>
@get:Input abstract val devEnabled: Property<Boolean>
@get:Input abstract val extraPackagerArgs: ListProperty<String>
@@ -94,7 +96,8 @@ abstract class BundleHermesCTask : DefaultTask() {
runCommand(bundleCommand)
if (hermesEnabled.get()) {
val detectedHermesCommand = detectOSAwareHermesCommand(root.get().asFile, hermesCommand.get())
val detectedHermesCommand =
detectOSAwareHermesCommand(root.get().asFile, hermesCommand.get(), hermesV1Enabled.get())
val bytecodeFile = File("${bundleFile}.hbc")
val outputSourceMap = resolveOutputSourceMap(bundleAssetFilename)
val compilerSourceMap = resolveCompilerSourceMap(bundleAssetFilename)
@@ -44,8 +44,12 @@ internal object AgpConfiguratorUtils {
maybeCreate("debugOptimized").apply {
manifestPlaceholders["usesCleartextTraffic"] = "true"
initWith(debug)
matchingFallbacks += listOf("release")
externalNativeBuild { cmake { arguments("-DCMAKE_BUILD_TYPE=Release") } }
externalNativeBuild {
cmake {
arguments("-DCMAKE_BUILD_TYPE=Release")
matchingFallbacks += listOf("release")
}
}
}
}
}
@@ -96,7 +100,6 @@ internal object AgpConfiguratorUtils {
project.extensions
.getByType(ApplicationAndroidComponentsExtension::class.java)
.finalizeDsl { ext ->
ext.buildFeatures.resValues = true
ext.defaultConfig.resValue(
"string",
"react_native_dev_server_ip",
@@ -14,7 +14,6 @@ import com.facebook.react.utils.PropertyUtils.INCLUDE_JITPACK_REPOSITORY
import com.facebook.react.utils.PropertyUtils.INCLUDE_JITPACK_REPOSITORY_DEFAULT
import com.facebook.react.utils.PropertyUtils.INTERNAL_HERMES_PUBLISHING_GROUP
import com.facebook.react.utils.PropertyUtils.INTERNAL_HERMES_V1_VERSION_NAME
import com.facebook.react.utils.PropertyUtils.INTERNAL_HERMES_VERSION_NAME
import com.facebook.react.utils.PropertyUtils.INTERNAL_REACT_NATIVE_MAVEN_LOCAL_REPO
import com.facebook.react.utils.PropertyUtils.INTERNAL_REACT_PUBLISHING_GROUP
import com.facebook.react.utils.PropertyUtils.INTERNAL_USE_HERMES_NIGHTLY
@@ -140,7 +139,11 @@ internal object DependencyUtils {
// Contributors only: The hermes-engine version is forced only if the user has
// not opted into using nightlies for local development.
configuration.resolutionStrategy.force(
"${coordinates.hermesGroupString}:hermes-android:${if (hermesV1Enabled) coordinates.hermesV1VersionString else coordinates.hermesVersionString}"
// TODO: T237406039 update coordinates
if (hermesV1Enabled)
"${coordinates.hermesGroupString}:hermes-android:${coordinates.hermesV1VersionString}"
else
"${coordinates.reactGroupString}:hermes-android:${coordinates.hermesVersionString}"
)
}
}
@@ -151,10 +154,13 @@ internal object DependencyUtils {
coordinates: Coordinates,
hermesV1Enabled: Boolean = false,
): List<Triple<String, String, String>> {
// TODO: T231755027 update coordinates and versioning
val dependencySubstitution = mutableListOf<Triple<String, String, String>>()
val hermesVersion =
if (hermesV1Enabled) coordinates.hermesV1VersionString else coordinates.hermesVersionString
val hermesVersionString = "${coordinates.hermesGroupString}:hermes-android:${hermesVersion}"
// TODO: T237406039 update coordinates
val hermesVersionString =
if (hermesV1Enabled)
"${coordinates.hermesGroupString}:hermes-android:${coordinates.hermesV1VersionString}"
else "${coordinates.reactGroupString}:hermes-android:${coordinates.hermesVersionString}"
dependencySubstitution.add(
Triple(
"com.facebook.react:react-native",
@@ -169,13 +175,6 @@ internal object DependencyUtils {
"The hermes-engine artifact was deprecated in favor of hermes-android due to https://github.com/facebook/react-native/issues/35210.",
)
)
dependencySubstitution.add(
Triple(
"com.facebook.react:hermes-android",
hermesVersionString,
"The hermes-android artifact was moved to com.facebook.hermes publishing group.",
)
)
if (coordinates.reactGroupString != DEFAULT_INTERNAL_REACT_PUBLISHING_GROUP) {
dependencySubstitution.add(
Triple(
@@ -184,6 +183,7 @@ internal object DependencyUtils {
"The react-android dependency was modified to use the correct Maven group.",
)
)
// TODO: T237406039 update coordinates
dependencySubstitution.add(
Triple(
"com.facebook.react:hermes-android",
@@ -191,13 +191,12 @@ internal object DependencyUtils {
"The hermes-android dependency was modified to use the correct Maven group.",
)
)
}
if (coordinates.hermesGroupString != DEFAULT_INTERNAL_HERMES_PUBLISHING_GROUP) {
} else if (hermesV1Enabled) {
dependencySubstitution.add(
Triple(
"com.facebook.hermes:hermes-android",
"com.facebook.react:hermes-android",
hermesVersionString,
"The hermes-android dependency was modified to use the correct Maven group.",
"The hermes-android dependency was modified to use Hermes V1.",
)
)
}
@@ -222,19 +221,11 @@ internal object DependencyUtils {
val hermesGroupString =
reactAndroidProperties[INTERNAL_HERMES_PUBLISHING_GROUP] as? String
?: DEFAULT_INTERNAL_HERMES_PUBLISHING_GROUP
// TODO: T237406039 read both versions from the same file
val hermesVersionProperties = Properties()
hermesVersionFile.inputStream().use { hermesVersionProperties.load(it) }
val hermesVersionString =
(hermesVersionProperties[INTERNAL_HERMES_VERSION_NAME] as? String).orEmpty()
val hermesVersion =
if (hermesVersionString.startsWith("0.0.0") || "-commitly-" in hermesVersionString) {
"$hermesVersionString-SNAPSHOT"
} else {
hermesVersionString
}
val hermesVersion = versionString
val hermesV1Version =
(hermesVersionProperties[INTERNAL_HERMES_V1_VERSION_NAME] as? String).orEmpty()
@@ -130,6 +130,7 @@ private fun detectCliFile(reactNativeRoot: File, preconfiguredCliFile: File?): F
internal fun detectOSAwareHermesCommand(
projectRoot: File,
hermesCommand: String,
hermesV1Enabled: Boolean = false,
): String { // 1. If the project specifies a Hermes command, don't second guess it.
if (hermesCommand.isNotBlank()) {
val osSpecificHermesCommand =
@@ -150,9 +151,13 @@ internal fun detectOSAwareHermesCommand(
return builtHermesc.cliPath(projectRoot)
}
// 3. Use hermes-compiler from npm
// 3. If Hermes V1 is enabled, use hermes-compiler from npm, otherwise, if the
// react-native contains a pre-built hermesc, use it.
// TODO: T237406039 use hermes-compiler from npm for both
val hermesCPath = if (hermesV1Enabled) HERMES_COMPILER_NPM_DIR else HERMESC_IN_REACT_NATIVE_DIR
val prebuiltHermesPath =
HERMES_COMPILER_NPM_DIR.plus(getHermesCBin())
hermesCPath
.plus(getHermesCBin())
.replace("%OS-BIN%", getHermesOSBin())
// Execution on Windows fails with / as separator
.replace('/', File.separatorChar)
@@ -238,5 +243,6 @@ internal fun readPackageJsonFile(
}
private const val HERMES_COMPILER_NPM_DIR = "node_modules/hermes-compiler/hermesc/%OS-BIN%/"
private const val HERMESC_IN_REACT_NATIVE_DIR = "node_modules/react-native/sdks/hermesc/%OS-BIN%/"
private const val HERMESC_BUILT_FROM_SOURCE_DIR =
"node_modules/react-native/ReactAndroid/hermes-engine/build/hermes/bin/"
@@ -81,9 +81,8 @@ object PropertyUtils {
const val INTERNAL_VERSION_NAME = "VERSION_NAME"
/**
* Internal properties, shared with iOS, used to control the version name of Hermes Engine. They
* are stored in sdks/hermes-engine/version.properties
* Internal property, shared with iOS, used to control the version name of Hermes Engine. This is
* stored in sdks/hermes-engine/version.properties
*/
const val INTERNAL_HERMES_VERSION_NAME = "HERMES_VERSION_NAME"
const val INTERNAL_HERMES_V1_VERSION_NAME = "HERMES_V1_VERSION_NAME"
}
@@ -289,7 +289,7 @@ class DependencyUtilsTest {
val forcedModules = project.configurations.first().resolutionStrategy.forcedModules
assertThat(forcedModules.any { it.toString() == "com.facebook.react:react-android:1.2.3" })
.isTrue()
assertThat(forcedModules.any { it.toString() == "com.facebook.hermes:hermes-android:4.5.6" })
assertThat(forcedModules.any { it.toString() == "com.facebook.react:hermes-android:4.5.6" })
.isTrue()
}
@@ -324,11 +324,11 @@ class DependencyUtilsTest {
val libForcedModules = libProject.configurations.first().resolutionStrategy.forcedModules
assertThat(appForcedModules.any { it.toString() == "com.facebook.react:react-android:1.2.3" })
.isTrue()
assertThat(appForcedModules.any { it.toString() == "com.facebook.hermes:hermes-android:4.5.6" })
assertThat(appForcedModules.any { it.toString() == "com.facebook.react:hermes-android:4.5.6" })
.isTrue()
assertThat(libForcedModules.any { it.toString() == "com.facebook.react:react-android:1.2.3" })
.isTrue()
assertThat(libForcedModules.any { it.toString() == "com.facebook.hermes:hermes-android:4.5.6" })
assertThat(libForcedModules.any { it.toString() == "com.facebook.react:hermes-android:4.5.6" })
.isTrue()
}
@@ -381,15 +381,11 @@ class DependencyUtilsTest {
val libForcedModules = libProject.configurations.first().resolutionStrategy.forcedModules
assertThat(appForcedModules.any { it.toString() == "io.github.test:react-android:1.2.3" })
.isTrue()
assertThat(
appForcedModules.any { it.toString() == "io.github.test.hermes:hermes-android:4.5.6" }
)
assertThat(appForcedModules.any { it.toString() == "io.github.test:hermes-android:4.5.6" })
.isTrue()
assertThat(libForcedModules.any { it.toString() == "io.github.test:react-android:1.2.3" })
.isTrue()
assertThat(
libForcedModules.any { it.toString() == "io.github.test.hermes:hermes-android:4.5.6" }
)
assertThat(libForcedModules.any { it.toString() == "io.github.test:hermes-android:4.5.6" })
.isTrue()
}
@@ -442,7 +438,7 @@ class DependencyUtilsTest {
)
.isEqualTo(dependencySubstitutions[0].third)
assertThat("com.facebook.react:hermes-engine").isEqualTo(dependencySubstitutions[1].first)
assertThat("com.facebook.hermes:hermes-android:0.42.0")
assertThat("com.facebook.react:hermes-android:0.42.0")
.isEqualTo(dependencySubstitutions[1].second)
assertThat(
"The hermes-engine artifact was deprecated in favor of hermes-android due to https://github.com/facebook/react-native/issues/35210."
@@ -494,26 +490,19 @@ class DependencyUtilsTest {
)
.isEqualTo(dependencySubstitutions[0].third)
assertThat("com.facebook.react:hermes-engine").isEqualTo(dependencySubstitutions[1].first)
assertThat("io.github.test.hermes:hermes-android:0.42.0")
.isEqualTo(dependencySubstitutions[1].second)
assertThat("io.github.test:hermes-android:0.42.0").isEqualTo(dependencySubstitutions[1].second)
assertThat(
"The hermes-engine artifact was deprecated in favor of hermes-android due to https://github.com/facebook/react-native/issues/35210."
)
.isEqualTo(dependencySubstitutions[1].third)
assertThat("com.facebook.react:hermes-android").isEqualTo(dependencySubstitutions[2].first)
assertThat("io.github.test.hermes:hermes-android:0.42.0")
.isEqualTo(dependencySubstitutions[2].second)
assertThat("The hermes-android artifact was moved to com.facebook.hermes publishing group.")
.isEqualTo(dependencySubstitutions[2].third)
assertThat("com.facebook.react:react-android").isEqualTo(dependencySubstitutions[3].first)
assertThat("io.github.test:react-android:0.42.0").isEqualTo(dependencySubstitutions[3].second)
assertThat("com.facebook.react:react-android").isEqualTo(dependencySubstitutions[2].first)
assertThat("io.github.test:react-android:0.42.0").isEqualTo(dependencySubstitutions[2].second)
assertThat("The react-android dependency was modified to use the correct Maven group.")
.isEqualTo(dependencySubstitutions[3].third)
assertThat("com.facebook.react:hermes-android").isEqualTo(dependencySubstitutions[4].first)
assertThat("io.github.test.hermes:hermes-android:0.42.0")
.isEqualTo(dependencySubstitutions[4].second)
.isEqualTo(dependencySubstitutions[2].third)
assertThat("com.facebook.react:hermes-android").isEqualTo(dependencySubstitutions[3].first)
assertThat("io.github.test:hermes-android:0.42.0").isEqualTo(dependencySubstitutions[3].second)
assertThat("The hermes-android dependency was modified to use the correct Maven group.")
.isEqualTo(dependencySubstitutions[4].third)
.isEqualTo(dependencySubstitutions[3].third)
}
@Test
@@ -543,20 +532,15 @@ class DependencyUtilsTest {
"The hermes-engine artifact was deprecated in favor of hermes-android due to https://github.com/facebook/react-native/issues/35210."
)
.isEqualTo(dependencySubstitutions[1].third)
assertThat("com.facebook.react:hermes-android").isEqualTo(dependencySubstitutions[2].first)
assertThat("io.github.test.hermes:hermes-android:0.43.0")
.isEqualTo(dependencySubstitutions[2].second)
assertThat("The hermes-android artifact was moved to com.facebook.hermes publishing group.")
.isEqualTo(dependencySubstitutions[2].third)
assertThat("com.facebook.react:react-android").isEqualTo(dependencySubstitutions[3].first)
assertThat("io.github.test:react-android:0.42.0").isEqualTo(dependencySubstitutions[3].second)
assertThat("com.facebook.react:react-android").isEqualTo(dependencySubstitutions[2].first)
assertThat("io.github.test:react-android:0.42.0").isEqualTo(dependencySubstitutions[2].second)
assertThat("The react-android dependency was modified to use the correct Maven group.")
.isEqualTo(dependencySubstitutions[3].third)
assertThat("com.facebook.react:hermes-android").isEqualTo(dependencySubstitutions[4].first)
.isEqualTo(dependencySubstitutions[2].third)
assertThat("com.facebook.react:hermes-android").isEqualTo(dependencySubstitutions[3].first)
assertThat("io.github.test.hermes:hermes-android:0.43.0")
.isEqualTo(dependencySubstitutions[4].second)
.isEqualTo(dependencySubstitutions[3].second)
assertThat("The hermes-android dependency was modified to use the correct Maven group.")
.isEqualTo(dependencySubstitutions[4].third)
.isEqualTo(dependencySubstitutions[3].third)
}
@Test
@@ -576,7 +560,6 @@ class DependencyUtilsTest {
tempFolder.newFile("version.properties").apply {
writeText(
"""
HERMES_VERSION_NAME=1000.0.0
HERMES_V1_VERSION_NAME=1000.0.0
ANOTHER_PROPERTY=true
"""
@@ -613,7 +596,6 @@ class DependencyUtilsTest {
tempFolder.newFile("version.properties").apply {
writeText(
"""
HERMES_VERSION_NAME=0.14.0
HERMES_V1_VERSION_NAME=250829098.0.0-stable
ANOTHER_PROPERTY=true
"""
@@ -627,7 +609,7 @@ class DependencyUtilsTest {
val hermesV1VersionString = strings.hermesV1VersionString
assertThat(versionString).isEqualTo("0.0.0-20221101-2019-cfe811ab1-SNAPSHOT")
assertThat(hermesVersionString).isEqualTo("0.14.0")
assertThat(hermesVersionString).isEqualTo("0.0.0-20221101-2019-cfe811ab1-SNAPSHOT")
assertThat(hermesV1VersionString).isEqualTo("250829098.0.0-stable")
}
@@ -679,7 +661,6 @@ class DependencyUtilsTest {
tempFolder.newFile("version.properties").apply {
writeText(
"""
HERMES_VERSION_NAME=
HERMES_V1_VERSION_NAME=
ANOTHER_PROPERTY=true
"""
@@ -714,7 +695,6 @@ class DependencyUtilsTest {
tempFolder.newFile("version.properties").apply {
writeText(
"""
HERMES_VERSION_NAME=
HERMES_V1_VERSION_NAME=
ANOTHER_PROPERTY=true
"""
@@ -746,7 +726,6 @@ class DependencyUtilsTest {
tempFolder.newFile("version.properties").apply {
writeText(
"""
HERMES_VERSION_NAME=
HERMES_V1_VERSION_NAME=
ANOTHER_PROPERTY=true
"""
@@ -155,11 +155,21 @@ class PathUtilsTest {
@Test
@WithOs(OS.MAC)
fun detectOSAwareHermesCommand_withHermescFromNPM() {
fun detectOSAwareHermesCommand_withBundledHermescInsideRN() {
tempFolder.newFolder("node_modules/react-native/sdks/hermesc/osx-bin/")
val expected = tempFolder.newFile("node_modules/react-native/sdks/hermesc/osx-bin/hermesc")
assertThat(detectOSAwareHermesCommand(tempFolder.root, "")).isEqualTo(expected.toString())
}
@Test
@WithOs(OS.MAC)
fun detectOSAwareHermesCommand_withHermesV1Enabled() {
tempFolder.newFolder("node_modules/hermes-compiler/hermesc/osx-bin/")
val expected = tempFolder.newFile("node_modules/hermes-compiler/hermesc/osx-bin/hermesc")
assertThat(detectOSAwareHermesCommand(tempFolder.root, "")).isEqualTo(expected.toString())
assertThat(detectOSAwareHermesCommand(tempFolder.root, "", hermesV1Enabled = true))
.isEqualTo(expected.toString())
}
@Test(expected = IllegalStateException::class)
+1 -2
View File
@@ -123,8 +123,7 @@ function getHermesLabel(): React.Node {
return (
<ThemedText color="secondary" style={styles.label}>
JS Engine: Hermes (
{global.HermesInternal.getRuntimeProperties?.()['OSS Release Version']})
JS Engine: Hermes
</ThemedText>
);
}
@@ -26,9 +26,7 @@ describe('console.timeStamp()', () => {
it("doesn't throw when additional arguments are specified", () => {
expect(() =>
console.timeStamp('label', 100, 500, 'Track', 'Group', 'error', {
tooltipText: 'Image processing failed',
}),
console.timeStamp('label', 100, 500, 'Track', 'Group', 'error'),
).not.toThrow();
});
+2 -11
View File
@@ -20,10 +20,6 @@ const EXCLUDED_FIRST_PARTY_PATHS = [
/[/\\]private[/\\]react-native-fantom[/\\]/,
];
// customTransformOptions may be strings from URL params, or booleans passed
// programatically. For strings, handle them as Metro does when parsing URLs.
const TRUE_VALS = new Set([true, 'true', '1']);
function isTypeScriptSource(fileName) {
return !!fileName && fileName.endsWith('.ts');
}
@@ -59,9 +55,6 @@ const getPreset = (src, options) => {
const isNull = src == null;
const hasClass = isNull || src.indexOf('class') !== -1;
const preserveClasses = TRUE_VALS.has(
options?.customTransformOptions?.unstable_preserveClasses,
);
const extraPlugins = [];
const firstPartyPlugins = [];
@@ -98,7 +91,7 @@ const getPreset = (src, options) => {
);
}
if (hasClass && !preserveClasses) {
if (hasClass) {
extraPlugins.push([require('@babel/plugin-transform-classes')]);
}
@@ -242,9 +235,7 @@ const getPreset = (src, options) => {
],
[require('babel-plugin-transform-flow-enums')],
[require('@babel/plugin-transform-block-scoping')],
...(preserveClasses
? []
: [[require('@babel/plugin-transform-class-properties'), {loose}]]),
[require('@babel/plugin-transform-class-properties'), {loose}],
[require('@babel/plugin-transform-private-methods'), {loose}],
[
require('@babel/plugin-transform-private-property-in-object'),
@@ -0,0 +1,51 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
'use strict';
import type {SchemaType} from '../../../../src/CodegenSchema';
const generator = require('../../../../src/generators/modules/GenerateModuleCpp');
const {FlowParser} = require('../../../../src/parsers/flow/parser');
const fs = require('fs');
const FIXTURE_DIR = `${__dirname}/../../__test_fixtures__/modules`;
const parser = new FlowParser();
function getModules(): SchemaType {
const filenames: Array<string> = fs.readdirSync(FIXTURE_DIR);
return filenames.reduce<SchemaType>(
(accumulator, file) => {
const schema = parser.parseFile(`${FIXTURE_DIR}/${file}`);
return {
modules: {
...accumulator.modules,
...schema.modules,
},
};
},
{modules: {}},
);
}
describe('GenerateModuleCpp', () => {
it('can generate an implementation file NativeModule specs', () => {
const libName = 'RNCodegenModuleFixtures';
const output = generator.generate(libName, getModules(), undefined, false);
expect(output.get(libName + 'JSI-generated.cpp')).toMatchSnapshot();
});
it('can generate a header file NativeModule specs with assume nonnull enabled', () => {
const libName = 'RNCodegenModuleFixtures';
const output = generator.generate(libName, getModules(), undefined, true);
expect(output.get(libName + 'JSI-generated.cpp')).toMatchSnapshot();
});
});
+3 -1
View File
@@ -36,6 +36,7 @@ const generateTests = require('./components/GenerateTests.js');
const generateThirdPartyFabricComponentsProviderH = require('./components/GenerateThirdPartyFabricComponentsProviderH.js');
const generateThirdPartyFabricComponentsProviderObjCpp = require('./components/GenerateThirdPartyFabricComponentsProviderObjCpp.js');
const generateViewConfigJs = require('./components/GenerateViewConfigJs.js');
const generateModuleCpp = require('./modules/GenerateModuleCpp.js');
const generateModuleH = require('./modules/GenerateModuleH.js');
const generateModuleJavaSpec = require('./modules/GenerateModuleJavaSpec.js');
const generateModuleJniCpp = require('./modules/GenerateModuleJniCpp.js');
@@ -55,6 +56,7 @@ const ALL_GENERATORS = {
generateStateCpp: generateStateCpp.generate,
generateStateH: generateStateH.generate,
generateModuleH: generateModuleH.generate,
generateModuleCpp: generateModuleCpp.generate,
generateModuleObjCpp: generateModuleObjCpp.generate,
generateModuleJavaSpec: generateModuleJavaSpec.generate,
generateModuleJniCpp: generateModuleJniCpp.generate,
@@ -177,7 +179,7 @@ const LIBRARY_GENERATORS: LibraryGeneratorsFunctions = {
generateModuleJniH.generate,
generateModuleJavaSpec.generate,
],
modulesCxx: [generateModuleH.generate],
modulesCxx: [generateModuleCpp.generate, generateModuleH.generate],
modulesIOS: [generateModuleObjCpp.generate],
tests: [generateTests.generate],
'shadow-nodes': [
@@ -0,0 +1,296 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/
'use strict';
import type {
NamedShape,
NativeModuleEnumMap,
NativeModuleFunctionTypeAnnotation,
NativeModuleParamTypeAnnotation,
NativeModulePropertyShape,
NativeModuleTypeAnnotation,
Nullable,
SchemaType,
} from '../../CodegenSchema';
import type {AliasResolver} from './Utils';
const {unwrapNullable} = require('../../parsers/parsers-commons');
const {createAliasResolver, getModules} = require('./Utils');
type FilesOutput = Map<string, string>;
const HostFunctionTemplate = ({
hasteModuleName,
methodName,
returnTypeAnnotation,
args,
}: $ReadOnly<{
hasteModuleName: string,
methodName: string,
returnTypeAnnotation: Nullable<NativeModuleTypeAnnotation>,
args: Array<string>,
}>) => {
const isNullable = returnTypeAnnotation.type === 'NullableTypeAnnotation';
const isVoid = returnTypeAnnotation.type === 'VoidTypeAnnotation';
const methodCallArgs = [' rt', ...args].join(',\n ');
const methodCall = `static_cast<${hasteModuleName}CxxSpecJSI *>(&turboModule)->${methodName}(\n${methodCallArgs}\n )`;
return `static jsi::Value __hostFunction_${hasteModuleName}CxxSpecJSI_${methodName}(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {${
isVoid
? `\n ${methodCall};`
: isNullable
? `\n auto result = ${methodCall};`
: ''
}
return ${
isVoid
? 'jsi::Value::undefined()'
: isNullable
? 'result ? jsi::Value(std::move(*result)) : jsi::Value::null()'
: methodCall
};
}`;
};
const ModuleTemplate = ({
hasteModuleName,
hostFunctions,
moduleName,
methods,
}: $ReadOnly<{
hasteModuleName: string,
hostFunctions: $ReadOnlyArray<string>,
moduleName: string,
methods: $ReadOnlyArray<$ReadOnly<{methodName: string, paramCount: number}>>,
}>) => {
return `${hostFunctions.join('\n')}
${hasteModuleName}CxxSpecJSI::${hasteModuleName}CxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker)
: TurboModule("${moduleName}", jsInvoker) {
${methods
.map(({methodName, paramCount}) => {
return ` methodMap_["${methodName}"] = MethodMetadata {${paramCount}, __hostFunction_${hasteModuleName}CxxSpecJSI_${methodName}};`;
})
.join('\n')}
}`;
};
const FileTemplate = ({
libraryName,
modules,
}: $ReadOnly<{
libraryName: string,
modules: string,
}>) => {
return `/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*
* ${'@'}generated by codegen project: GenerateModuleCpp.js
*/
#include "${libraryName}JSI.h"
namespace facebook::react {
${modules}
} // namespace facebook::react
`;
};
type Param = NamedShape<Nullable<NativeModuleParamTypeAnnotation>>;
function serializeArg(
moduleName: string,
arg: Param,
index: number,
resolveAlias: AliasResolver,
enumMap: NativeModuleEnumMap,
): string {
const {typeAnnotation: nullableTypeAnnotation, optional} = arg;
const [typeAnnotation, nullable] =
unwrapNullable<NativeModuleParamTypeAnnotation>(nullableTypeAnnotation);
let realTypeAnnotation = typeAnnotation;
if (realTypeAnnotation.type === 'TypeAliasTypeAnnotation') {
realTypeAnnotation = resolveAlias(realTypeAnnotation.name);
}
function wrap(callback: (val: string) => string) {
const val = `args[${index}]`;
const expression = callback(val);
// param?: T
if (optional && !nullable) {
// throw new Error('are we hitting this case? ' + moduleName);
return `count <= ${index} || ${val}.isUndefined() ? std::nullopt : std::make_optional(${expression})`;
}
// param: ?T
// param?: ?T
if (nullable || optional) {
return `count <= ${index} || ${val}.isNull() || ${val}.isUndefined() ? std::nullopt : std::make_optional(${expression})`;
}
// param: T
return `count <= ${index} ? throw jsi::JSError(rt, "Expected argument in position ${index} to be passed") : ${expression}`;
}
switch (realTypeAnnotation.type) {
case 'ReservedTypeAnnotation':
switch (realTypeAnnotation.name) {
case 'RootTag':
return wrap(val => `${val}.asNumber()`);
default:
(realTypeAnnotation.name: empty);
throw new Error(
`Unknown prop type for "${arg.name}, found: ${realTypeAnnotation.name}"`,
);
}
case 'StringTypeAnnotation':
return wrap(val => `${val}.asString(rt)`);
case 'StringLiteralTypeAnnotation':
return wrap(val => `${val}.asString(rt)`);
case 'StringLiteralUnionTypeAnnotation':
return wrap(val => `${val}.asString(rt)`);
case 'BooleanTypeAnnotation':
return wrap(val => `${val}.asBool()`);
case 'EnumDeclaration':
switch (realTypeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return wrap(val => `${val}.asNumber()`);
case 'StringTypeAnnotation':
return wrap(val => `${val}.asString(rt)`);
default:
throw new Error(
`Unknown enum type for "${arg.name}, found: ${realTypeAnnotation.type}"`,
);
}
case 'NumberTypeAnnotation':
return wrap(val => `${val}.asNumber()`);
case 'FloatTypeAnnotation':
return wrap(val => `${val}.asNumber()`);
case 'DoubleTypeAnnotation':
return wrap(val => `${val}.asNumber()`);
case 'Int32TypeAnnotation':
return wrap(val => `${val}.asNumber()`);
case 'NumberLiteralTypeAnnotation':
return wrap(val => `${val}.asNumber()`);
case 'ArrayTypeAnnotation':
return wrap(val => `${val}.asObject(rt).asArray(rt)`);
case 'FunctionTypeAnnotation':
return wrap(val => `${val}.asObject(rt).asFunction(rt)`);
case 'GenericObjectTypeAnnotation':
return wrap(val => `${val}.asObject(rt)`);
case 'UnionTypeAnnotation':
switch (typeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return wrap(val => `${val}.asNumber()`);
case 'ObjectTypeAnnotation':
return wrap(val => `${val}.asObject(rt)`);
case 'StringTypeAnnotation':
return wrap(val => `${val}.asString(rt)`);
default:
throw new Error(
`Unsupported union member type for param "${arg.name}, found: ${realTypeAnnotation.memberType}"`,
);
}
case 'ObjectTypeAnnotation':
return wrap(val => `${val}.asObject(rt)`);
case 'MixedTypeAnnotation':
return wrap(val => `jsi::Value(rt, ${val})`);
default:
(realTypeAnnotation.type: empty);
throw new Error(
`Unknown prop type for "${arg.name}, found: ${realTypeAnnotation.type}"`,
);
}
}
function serializePropertyIntoHostFunction(
moduleName: string,
hasteModuleName: string,
property: NativeModulePropertyShape,
resolveAlias: AliasResolver,
enumMap: NativeModuleEnumMap,
): string {
const [propertyTypeAnnotation] =
unwrapNullable<NativeModuleFunctionTypeAnnotation>(property.typeAnnotation);
return HostFunctionTemplate({
hasteModuleName,
methodName: property.name,
returnTypeAnnotation: propertyTypeAnnotation.returnTypeAnnotation,
args: propertyTypeAnnotation.params.map((p, i) =>
serializeArg(moduleName, p, i, resolveAlias, enumMap),
),
});
}
module.exports = {
generate(
libraryName: string,
schema: SchemaType,
packageName?: string,
assumeNonnull: boolean = false,
headerPrefix?: string,
): FilesOutput {
const nativeModules = getModules(schema);
const modules = Object.keys(nativeModules)
.map((hasteModuleName: string) => {
const nativeModule = nativeModules[hasteModuleName];
const {
aliasMap,
enumMap,
spec: {methods},
moduleName,
} = nativeModule;
const resolveAlias = createAliasResolver(aliasMap);
const hostFunctions = methods.map(property =>
serializePropertyIntoHostFunction(
moduleName,
hasteModuleName,
property,
resolveAlias,
enumMap,
),
);
return ModuleTemplate({
hasteModuleName,
hostFunctions,
moduleName,
methods: methods.map(
({name: propertyName, typeAnnotation: nullableTypeAnnotation}) => {
const [{params}] = unwrapNullable(nullableTypeAnnotation);
return {
methodName: propertyName,
paramCount: params.length,
};
},
),
});
})
.join('\n');
const fileName = `${libraryName}JSI-generated.cpp`;
const replacedTemplate = FileTemplate({
modules,
libraryName,
});
return new Map([[fileName, replacedTemplate]]);
},
};
@@ -9,17 +9,17 @@
*/
'use strict';
import type {
NamedShape,
NativeModuleAliasMap,
NativeModuleBaseTypeAnnotation,
} from '../../CodegenSchema';
import type {
NativeModuleAliasMap,
NativeModuleEnumMap,
NativeModuleEnumMember,
NativeModuleEnumMemberType,
NativeModuleEventEmitterShape,
NativeModuleFunctionTypeAnnotation,
NativeModuleParamTypeAnnotation,
NativeModulePropertyShape,
NativeModuleTypeAnnotation,
Nullable,
@@ -30,6 +30,7 @@ import type {AliasResolver} from './Utils';
const {unwrapNullable} = require('../../parsers/parsers-commons');
const {wrapOptional} = require('../TypeUtils/Cxx');
const {getEnumName, toPascalCase, toSafeCppString} = require('../Utils');
const {indent} = require('../Utils');
const {
createAliasResolver,
getModules,
@@ -39,151 +40,74 @@ const {
type FilesOutput = Map<string, string>;
type Param = NamedShape<Nullable<NativeModuleParamTypeAnnotation>>;
const ModuleClassDeclarationTemplate = ({
hasteModuleName,
moduleProperties,
structs,
enums,
}: $ReadOnly<{
hasteModuleName: string,
moduleProperties: string[],
structs: string,
enums: string,
}>) => {
return `${enums}
${structs}class JSI_EXPORT ${hasteModuleName}CxxSpecJSI : public TurboModule {
protected:
${hasteModuleName}CxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker);
function serializeArg(
moduleName: string,
arg: Param,
index: number,
resolveAlias: AliasResolver,
enumMap: NativeModuleEnumMap,
): string {
const {typeAnnotation: nullableTypeAnnotation, optional} = arg;
const [typeAnnotation, nullable] =
unwrapNullable<NativeModuleParamTypeAnnotation>(nullableTypeAnnotation);
public:
${indent(moduleProperties.join('\n'), 2)}
let realTypeAnnotation = typeAnnotation;
if (realTypeAnnotation.type === 'TypeAliasTypeAnnotation') {
realTypeAnnotation = resolveAlias(realTypeAnnotation.name);
}
function wrap(callback: (val: string) => string) {
const val = `args[${index}]`;
const expression = callback(val);
// param?: T
if (optional && !nullable) {
// throw new Error('are we hitting this case? ' + moduleName);
return `count <= ${index} || ${val}.isUndefined() ? std::nullopt : std::make_optional(${expression})`;
}
// param: ?T
// param?: ?T
if (nullable || optional) {
return `count <= ${index} || ${val}.isNull() || ${val}.isUndefined() ? std::nullopt : std::make_optional(${expression})`;
}
// param: T
return `count <= ${index} ? throw jsi::JSError(rt, "Expected argument in position ${index} to be passed") : ${expression}`;
}
switch (realTypeAnnotation.type) {
case 'ReservedTypeAnnotation':
switch (realTypeAnnotation.name) {
case 'RootTag':
return wrap(val => `${val}.asNumber()`);
default:
(realTypeAnnotation.name: empty);
throw new Error(
`Unknown prop type for "${arg.name}, found: ${realTypeAnnotation.name}"`,
);
}
case 'StringTypeAnnotation':
return wrap(val => `${val}.asString(rt)`);
case 'StringLiteralTypeAnnotation':
return wrap(val => `${val}.asString(rt)`);
case 'StringLiteralUnionTypeAnnotation':
return wrap(val => `${val}.asString(rt)`);
case 'BooleanTypeAnnotation':
return wrap(val => `${val}.asBool()`);
case 'EnumDeclaration':
switch (realTypeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return wrap(val => `${val}.asNumber()`);
case 'StringTypeAnnotation':
return wrap(val => `${val}.asString(rt)`);
default:
throw new Error(
`Unknown enum type for "${arg.name}, found: ${realTypeAnnotation.type}"`,
);
}
case 'NumberTypeAnnotation':
return wrap(val => `${val}.asNumber()`);
case 'FloatTypeAnnotation':
return wrap(val => `${val}.asNumber()`);
case 'DoubleTypeAnnotation':
return wrap(val => `${val}.asNumber()`);
case 'Int32TypeAnnotation':
return wrap(val => `${val}.asNumber()`);
case 'NumberLiteralTypeAnnotation':
return wrap(val => `${val}.asNumber()`);
case 'ArrayTypeAnnotation':
return wrap(val => `${val}.asObject(rt).asArray(rt)`);
case 'FunctionTypeAnnotation':
return wrap(val => `${val}.asObject(rt).asFunction(rt)`);
case 'GenericObjectTypeAnnotation':
return wrap(val => `${val}.asObject(rt)`);
case 'UnionTypeAnnotation':
switch (typeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return wrap(val => `${val}.asNumber()`);
case 'ObjectTypeAnnotation':
return wrap(val => `${val}.asObject(rt)`);
case 'StringTypeAnnotation':
return wrap(val => `${val}.asString(rt)`);
default:
throw new Error(
`Unsupported union member type for param "${arg.name}, found: ${realTypeAnnotation.memberType}"`,
);
}
case 'ObjectTypeAnnotation':
return wrap(val => `${val}.asObject(rt)`);
case 'MixedTypeAnnotation':
return wrap(val => `jsi::Value(rt, ${val})`);
default:
(realTypeAnnotation.type: empty);
throw new Error(
`Unknown prop type for "${arg.name}, found: ${realTypeAnnotation.type}"`,
);
}
}
};`;
};
const ModuleSpecClassDeclarationTemplate = ({
hasteModuleName,
moduleName,
structs,
enums,
moduleEventEmitters,
moduleFunctions,
methods,
moduleProperties,
}: $ReadOnly<{
hasteModuleName: string,
moduleName: string,
structs: string,
enums: string,
moduleEventEmitters: EventEmitterCpp[],
moduleFunctions: string[],
methods: $ReadOnlyArray<$ReadOnly<{methodName: string, paramCount: number}>>,
moduleProperties: string[],
}>) => {
return `${enums}${structs}
template <typename T>
return `template <typename T>
class JSI_EXPORT ${hasteModuleName}CxxSpec : public TurboModule {
public:
jsi::Value create(jsi::Runtime &rt, const jsi::PropNameID &propName) override {
return delegate_.create(rt, propName);
}
std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime& runtime) override {
return delegate_.getPropertyNames(runtime);
}
static constexpr std::string_view kModuleName = "${moduleName}";
protected:
${hasteModuleName}CxxSpec(std::shared_ptr<CallInvoker> jsInvoker) : TurboModule(std::string{${hasteModuleName}CxxSpec::kModuleName}, jsInvoker) {
${methods
.map(({methodName, paramCount}) => {
return ` methodMap_["${methodName}"] = MethodMetadata {.argCount = ${paramCount}, .invoker = __${methodName}};`;
})
.join(
'\n',
)}${moduleEventEmitters.length > 0 ? '\n' : ''}${moduleEventEmitters.map(e => e.registerEventEmitter).join('\n')}
}
${moduleEventEmitters.map(e => e.emitFunction).join('\n')}
${hasteModuleName}CxxSpec(std::shared_ptr<CallInvoker> jsInvoker)
: TurboModule(std::string{${hasteModuleName}CxxSpec::kModuleName}, jsInvoker),
delegate_(reinterpret_cast<T*>(this), jsInvoker) {}
${moduleEventEmitters.map(e => e.emitFunction).join('\n')}
private:
${moduleFunctions.join('\n\n')}
class Delegate : public ${hasteModuleName}CxxSpecJSI {
public:
Delegate(T *instance, std::shared_ptr<CallInvoker> jsInvoker) :
${hasteModuleName}CxxSpecJSI(std::move(jsInvoker)), instance_(instance) {
${moduleEventEmitters.map(e => e.registerEventEmitter).join('\n')}
}
${indent(moduleProperties.join('\n'), 4)}
private:
friend class ${hasteModuleName}CxxSpec;
T *instance_;
};
Delegate delegate_;
};`;
};
@@ -368,7 +292,7 @@ function createStructsString(
return bridging::toJs(rt, value);
}`,
)
.join('\n');
.join('\n\n');
return `
#pragma mark - ${structName}
@@ -552,19 +476,19 @@ function createEnums(
.join('\n');
}
function translateFunctionToCpp(
function translatePropertyToCpp(
hasteModuleName: string,
prop: NativeModulePropertyShape,
resolveAlias: AliasResolver,
enumMap: NativeModuleEnumMap,
args: Array<string>,
returnTypeAnnotation: Nullable<NativeModuleTypeAnnotation>,
abstract: boolean = false,
): string {
const [propTypeAnnotation] =
unwrapNullable<NativeModuleFunctionTypeAnnotation>(prop.typeAnnotation);
const isNullable = returnTypeAnnotation.type === 'NullableTypeAnnotation';
const isVoid = returnTypeAnnotation.type === 'VoidTypeAnnotation';
const params = propTypeAnnotation.params.map(
param => `std::move(${param.name})`,
);
const paramTypes = propTypeAnnotation.params.map(param => {
const translatedParam = translatePrimitiveJSTypeToCpp(
@@ -579,7 +503,6 @@ function translateFunctionToCpp(
);
return `${translatedParam} ${param.name}`;
});
paramTypes.unshift('jsi::Runtime &rt');
const returnType = translatePrimitiveJSTypeToCpp(
hasteModuleName,
@@ -591,16 +514,23 @@ function translateFunctionToCpp(
enumMap,
);
let methodCallArgs = [...args].join(',\n ');
if (methodCallArgs.length > 0) {
methodCallArgs = `,\n ${methodCallArgs}`;
// The first param will always be the runtime reference.
paramTypes.unshift('jsi::Runtime &rt');
const method = `${returnType} ${prop.name}(${paramTypes.join(', ')})`;
if (abstract) {
return `virtual ${method} = 0;`;
}
return ` static jsi::Value __${prop.name}(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* ${args.length > 0 ? 'args' : '/*args*/'}, size_t ${args.length > 0 ? 'count' : '/*count*/'}) {
static_assert(
return `${method} override {
static_assert(
bridging::getParameterCount(&T::${prop.name}) == ${paramTypes.length},
"Expected ${prop.name}(...) to have ${paramTypes.length} parameters");
${!isVoid ? (!isNullable ? 'return ' : 'auto result = ') : ''}bridging::callFromJs<${returnType}>(rt, &T::${prop.name}, static_cast<${hasteModuleName}CxxSpec*>(&turboModule)->jsInvoker_, static_cast<T*>(&turboModule)${methodCallArgs});${!isVoid ? (!isNullable ? '' : 'return result ? jsi::Value(std::move(*result)) : jsi::Value::null();') : 'return jsi::Value::undefined();'}\n }`;
return bridging::callFromJs<${returnType}>(
rt, &T::${prop.name}, jsInvoker_, ${['instance_', ...params].join(', ')});
}`;
}
type EventEmitterCpp = {
@@ -633,7 +563,7 @@ function translateEventEmitterToCpp(
return {
isVoidTypeAnnotation: isVoidTypeAnnotation,
templateName: isVoidTypeAnnotation ? `/*${templateName}*/` : templateName,
registerEventEmitter: ` eventEmitterMap_["${
registerEventEmitter: ` eventEmitterMap_["${
eventEmitter.name
}"] = std::make_shared<AsyncEventEmitter<${
isVoidTypeAnnotation ? '' : 'jsi::Value'
@@ -655,7 +585,7 @@ function translateEventEmitterToCpp(
}
static_cast<AsyncEventEmitter<${
isVoidTypeAnnotation ? '' : 'jsi::Value'
}>&>(*eventEmitterMap_["${eventEmitter.name}"]).emit(${
}>&>(*delegate_.eventEmitterMap_["${eventEmitter.name}"]).emit(${
isVoidTypeAnnotation
? ''
: `[jsInvoker = jsInvoker_, eventValue = value](jsi::Runtime& rt) -> jsi::Value {
@@ -677,14 +607,8 @@ module.exports = {
const nativeModules = getModules(schema);
const modules = Object.keys(nativeModules).flatMap(hasteModuleName => {
const nativeModule = nativeModules[hasteModuleName];
const {
aliasMap,
enumMap,
spec: {methods},
spec,
moduleName,
} = nativeModule;
const {aliasMap, enumMap, spec, moduleName} =
nativeModules[hasteModuleName];
const resolveAlias = createAliasResolver(aliasMap);
const structs = createStructsString(
hasteModuleName,
@@ -693,12 +617,25 @@ module.exports = {
enumMap,
);
const enums = createEnums(hasteModuleName, enumMap, resolveAlias);
return [
ModuleClassDeclarationTemplate({
hasteModuleName,
moduleProperties: spec.methods.map(prop =>
translatePropertyToCpp(
hasteModuleName,
prop,
resolveAlias,
enumMap,
true,
),
),
structs,
enums,
}),
ModuleSpecClassDeclarationTemplate({
hasteModuleName,
moduleName,
structs,
enums,
moduleEventEmitters: spec.eventEmitters.map(eventEmitter =>
translateEventEmitterToCpp(
moduleName,
@@ -707,30 +644,13 @@ module.exports = {
enumMap,
),
),
moduleFunctions: spec.methods.map(property => {
const [propertyTypeAnnotation] =
unwrapNullable<NativeModuleFunctionTypeAnnotation>(
property.typeAnnotation,
);
return translateFunctionToCpp(
moduleProperties: spec.methods.map(prop =>
translatePropertyToCpp(
hasteModuleName,
property,
prop,
resolveAlias,
enumMap,
propertyTypeAnnotation.params.map((p, i) =>
serializeArg(moduleName, p, i, resolveAlias, enumMap),
),
propertyTypeAnnotation.returnTypeAnnotation,
);
}),
methods: methods.map(
({name: propertyName, typeAnnotation: nullableTypeAnnotation}) => {
const [{params}] = unwrapNullable(nullableTypeAnnotation);
return {
methodName: propertyName,
paramCount: params.length,
};
},
),
),
}),
];
@@ -0,0 +1,32 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
'use strict';
const fixtures = require('../__test_fixtures__/fixtures.js');
const generator = require('../GenerateModuleCpp.js');
describe('GenerateModuleCpp', () => {
Object.keys(fixtures)
.sort()
.forEach(fixtureName => {
const fixture = fixtures[fixtureName];
it(`can generate fixture ${fixtureName}`, () => {
expect(
generator.generate(
fixtureName,
fixture,
'com.facebook.fbreact.specs',
),
).toMatchSnapshot();
});
});
});
@@ -0,0 +1,782 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`GenerateModuleCpp can generate fixture SampleWithUppercaseName 1`] = `
Map {
"SampleWithUppercaseNameJSI-generated.cpp" => "/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*
* @generated by codegen project: GenerateModuleCpp.js
*/
#include \\"SampleWithUppercaseNameJSI.h\\"
namespace facebook::react {
NativeSampleTurboModuleCxxSpecJSI::NativeSampleTurboModuleCxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker)
: TurboModule(\\"SampleTurboModule\\", jsInvoker) {
}
} // namespace facebook::react
",
}
`;
exports[`GenerateModuleCpp can generate fixture complex_objects 1`] = `
Map {
"complex_objectsJSI-generated.cpp" => "/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*
* @generated by codegen project: GenerateModuleCpp.js
*/
#include \\"complex_objectsJSI.h\\"
namespace facebook::react {
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_difficult(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->difficult(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt)
);
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_optionals(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->optionals(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt)
);
return jsi::Value::undefined();
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_optionalMethod(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->optionalMethod(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt),
count <= 1 ? throw jsi::JSError(rt, \\"Expected argument in position 1 to be passed\\") : args[1].asObject(rt).asFunction(rt),
count <= 2 || args[2].isUndefined() ? std::nullopt : std::make_optional(args[2].asObject(rt).asArray(rt))
);
return jsi::Value::undefined();
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getArrays(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getArrays(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt)
);
return jsi::Value::undefined();
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getNullableObject(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
auto result = static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getNullableObject(
rt
);
return result ? jsi::Value(std::move(*result)) : jsi::Value::null();
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getNullableGenericObject(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
auto result = static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getNullableGenericObject(
rt
);
return result ? jsi::Value(std::move(*result)) : jsi::Value::null();
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getNullableArray(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
auto result = static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getNullableArray(
rt
);
return result ? jsi::Value(std::move(*result)) : jsi::Value::null();
}
NativeSampleTurboModuleCxxSpecJSI::NativeSampleTurboModuleCxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker)
: TurboModule(\\"SampleTurboModule\\", jsInvoker) {
methodMap_[\\"difficult\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_difficult};
methodMap_[\\"optionals\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_optionals};
methodMap_[\\"optionalMethod\\"] = MethodMetadata {3, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_optionalMethod};
methodMap_[\\"getArrays\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getArrays};
methodMap_[\\"getNullableObject\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getNullableObject};
methodMap_[\\"getNullableGenericObject\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getNullableGenericObject};
methodMap_[\\"getNullableArray\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getNullableArray};
}
} // namespace facebook::react
",
}
`;
exports[`GenerateModuleCpp can generate fixture cxx_only_native_modules 1`] = `
Map {
"cxx_only_native_modulesJSI-generated.cpp" => "/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*
* @generated by codegen project: GenerateModuleCpp.js
*/
#include \\"cxx_only_native_modulesJSI.h\\"
namespace facebook::react {
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getArray(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getArray(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asArray(rt)
);
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getBool(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getBool(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asBool()
);
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getConstants(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getConstants(
rt
);
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getCustomEnum(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getCustomEnum(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asNumber()
);
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getCustomHostObject(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getCustomHostObject(
rt
);
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_consumeCustomHostObject(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->consumeCustomHostObject(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt)
);
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getBinaryTreeNode(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getBinaryTreeNode(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt)
);
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getGraphNode(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getGraphNode(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt)
);
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getNumEnum(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getNumEnum(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asNumber()
);
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getStrEnum(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getStrEnum(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asString(rt)
);
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getMap(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getMap(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt)
);
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getNumber(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getNumber(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asNumber()
);
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getObject(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getObject(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt)
);
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getSet(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getSet(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asArray(rt)
);
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getString(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getString(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asString(rt)
);
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getUnion(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getUnion(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asNumber(),
count <= 1 ? throw jsi::JSError(rt, \\"Expected argument in position 1 to be passed\\") : args[1].asString(rt),
count <= 2 ? throw jsi::JSError(rt, \\"Expected argument in position 2 to be passed\\") : args[2].asString(rt),
count <= 3 ? throw jsi::JSError(rt, \\"Expected argument in position 3 to be passed\\") : args[3].asObject(rt)
);
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValue(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getValue(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asNumber(),
count <= 1 ? throw jsi::JSError(rt, \\"Expected argument in position 1 to be passed\\") : args[1].asString(rt),
count <= 2 ? throw jsi::JSError(rt, \\"Expected argument in position 2 to be passed\\") : args[2].asObject(rt)
);
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValueWithCallback(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getValueWithCallback(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asFunction(rt)
);
return jsi::Value::undefined();
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValueWithPromise(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getValueWithPromise(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asBool()
);
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getWithWithOptionalArgs(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
auto result = static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getWithWithOptionalArgs(
rt,
count <= 0 || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asBool())
);
return result ? jsi::Value(std::move(*result)) : jsi::Value::null();
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_voidFunc(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->voidFunc(
rt
);
return jsi::Value::undefined();
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_setMenu(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->setMenu(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt)
);
return jsi::Value::undefined();
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_emitCustomDeviceEvent(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->emitCustomDeviceEvent(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asString(rt)
);
return jsi::Value::undefined();
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_voidFuncThrows(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->voidFuncThrows(
rt
);
return jsi::Value::undefined();
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getObjectThrows(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getObjectThrows(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt)
);
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_voidFuncAssert(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->voidFuncAssert(
rt
);
return jsi::Value::undefined();
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getObjectAssert(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getObjectAssert(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt)
);
}
NativeSampleTurboModuleCxxSpecJSI::NativeSampleTurboModuleCxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker)
: TurboModule(\\"SampleTurboModuleCxx\\", jsInvoker) {
methodMap_[\\"getArray\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getArray};
methodMap_[\\"getBool\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getBool};
methodMap_[\\"getConstants\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getConstants};
methodMap_[\\"getCustomEnum\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getCustomEnum};
methodMap_[\\"getCustomHostObject\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getCustomHostObject};
methodMap_[\\"consumeCustomHostObject\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_consumeCustomHostObject};
methodMap_[\\"getBinaryTreeNode\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getBinaryTreeNode};
methodMap_[\\"getGraphNode\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getGraphNode};
methodMap_[\\"getNumEnum\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getNumEnum};
methodMap_[\\"getStrEnum\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getStrEnum};
methodMap_[\\"getMap\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getMap};
methodMap_[\\"getNumber\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getNumber};
methodMap_[\\"getObject\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getObject};
methodMap_[\\"getSet\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getSet};
methodMap_[\\"getString\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getString};
methodMap_[\\"getUnion\\"] = MethodMetadata {4, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getUnion};
methodMap_[\\"getValue\\"] = MethodMetadata {3, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValue};
methodMap_[\\"getValueWithCallback\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValueWithCallback};
methodMap_[\\"getValueWithPromise\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValueWithPromise};
methodMap_[\\"getWithWithOptionalArgs\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getWithWithOptionalArgs};
methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_voidFunc};
methodMap_[\\"setMenu\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_setMenu};
methodMap_[\\"emitCustomDeviceEvent\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_emitCustomDeviceEvent};
methodMap_[\\"voidFuncThrows\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_voidFuncThrows};
methodMap_[\\"getObjectThrows\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getObjectThrows};
methodMap_[\\"voidFuncAssert\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_voidFuncAssert};
methodMap_[\\"getObjectAssert\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getObjectAssert};
}
} // namespace facebook::react
",
}
`;
exports[`GenerateModuleCpp can generate fixture empty_native_modules 1`] = `
Map {
"empty_native_modulesJSI-generated.cpp" => "/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*
* @generated by codegen project: GenerateModuleCpp.js
*/
#include \\"empty_native_modulesJSI.h\\"
namespace facebook::react {
NativeSampleTurboModuleCxxSpecJSI::NativeSampleTurboModuleCxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker)
: TurboModule(\\"SampleTurboModule\\", jsInvoker) {
}
} // namespace facebook::react
",
}
`;
exports[`GenerateModuleCpp can generate fixture event_emitter_module 1`] = `
Map {
"event_emitter_moduleJSI-generated.cpp" => "/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*
* @generated by codegen project: GenerateModuleCpp.js
*/
#include \\"event_emitter_moduleJSI.h\\"
namespace facebook::react {
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_voidFunc(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->voidFunc(
rt
);
return jsi::Value::undefined();
}
NativeSampleTurboModuleCxxSpecJSI::NativeSampleTurboModuleCxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker)
: TurboModule(\\"SampleTurboModule\\", jsInvoker) {
methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_voidFunc};
}
} // namespace facebook::react
",
}
`;
exports[`GenerateModuleCpp can generate fixture native_modules_with_type_aliases 1`] = `
Map {
"native_modules_with_type_aliasesJSI-generated.cpp" => "/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*
* @generated by codegen project: GenerateModuleCpp.js
*/
#include \\"native_modules_with_type_aliasesJSI.h\\"
namespace facebook::react {
static jsi::Value __hostFunction_AliasTurboModuleCxxSpecJSI_getConstants(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<AliasTurboModuleCxxSpecJSI *>(&turboModule)->getConstants(
rt
);
}
static jsi::Value __hostFunction_AliasTurboModuleCxxSpecJSI_cropImage(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
static_cast<AliasTurboModuleCxxSpecJSI *>(&turboModule)->cropImage(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt)
);
return jsi::Value::undefined();
}
AliasTurboModuleCxxSpecJSI::AliasTurboModuleCxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker)
: TurboModule(\\"AliasTurboModule\\", jsInvoker) {
methodMap_[\\"getConstants\\"] = MethodMetadata {0, __hostFunction_AliasTurboModuleCxxSpecJSI_getConstants};
methodMap_[\\"cropImage\\"] = MethodMetadata {1, __hostFunction_AliasTurboModuleCxxSpecJSI_cropImage};
}
} // namespace facebook::react
",
}
`;
exports[`GenerateModuleCpp can generate fixture real_module_example 1`] = `
Map {
"real_module_exampleJSI-generated.cpp" => "/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*
* @generated by codegen project: GenerateModuleCpp.js
*/
#include \\"real_module_exampleJSI.h\\"
namespace facebook::react {
static jsi::Value __hostFunction_NativeCameraRollManagerCxxSpecJSI_getConstants(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeCameraRollManagerCxxSpecJSI *>(&turboModule)->getConstants(
rt
);
}
static jsi::Value __hostFunction_NativeCameraRollManagerCxxSpecJSI_getPhotos(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeCameraRollManagerCxxSpecJSI *>(&turboModule)->getPhotos(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt)
);
}
static jsi::Value __hostFunction_NativeCameraRollManagerCxxSpecJSI_saveToCameraRoll(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeCameraRollManagerCxxSpecJSI *>(&turboModule)->saveToCameraRoll(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asString(rt),
count <= 1 ? throw jsi::JSError(rt, \\"Expected argument in position 1 to be passed\\") : args[1].asString(rt)
);
}
static jsi::Value __hostFunction_NativeCameraRollManagerCxxSpecJSI_deletePhotos(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeCameraRollManagerCxxSpecJSI *>(&turboModule)->deletePhotos(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asArray(rt)
);
}
NativeCameraRollManagerCxxSpecJSI::NativeCameraRollManagerCxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker)
: TurboModule(\\"CameraRollManager\\", jsInvoker) {
methodMap_[\\"getConstants\\"] = MethodMetadata {0, __hostFunction_NativeCameraRollManagerCxxSpecJSI_getConstants};
methodMap_[\\"getPhotos\\"] = MethodMetadata {1, __hostFunction_NativeCameraRollManagerCxxSpecJSI_getPhotos};
methodMap_[\\"saveToCameraRoll\\"] = MethodMetadata {2, __hostFunction_NativeCameraRollManagerCxxSpecJSI_saveToCameraRoll};
methodMap_[\\"deletePhotos\\"] = MethodMetadata {1, __hostFunction_NativeCameraRollManagerCxxSpecJSI_deletePhotos};
}
static jsi::Value __hostFunction_NativeExceptionsManagerCxxSpecJSI_reportFatalException(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
static_cast<NativeExceptionsManagerCxxSpecJSI *>(&turboModule)->reportFatalException(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asString(rt),
count <= 1 ? throw jsi::JSError(rt, \\"Expected argument in position 1 to be passed\\") : args[1].asObject(rt).asArray(rt),
count <= 2 ? throw jsi::JSError(rt, \\"Expected argument in position 2 to be passed\\") : args[2].asNumber()
);
return jsi::Value::undefined();
}
static jsi::Value __hostFunction_NativeExceptionsManagerCxxSpecJSI_reportSoftException(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
static_cast<NativeExceptionsManagerCxxSpecJSI *>(&turboModule)->reportSoftException(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asString(rt),
count <= 1 ? throw jsi::JSError(rt, \\"Expected argument in position 1 to be passed\\") : args[1].asObject(rt).asArray(rt),
count <= 2 ? throw jsi::JSError(rt, \\"Expected argument in position 2 to be passed\\") : args[2].asNumber()
);
return jsi::Value::undefined();
}
static jsi::Value __hostFunction_NativeExceptionsManagerCxxSpecJSI_reportException(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
static_cast<NativeExceptionsManagerCxxSpecJSI *>(&turboModule)->reportException(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt)
);
return jsi::Value::undefined();
}
static jsi::Value __hostFunction_NativeExceptionsManagerCxxSpecJSI_updateExceptionMessage(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
static_cast<NativeExceptionsManagerCxxSpecJSI *>(&turboModule)->updateExceptionMessage(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asString(rt),
count <= 1 ? throw jsi::JSError(rt, \\"Expected argument in position 1 to be passed\\") : args[1].asObject(rt).asArray(rt),
count <= 2 ? throw jsi::JSError(rt, \\"Expected argument in position 2 to be passed\\") : args[2].asNumber()
);
return jsi::Value::undefined();
}
static jsi::Value __hostFunction_NativeExceptionsManagerCxxSpecJSI_dismissRedbox(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
static_cast<NativeExceptionsManagerCxxSpecJSI *>(&turboModule)->dismissRedbox(
rt
);
return jsi::Value::undefined();
}
NativeExceptionsManagerCxxSpecJSI::NativeExceptionsManagerCxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker)
: TurboModule(\\"ExceptionsManager\\", jsInvoker) {
methodMap_[\\"reportFatalException\\"] = MethodMetadata {3, __hostFunction_NativeExceptionsManagerCxxSpecJSI_reportFatalException};
methodMap_[\\"reportSoftException\\"] = MethodMetadata {3, __hostFunction_NativeExceptionsManagerCxxSpecJSI_reportSoftException};
methodMap_[\\"reportException\\"] = MethodMetadata {1, __hostFunction_NativeExceptionsManagerCxxSpecJSI_reportException};
methodMap_[\\"updateExceptionMessage\\"] = MethodMetadata {3, __hostFunction_NativeExceptionsManagerCxxSpecJSI_updateExceptionMessage};
methodMap_[\\"dismissRedbox\\"] = MethodMetadata {0, __hostFunction_NativeExceptionsManagerCxxSpecJSI_dismissRedbox};
}
} // namespace facebook::react
",
}
`;
exports[`GenerateModuleCpp can generate fixture simple_native_modules 1`] = `
Map {
"simple_native_modulesJSI-generated.cpp" => "/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*
* @generated by codegen project: GenerateModuleCpp.js
*/
#include \\"simple_native_modulesJSI.h\\"
namespace facebook::react {
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getConstants(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getConstants(
rt
);
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_voidFunc(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->voidFunc(
rt
);
return jsi::Value::undefined();
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getBool(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getBool(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asBool()
);
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getNumber(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getNumber(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asNumber()
);
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getString(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getString(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asString(rt)
);
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getArray(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getArray(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asArray(rt)
);
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getObject(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getObject(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt)
);
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getRootTag(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getRootTag(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asNumber()
);
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValue(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getValue(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asNumber(),
count <= 1 ? throw jsi::JSError(rt, \\"Expected argument in position 1 to be passed\\") : args[1].asString(rt),
count <= 2 ? throw jsi::JSError(rt, \\"Expected argument in position 2 to be passed\\") : args[2].asObject(rt)
);
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getEnumReturn(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getEnumReturn(
rt
);
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValueWithCallback(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getValueWithCallback(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asFunction(rt)
);
return jsi::Value::undefined();
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValueWithPromise(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getValueWithPromise(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asBool()
);
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValueWithOptionalArg(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getValueWithOptionalArg(
rt,
count <= 0 || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt))
);
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getEnums(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getEnums(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asNumber(),
count <= 1 ? throw jsi::JSError(rt, \\"Expected argument in position 1 to be passed\\") : args[1].asNumber(),
count <= 2 ? throw jsi::JSError(rt, \\"Expected argument in position 2 to be passed\\") : args[2].asString(rt)
);
}
NativeSampleTurboModuleCxxSpecJSI::NativeSampleTurboModuleCxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker)
: TurboModule(\\"SampleTurboModule\\", jsInvoker) {
methodMap_[\\"getConstants\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getConstants};
methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_voidFunc};
methodMap_[\\"getBool\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getBool};
methodMap_[\\"getNumber\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getNumber};
methodMap_[\\"getString\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getString};
methodMap_[\\"getArray\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getArray};
methodMap_[\\"getObject\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getObject};
methodMap_[\\"getRootTag\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getRootTag};
methodMap_[\\"getValue\\"] = MethodMetadata {3, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValue};
methodMap_[\\"getEnumReturn\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getEnumReturn};
methodMap_[\\"getValueWithCallback\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValueWithCallback};
methodMap_[\\"getValueWithPromise\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValueWithPromise};
methodMap_[\\"getValueWithOptionalArg\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValueWithOptionalArg};
methodMap_[\\"getEnums\\"] = MethodMetadata {3, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getEnums};
}
} // namespace facebook::react
",
}
`;
exports[`GenerateModuleCpp can generate fixture string_literals 1`] = `
Map {
"string_literalsJSI-generated.cpp" => "/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*
* @generated by codegen project: GenerateModuleCpp.js
*/
#include \\"string_literalsJSI.h\\"
namespace facebook::react {
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getStringLiteral(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getStringLiteral(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asString(rt)
);
}
NativeSampleTurboModuleCxxSpecJSI::NativeSampleTurboModuleCxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker)
: TurboModule(\\"SampleTurboModule\\", jsInvoker) {
methodMap_[\\"getStringLiteral\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getStringLiteral};
}
} // namespace facebook::react
",
}
`;
exports[`GenerateModuleCpp can generate fixture two_modules_different_files 1`] = `
Map {
"two_modules_different_filesJSI-generated.cpp" => "/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*
* @generated by codegen project: GenerateModuleCpp.js
*/
#include \\"two_modules_different_filesJSI.h\\"
namespace facebook::react {
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_voidFunc(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->voidFunc(
rt
);
return jsi::Value::undefined();
}
NativeSampleTurboModuleCxxSpecJSI::NativeSampleTurboModuleCxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker)
: TurboModule(\\"SampleTurboModule\\", jsInvoker) {
methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_voidFunc};
}
static jsi::Value __hostFunction_NativeSampleTurboModule2CxxSpecJSI_getConstants(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeSampleTurboModule2CxxSpecJSI *>(&turboModule)->getConstants(
rt
);
}
static jsi::Value __hostFunction_NativeSampleTurboModule2CxxSpecJSI_voidFunc(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
static_cast<NativeSampleTurboModule2CxxSpecJSI *>(&turboModule)->voidFunc(
rt
);
return jsi::Value::undefined();
}
NativeSampleTurboModule2CxxSpecJSI::NativeSampleTurboModule2CxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker)
: TurboModule(\\"SampleTurboModule2\\", jsInvoker) {
methodMap_[\\"getConstants\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModule2CxxSpecJSI_getConstants};
methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModule2CxxSpecJSI_voidFunc};
}
} // namespace facebook::react
",
}
`;
exports[`GenerateModuleCpp can generate fixture union_module 1`] = `
Map {
"union_moduleJSI-generated.cpp" => "/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*
* @generated by codegen project: GenerateModuleCpp.js
*/
#include \\"union_moduleJSI.h\\"
namespace facebook::react {
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getUnion(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getUnion(
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asNumber(),
count <= 1 ? throw jsi::JSError(rt, \\"Expected argument in position 1 to be passed\\") : args[1].asNumber(),
count <= 2 ? throw jsi::JSError(rt, \\"Expected argument in position 2 to be passed\\") : args[2].asObject(rt),
count <= 3 ? throw jsi::JSError(rt, \\"Expected argument in position 3 to be passed\\") : args[3].asString(rt),
count <= 4 ? throw jsi::JSError(rt, \\"Expected argument in position 4 to be passed\\") : args[4].asString(rt)
);
}
NativeSampleTurboModuleCxxSpecJSI::NativeSampleTurboModuleCxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker)
: TurboModule(\\"SampleTurboModule\\", jsInvoker) {
methodMap_[\\"getUnion\\"] = MethodMetadata {5, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getUnion};
}
} // namespace facebook::react
",
}
`;
@@ -120,7 +120,6 @@ std::unique_ptr<facebook::react::JSExecutorFactory> RCTAppSetupDefaultJsExecutor
RCTTurboModuleManager *turboModuleManager,
const std::shared_ptr<facebook::react::RuntimeScheduler> &runtimeScheduler)
{
#ifndef RCT_REMOVE_LEGACY_ARCH
// Necessary to allow NativeModules to lookup TurboModules
[bridge setRCTTurboModuleRegistry:turboModuleManager];
@@ -147,18 +146,12 @@ std::unique_ptr<facebook::react::JSExecutorFactory> RCTAppSetupDefaultJsExecutor
return std::make_unique<facebook::react::HermesExecutorFactory>(
facebook::react::RCTJSIExecutorRuntimeInstaller(runtimeInstallerLambda));
#endif
#else
// This method should not be invoked in the New Arch. So when Legacy Arch is removed, we can
// safly return a nullptr.
return nullptr;
#endif
}
std::unique_ptr<facebook::react::JSExecutorFactory> RCTAppSetupJsExecutorFactoryForOldArch(
RCTBridge *bridge,
const std::shared_ptr<facebook::react::RuntimeScheduler> &runtimeScheduler)
{
#ifndef RCT_REMOVE_LEGACY_ARCH
auto runtimeInstallerLambda = [bridge, runtimeScheduler](facebook::jsi::Runtime &runtime) {
if (!bridge) {
return;
@@ -171,9 +164,4 @@ std::unique_ptr<facebook::react::JSExecutorFactory> RCTAppSetupJsExecutorFactory
return std::make_unique<facebook::react::HermesExecutorFactory>(
facebook::react::RCTJSIExecutorRuntimeInstaller(runtimeInstallerLambda));
#endif
#else
// This method should not be invoked in the New Arch. So when Legacy Arch is removed, we can
// safly return a nullptr.
return nullptr;
#endif
}
@@ -261,12 +261,7 @@ using namespace facebook::react;
configuration.sourceURLForBridge = ^NSURL *_Nullable(RCTBridge *_Nonnull bridge)
{
#ifndef RCT_REMOVE_LEGACY_ARCH
return [weakSelf.delegate sourceURLForBridge:bridge];
#else
// When the Legacy Arch is removed, the Delegate does not have a sourceURLForBridge method
return [weakSelf.delegate bundleURL];
#endif
};
if ([self.delegate respondsToSelector:@selector(extraModulesForBridge:)]) {
@@ -280,24 +275,13 @@ using namespace facebook::react;
configuration.extraLazyModuleClassesForBridge =
^NSDictionary<NSString *, Class> *_Nonnull(RCTBridge *_Nonnull bridge)
{
#ifndef RCT_REMOVE_LEGACY_ARCH
return [weakSelf.delegate extraLazyModuleClassesForBridge:bridge];
#else
// When the Legacy Arch is removed, the Delegate does not have a extraLazyModuleClassesForBridge method
return @{};
#endif
};
}
if ([self.delegate respondsToSelector:@selector(bridge:didNotFindModule:)]) {
configuration.bridgeDidNotFindModule = ^BOOL(RCTBridge *_Nonnull bridge, NSString *_Nonnull moduleName) {
#ifndef RCT_REMOVE_LEGACY_ARCH
return [weakSelf.delegate bridge:bridge didNotFindModule:moduleName];
#else
// When the Legacy Arch is removed, the Delegate does not have a bridge:didNotFindModule method
// We return NO, because if we have invoked this method is unlikely that the module will be actually registered
return NO;
#endif
};
}
@@ -306,30 +290,13 @@ using namespace facebook::react;
^(RCTBridge *_Nonnull bridge,
RCTSourceLoadProgressBlock _Nonnull onProgress,
RCTSourceLoadBlock _Nonnull loadCallback) {
#ifndef RCT_REMOVE_LEGACY_ARCH
[weakSelf.delegate loadSourceForBridge:bridge onProgress:onProgress onComplete:loadCallback];
#else
// When the Legacy Arch is removed, the Delegate does not have a
// loadSourceForBridge:onProgress:onComplete: method
// We then call the loadBundleAtURL:onProgress:onComplete: instead
[weakSelf.delegate loadBundleAtURL:self.bundleURL onProgress:onProgress onComplete:loadCallback];
#endif
};
}
if ([self.delegate respondsToSelector:@selector(loadSourceForBridge:withBlock:)]) {
configuration.loadSourceForBridge = ^(RCTBridge *_Nonnull bridge, RCTSourceLoadBlock _Nonnull loadCallback) {
#ifndef RCT_REMOVE_LEGACY_ARCH
[weakSelf.delegate loadSourceForBridge:bridge withBlock:loadCallback];
#else
// When the Legacy Arch is removed, the Delegate does not have a
// loadSourceForBridge:withBlock: method
// We then call the loadBundleAtURL:onProgress:onComplete: instead
[weakSelf.delegate loadBundleAtURL:self.bundleURL
onProgress:^(RCTLoadingProgress *progressData) {
}
onComplete:loadCallback];
#endif
};
}
@@ -24,9 +24,11 @@ RCT_EXPORT_MODULE(FileReaderModule)
@synthesize moduleRegistry = _moduleRegistry;
RCT_EXPORT_METHOD(
readAsText : (NSDictionary<NSString *, id> *)blob encoding : (NSString *)encoding resolve : (RCTPromiseResolveBlock)
resolve reject : (RCTPromiseRejectBlock)reject)
RCT_EXPORT_METHOD(readAsText
: (NSDictionary<NSString *, id> *)blob encoding
: (NSString *)encoding resolve
: (RCTPromiseResolveBlock)resolve reject
: (RCTPromiseRejectBlock)reject)
{
RCTBlobManager *blobManager = [_moduleRegistry moduleForName:"BlobModule"];
dispatch_async(blobManager.methodQueue, ^{
@@ -54,9 +56,10 @@ RCT_EXPORT_METHOD(
});
}
RCT_EXPORT_METHOD(
readAsDataURL : (NSDictionary<NSString *, id> *)blob resolve : (RCTPromiseResolveBlock)
resolve reject : (RCTPromiseRejectBlock)reject)
RCT_EXPORT_METHOD(readAsDataURL
: (NSDictionary<NSString *, id> *)blob resolve
: (RCTPromiseResolveBlock)resolve reject
: (RCTPromiseRejectBlock)reject)
{
RCTBlobManager *blobManager = [_moduleRegistry moduleForName:"BlobModule"];
dispatch_async(blobManager.methodQueue, ^{
@@ -99,7 +99,7 @@ const AccessibilityInfo = {
reject,
);
} else {
reject(new Error('NativeAccessibilityManagerIOS is not available'));
reject(null);
}
});
}
@@ -119,11 +119,7 @@ const AccessibilityInfo = {
if (NativeAccessibilityInfoAndroid?.isGrayscaleEnabled != null) {
NativeAccessibilityInfoAndroid.isGrayscaleEnabled(resolve);
} else {
reject(
new Error(
'NativeAccessibilityInfoAndroid.isGrayscaleEnabled is not available',
),
);
reject(null);
}
});
} else {
@@ -134,7 +130,7 @@ const AccessibilityInfo = {
reject,
);
} else {
reject(new Error('AccessibilityInfo native module is not available'));
reject(null);
}
});
}
@@ -154,11 +150,7 @@ const AccessibilityInfo = {
if (NativeAccessibilityInfoAndroid?.isInvertColorsEnabled != null) {
NativeAccessibilityInfoAndroid.isInvertColorsEnabled(resolve);
} else {
reject(
new Error(
'NativeAccessibilityInfoAndroid.isInvertColorsEnabled is not available',
),
);
reject(null);
}
});
} else {
@@ -169,7 +161,7 @@ const AccessibilityInfo = {
reject,
);
} else {
reject(new Error('AccessibilityInfo native module is not available'));
reject(null);
}
});
}
@@ -189,7 +181,7 @@ const AccessibilityInfo = {
if (NativeAccessibilityInfoAndroid != null) {
NativeAccessibilityInfoAndroid.isReduceMotionEnabled(resolve);
} else {
reject(new Error('AccessibilityInfo native module is not available'));
reject(null);
}
} else {
if (NativeAccessibilityManagerIOS != null) {
@@ -198,7 +190,7 @@ const AccessibilityInfo = {
reject,
);
} else {
reject(new Error('NativeAccessibilityManagerIOS is not available'));
reject(null);
}
}
});
@@ -216,11 +208,7 @@ const AccessibilityInfo = {
if (NativeAccessibilityInfoAndroid?.isHighTextContrastEnabled != null) {
NativeAccessibilityInfoAndroid.isHighTextContrastEnabled(resolve);
} else {
reject(
new Error(
'NativeAccessibilityInfoAndroid.isHighTextContrastEnabled is not available',
),
);
reject(null);
}
} else {
return Promise.resolve(false);
@@ -248,11 +236,7 @@ const AccessibilityInfo = {
reject,
);
} else {
reject(
new Error(
'NativeAccessibilityManagerIOS.getCurrentDarkerSystemColorsState is not available',
),
);
reject(null);
}
}
});
@@ -280,11 +264,7 @@ const AccessibilityInfo = {
reject,
);
} else {
reject(
new Error(
'NativeAccessibilityManagerIOS.getCurrentPrefersCrossFadeTransitionsState is not available',
),
);
reject(null);
}
}
});
@@ -309,7 +289,7 @@ const AccessibilityInfo = {
reject,
);
} else {
reject(new Error('NativeAccessibilityManagerIOS is not available'));
reject(null);
}
});
}
@@ -329,7 +309,7 @@ const AccessibilityInfo = {
if (NativeAccessibilityInfoAndroid != null) {
NativeAccessibilityInfoAndroid.isTouchExplorationEnabled(resolve);
} else {
reject(new Error('NativeAccessibilityInfoAndroid is not available'));
reject(null);
}
} else {
if (NativeAccessibilityManagerIOS != null) {
@@ -338,7 +318,7 @@ const AccessibilityInfo = {
reject,
);
} else {
reject(new Error('NativeAccessibilityManagerIOS is not available'));
reject(null);
}
}
});
@@ -363,18 +343,10 @@ const AccessibilityInfo = {
) {
NativeAccessibilityInfoAndroid.isAccessibilityServiceEnabled(resolve);
} else {
reject(
new Error(
'NativeAccessibilityInfoAndroid.isAccessibilityServiceEnabled is not available',
),
);
reject(null);
}
} else {
reject(
new Error(
'isAccessibilityServiceEnabled is only available on Android',
),
);
reject(null);
}
});
},
@@ -9,7 +9,7 @@
import type * as React from 'react';
import {Constructor} from '../../../types/private/Utilities';
import {HostInstance} from '../../../types/public/ReactNativeTypes';
import {NativeMethods} from '../../../types/public/ReactNativeTypes';
import {ColorValue, StyleProp} from '../../StyleSheet/StyleSheet';
import {ViewStyle} from '../../StyleSheet/StyleSheetTypes';
import {LayoutChangeEvent} from '../../Types/CoreEventTypes';
@@ -46,7 +46,7 @@ export interface ActivityIndicatorProps extends ViewProps {
}
declare class ActivityIndicatorComponent extends React.Component<ActivityIndicatorProps> {}
declare const ActivityIndicatorBase: Constructor<HostInstance> &
declare const ActivityIndicatorBase: Constructor<NativeMethods> &
typeof ActivityIndicatorComponent;
export class ActivityIndicator extends ActivityIndicatorBase {}
@@ -9,7 +9,7 @@
import type * as React from 'react';
import {Constructor} from '../../../types/private/Utilities';
import {HostInstance} from '../../../types/public/ReactNativeTypes';
import {NativeMethods} from '../../../types/public/ReactNativeTypes';
import {ColorValue} from '../../StyleSheet/StyleSheet';
import {
NativeSyntheticEvent,
@@ -121,7 +121,7 @@ interface DrawerPosition {
}
declare class DrawerLayoutAndroidComponent extends React.Component<DrawerLayoutAndroidProps> {}
declare const DrawerLayoutAndroidBase: Constructor<HostInstance> &
declare const DrawerLayoutAndroidBase: Constructor<NativeMethods> &
typeof DrawerLayoutAndroidComponent;
export class DrawerLayoutAndroid extends DrawerLayoutAndroidBase {
/**
@@ -9,7 +9,7 @@
import type * as React from 'react';
import {Constructor} from '../../../types/private/Utilities';
import {HostInstance} from '../../../types/public/ReactNativeTypes';
import {NativeMethods} from '../../../types/public/ReactNativeTypes';
import {ColorValue} from '../../StyleSheet/StyleSheet';
import {ViewProps} from '../View/ViewPropTypes';
@@ -72,7 +72,7 @@ export interface ProgressBarAndroidProps extends ViewProps {
* that the app is loading or there is some activity in the app.
*/
declare class ProgressBarAndroidComponent extends React.Component<ProgressBarAndroidProps> {}
declare const ProgressBarAndroidBase: Constructor<HostInstance> &
declare const ProgressBarAndroidBase: Constructor<NativeMethods> &
typeof ProgressBarAndroidComponent;
/**
* ProgressBarAndroid has been extracted from react-native core and will be removed in a future release.
@@ -9,7 +9,7 @@
import type * as React from 'react';
import {Constructor} from '../../../types/private/Utilities';
import {HostInstance} from '../../../types/public/ReactNativeTypes';
import {NativeMethods} from '../../../types/public/ReactNativeTypes';
import {ColorValue} from '../../StyleSheet/StyleSheet';
import {ViewProps} from '../View/ViewPropTypes';
@@ -80,7 +80,7 @@ export interface RefreshControlProps
* in the `onRefresh` function otherwise the refresh indicator will stop immediately.
*/
declare class RefreshControlComponent extends React.Component<RefreshControlProps> {}
declare const RefreshControlBase: Constructor<HostInstance> &
declare const RefreshControlBase: Constructor<NativeMethods> &
typeof RefreshControlComponent;
export class RefreshControl extends RefreshControlBase {
static SIZE: Object; // Undocumented
@@ -9,7 +9,7 @@
import type * as React from 'react';
import {Constructor} from '../../../types/private/Utilities';
import {HostInstance} from '../../../types/public/ReactNativeTypes';
import {NativeMethods} from '../../../types/public/ReactNativeTypes';
import {ViewProps} from '../View/ViewPropTypes';
/**
@@ -23,7 +23,7 @@ import {ViewProps} from '../View/ViewPropTypes';
*/
declare class SafeAreaViewComponent extends React.Component<ViewProps> {}
declare const SafeAreaViewBase: Constructor<HostInstance> &
declare const SafeAreaViewBase: Constructor<NativeMethods> &
typeof SafeAreaViewComponent;
/**
@@ -12,10 +12,12 @@ import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
import type {HostInstance} from 'react-native';
import ensureInstance from '../../../../src/private/__tests__/utilities/ensureInstance';
import * as Fantom from '@react-native/fantom';
import * as React from 'react';
import {createRef} from 'react';
import {ScrollView} from 'react-native';
import ReactNativeElement from 'react-native/src/private/webapis/dom/nodes/ReactNativeElement';
describe('onScroll', () => {
it('delivers onScroll event', () => {
@@ -34,9 +36,11 @@ describe('onScroll', () => {
);
});
const element = ensureInstance(scrollViewRef.current, ReactNativeElement);
Fantom.runOnUIThread(() => {
Fantom.enqueueNativeEvent(
scrollViewRef,
element,
'scroll',
{
contentOffset: {
@@ -76,9 +80,11 @@ describe('onScroll', () => {
);
});
const element = ensureInstance(scrollViewRef.current, ReactNativeElement);
Fantom.runOnUIThread(() => {
Fantom.enqueueNativeEvent(
scrollViewRef,
element,
'scroll',
{
contentOffset: {
@@ -91,7 +97,7 @@ describe('onScroll', () => {
},
);
Fantom.enqueueNativeEvent(
scrollViewRef,
element,
'scroll',
{
contentOffset: {
@@ -13,11 +13,13 @@ import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
import type {HostInstance} from 'react-native';
import ensureInstance from '../../../../src/private/__tests__/utilities/ensureInstance';
import * as Fantom from '@react-native/fantom';
import nullthrows from 'nullthrows';
import * as React from 'react';
import {createRef, useState} from 'react';
import {FlatList, Modal, ScrollView, View} from 'react-native';
import ReactNativeElement from 'react-native/src/private/webapis/dom/nodes/ReactNativeElement';
test('basic culling', () => {
const root = Fantom.createRoot({viewportWidth: 100, viewportHeight: 100});
@@ -44,7 +46,9 @@ test('basic culling', () => {
'Insert {type: "ScrollView", parentNativeID: (root), index: 0, nativeID: (N/A)}',
]);
Fantom.scrollTo(nodeRef, {
const element = ensureInstance(nodeRef.current, ReactNativeElement);
Fantom.scrollTo(element, {
x: 0,
y: 60,
});
@@ -57,7 +61,7 @@ test('basic culling', () => {
'Update {type: "ScrollView", nativeID: (N/A)}',
]);
Fantom.scrollTo(nodeRef, {
Fantom.scrollTo(element, {
x: 0,
y: 0,
});
@@ -114,8 +118,10 @@ test('recursive culling', () => {
'Insert {type: "ScrollView", parentNativeID: (root), index: 0, nativeID: (N/A)}',
]);
const element = ensureInstance(nodeRef.current, ReactNativeElement);
// === Scroll down to the edge of child AA ===
Fantom.scrollTo(nodeRef, {
Fantom.scrollTo(element, {
x: 0,
y: 30,
});
@@ -126,7 +132,7 @@ test('recursive culling', () => {
// === Scroll down past child AA ===
Fantom.scrollTo(nodeRef, {
Fantom.scrollTo(element, {
x: 0,
y: 36,
});
@@ -138,7 +144,7 @@ test('recursive culling', () => {
]);
// === Scroll down past child AB ===
Fantom.scrollTo(nodeRef, {
Fantom.scrollTo(element, {
x: 0,
y: 51,
});
@@ -150,7 +156,7 @@ test('recursive culling', () => {
]);
// === Scroll down past element A ===
Fantom.scrollTo(nodeRef, {
Fantom.scrollTo(element, {
x: 0,
y: 56,
});
@@ -162,7 +168,7 @@ test('recursive culling', () => {
]);
// Scroll element B into viewport. Just child BA should be created.
Fantom.scrollTo(nodeRef, {
Fantom.scrollTo(element, {
x: 0,
y: 155,
});
@@ -176,7 +182,7 @@ test('recursive culling', () => {
]);
// Scroll child BA into viewport.
Fantom.scrollTo(nodeRef, {
Fantom.scrollTo(element, {
x: 0,
y: 165,
});
@@ -188,7 +194,7 @@ test('recursive culling', () => {
]);
// Scroll back to start
Fantom.scrollTo(nodeRef, {
Fantom.scrollTo(element, {
x: 0,
y: 0,
});
@@ -210,7 +216,7 @@ test('recursive culling', () => {
]);
// Scroll past element A
Fantom.scrollTo(nodeRef, {
Fantom.scrollTo(element, {
x: 0,
y: 85,
});
@@ -259,7 +265,9 @@ test('recursive culling when initial offset is negative', () => {
'Insert {type: "ScrollView", parentNativeID: (root), index: 0, nativeID: (N/A)}',
]);
Fantom.scrollTo(nodeRef, {
const element = ensureInstance(nodeRef.current, ReactNativeElement);
Fantom.scrollTo(element, {
x: 0,
y: 0,
});
@@ -320,7 +328,9 @@ test('deep nesting', () => {
'Insert {type: "ScrollView", parentNativeID: (root), index: 0, nativeID: (N/A)}',
]);
Fantom.scrollTo(nodeRef, {
const element = ensureInstance(nodeRef.current, ReactNativeElement);
Fantom.scrollTo(element, {
x: 0,
y: 40,
});
@@ -335,7 +345,7 @@ test('deep nesting', () => {
'Insert {type: "View", parentNativeID: (N/A), index: 1, nativeID: "element B"}',
]);
Fantom.scrollTo(nodeRef, {
Fantom.scrollTo(element, {
x: 0,
y: 150,
});
@@ -479,7 +489,9 @@ test('initial render', () => {
'Insert {type: "ScrollView", parentNativeID: (root), index: 0, nativeID: (N/A)}',
]);
Fantom.scrollTo(nodeRef, {
const element = ensureInstance(nodeRef.current, ReactNativeElement);
Fantom.scrollTo(element, {
x: 0,
y: 100,
});
@@ -549,7 +561,9 @@ test('basic culling smaller ScrollView', () => {
'Insert {type: "ScrollView", parentNativeID: (root), index: 0, nativeID: (N/A)}',
]);
Fantom.scrollTo(nodeRef, {
const element = ensureInstance(nodeRef.current, ReactNativeElement);
Fantom.scrollTo(element, {
x: 0,
y: 11,
});
@@ -610,7 +624,9 @@ test('culling with transform move', () => {
'Insert {type: "ScrollView", parentNativeID: (root), index: 0, nativeID: (N/A)}',
]);
Fantom.scrollTo(nodeRef, {
const element = ensureInstance(nodeRef.current, ReactNativeElement);
Fantom.scrollTo(element, {
x: 0,
y: 1,
});
@@ -653,7 +669,9 @@ test('culling with recursive transform move', () => {
'Insert {type: "ScrollView", parentNativeID: (root), index: 0, nativeID: (N/A)}',
]);
Fantom.scrollTo(nodeRef, {
const element = ensureInstance(nodeRef.current, ReactNativeElement);
Fantom.scrollTo(element, {
x: 0,
y: 1,
});
@@ -695,7 +713,9 @@ test('culling with transform scale', () => {
'Insert {type: "ScrollView", parentNativeID: (root), index: 0, nativeID: (N/A)}',
]);
Fantom.scrollTo(nodeRef, {
const element = ensureInstance(nodeRef.current, ReactNativeElement);
Fantom.scrollTo(element, {
x: 0,
y: 121,
});
@@ -754,8 +774,10 @@ test('culling inside of Modal', () => {
);
});
const element = ensureInstance(nodeRef.current, ReactNativeElement);
Fantom.runOnUIThread(() => {
Fantom.enqueueModalSizeUpdate(nodeRef, {
Fantom.enqueueModalSizeUpdate(element, {
width: 100,
height: 100,
});
@@ -878,7 +900,9 @@ describe('reparenting', () => {
'Insert {type: "ScrollView", parentNativeID: (root), index: 0, nativeID: (N/A)}',
]);
Fantom.scrollTo(nodeRef, {
const element = ensureInstance(nodeRef.current, ReactNativeElement);
Fantom.scrollTo(element, {
x: 0,
y: 60,
});
@@ -1554,8 +1578,10 @@ describe('reparenting', () => {
'Insert {type: "View", parentNativeID: (N/A), index: 0, nativeID: "child"}',
]);
const element = ensureInstance(nodeRef.current, ReactNativeElement);
// Scroll down to see the grandchild.
Fantom.scrollTo(nodeRef, {
Fantom.scrollTo(element, {
x: 0,
y: 115,
});
@@ -1643,8 +1669,10 @@ describe('reparenting', () => {
'Insert {type: "View", parentNativeID: (N/A), index: 0, nativeID: "child"}',
]);
const element = ensureInstance(nodeRef.current, ReactNativeElement);
// Scroll down to see the grandchild.
Fantom.scrollTo(nodeRef, {
Fantom.scrollTo(element, {
x: 0,
y: 118,
});
@@ -1883,8 +1911,10 @@ describe('reparenting', () => {
'Insert {type: "View", parentNativeID: (N/A), index: 0, nativeID: (N/A)}',
]);
const element = ensureInstance(nodeRef.current, ReactNativeElement);
// Scroll to reveal grandchild.
Fantom.scrollTo(nodeRef, {
Fantom.scrollTo(element, {
x: 0,
y: 70,
});
@@ -1971,8 +2001,10 @@ describe('reparenting', () => {
'Insert {type: "View", parentNativeID: (N/A), index: 0, nativeID: (N/A)}',
]);
const element = ensureInstance(nodeRef.current, ReactNativeElement);
// Scroll to reveal grandchild.
Fantom.scrollTo(nodeRef, {
Fantom.scrollTo(element, {
x: 0,
y: 70,
});
@@ -2182,7 +2214,9 @@ describe('reparenting', () => {
'Insert {type: "View", parentNativeID: "unflattened", index: 0, nativeID: "child"}',
]);
Fantom.scrollTo(nodeRef, {
const element = ensureInstance(nodeRef.current, ReactNativeElement);
Fantom.scrollTo(element, {
x: 0,
y: 50,
});
@@ -2278,7 +2312,9 @@ describe('reparenting', () => {
'Insert {type: "View", parentNativeID: "unflattened", index: 0, nativeID: "child"}',
]);
Fantom.scrollTo(nodeRef, {
const element = ensureInstance(nodeRef.current, ReactNativeElement);
Fantom.scrollTo(element, {
x: 0,
y: 50,
});
@@ -2427,9 +2463,10 @@ describe('opt out mechanism - Unstable_uncullableView & Unstable_uncullableTrace
</ScrollView>,
);
});
const element = ensureInstance(nodeRef.current, ReactNativeElement);
Fantom.runOnUIThread(() => {
Fantom.enqueueModalSizeUpdate(nodeRef, {
Fantom.enqueueModalSizeUpdate(element, {
width: 100,
height: 100,
});
@@ -2480,8 +2517,10 @@ describe('opt out mechanism - Unstable_uncullableView & Unstable_uncullableTrace
);
});
const element = ensureInstance(nodeRef.current, ReactNativeElement);
Fantom.runOnUIThread(() => {
Fantom.enqueueModalSizeUpdate(nodeRef, {
Fantom.enqueueModalSizeUpdate(element, {
width: 100,
height: 100,
});
@@ -9,7 +9,7 @@
import type * as React from 'react';
import {Constructor} from '../../../types/private/Utilities';
import {HostInstance} from '../../../types/public/ReactNativeTypes';
import {NativeMethods} from '../../../types/public/ReactNativeTypes';
import {ColorValue, StyleProp} from '../../StyleSheet/StyleSheet';
import {ViewStyle} from '../../StyleSheet/StyleSheetTypes';
import {ViewProps} from '../View/ViewPropTypes';
@@ -114,5 +114,5 @@ export interface SwitchProps extends SwitchPropsIOS {
* the supplied `value` prop instead of the expected result of any user actions.
*/
declare class SwitchComponent extends React.Component<SwitchProps> {}
declare const SwitchBase: Constructor<HostInstance> & typeof SwitchComponent;
declare const SwitchBase: Constructor<NativeMethods> & typeof SwitchComponent;
export class Switch extends SwitchBase {}
@@ -10,7 +10,10 @@
import type * as React from 'react';
import {Constructor} from '../../../types/private/Utilities';
import {TimerMixin} from '../../../types/private/TimerMixin';
import {HostInstance} from '../../../types/public/ReactNativeTypes';
import {
HostInstance,
NativeMethods,
} from '../../../types/public/ReactNativeTypes';
import {ColorValue, StyleProp} from '../../StyleSheet/StyleSheet';
import {TextStyle} from '../../StyleSheet/StyleSheetTypes';
import {
@@ -1026,7 +1029,7 @@ interface TextInputState {
* @see https://reactnative.dev/docs/textinput#methods
*/
declare class TextInputComponent extends React.Component<TextInputProps> {}
declare const TextInputBase: Constructor<HostInstance> &
declare const TextInputBase: Constructor<NativeMethods> &
Constructor<TimerMixin> &
typeof TextInputComponent;
export class TextInput extends TextInputBase {
@@ -449,12 +449,6 @@ function InternalTextInput(props: TextInputProps): React.Node {
before we can get to the long term breaking change.
*/
if (instance != null) {
// Register the input immediately when the ref is set so that focus()
// can be called from ref callbacks
// Double registering during useLayoutEffect is fine, because the underlying
// state is a Set.
TextInputState.registerInput(instance);
// $FlowFixMe[prop-missing] - See the explanation above.
// $FlowFixMe[unsafe-object-assign]
Object.assign(instance, {
@@ -12,6 +12,7 @@ import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
import type {TextInputInstance} from '../TextInput.flow';
import ensureInstance from '../../../../src/private/__tests__/utilities/ensureInstance';
import * as Fantom from '@react-native/fantom';
import nullthrows from 'nullthrows';
import * as React from 'react';
@@ -59,8 +60,10 @@ describe('<TextInput>', () => {
);
});
const element = ensureInstance(nodeRef.current, ReactNativeElement);
Fantom.runOnUIThread(() => {
Fantom.enqueueNativeEvent(nodeRef, 'change', {
Fantom.enqueueNativeEvent(element, 'change', {
text: 'Hello World',
});
});
@@ -83,8 +86,10 @@ describe('<TextInput>', () => {
root.render(<TextInput onChangeText={onChangeText} ref={nodeRef} />);
});
const element = ensureInstance(nodeRef.current, ReactNativeElement);
Fantom.runOnUIThread(() => {
Fantom.enqueueNativeEvent(nodeRef, 'change', {
Fantom.enqueueNativeEvent(element, 'change', {
text: 'Hello World',
});
});
@@ -108,10 +113,12 @@ describe('<TextInput>', () => {
root.render(<TextInput onFocus={focusEvent} ref={nodeRef} />);
});
const element = ensureInstance(nodeRef.current, ReactNativeElement);
expect(focusEvent).toHaveBeenCalledTimes(0);
Fantom.runOnUIThread(() => {
Fantom.enqueueNativeEvent(nodeRef, 'focus');
Fantom.enqueueNativeEvent(element, 'focus');
});
// The tasks have not run.
@@ -134,10 +141,12 @@ describe('<TextInput>', () => {
root.render(<TextInput onBlur={blurEvent} ref={nodeRef} />);
});
const element = ensureInstance(nodeRef.current, ReactNativeElement);
expect(blurEvent).toHaveBeenCalledTimes(0);
Fantom.runOnUIThread(() => {
Fantom.enqueueNativeEvent(nodeRef, 'blur');
Fantom.enqueueNativeEvent(element, 'blur');
});
// The tasks have not run.
@@ -13,9 +13,6 @@ import type {AnyAttributeType} from '../../Renderer/shims/ReactNativeTypes';
import * as ReactNativeFeatureFlags from '../../../src/private/featureflags/ReactNativeFeatureFlags';
import processAspectRatio from '../../StyleSheet/processAspectRatio';
import processBackgroundImage from '../../StyleSheet/processBackgroundImage';
import processBackgroundPosition from '../../StyleSheet/processBackgroundPosition';
import processBackgroundRepeat from '../../StyleSheet/processBackgroundRepeat';
import processBackgroundSize from '../../StyleSheet/processBackgroundSize';
import processBoxShadow from '../../StyleSheet/processBoxShadow';
import processColor from '../../StyleSheet/processColor';
import processFilter from '../../StyleSheet/processFilter';
@@ -147,25 +144,10 @@ const ReactNativeStyleAttributes: {[string]: AnyAttributeType, ...} = {
: {process: processBoxShadow},
/**
* BackgroundImage
* Linear Gradient
*/
experimental_backgroundImage: {process: processBackgroundImage},
/**
* BackgroundSize
*/
experimental_backgroundSize: {process: processBackgroundSize},
/**
* BackgroundPosition
*/
experimental_backgroundPosition: {process: processBackgroundPosition},
/**
* BackgroundRepeat
*/
experimental_backgroundRepeat: {process: processBackgroundRepeat},
/**
* View
*/
+2 -2
View File
@@ -10,7 +10,7 @@
import type * as React from 'react';
import {Constructor} from '../../../types/private/Utilities';
import {ViewProps} from './ViewPropTypes';
import {HostInstance} from '../../../types/public/ReactNativeTypes';
import {NativeMethods} from '../../../types/public/ReactNativeTypes';
/**
* The most fundamental component for building UI, View is a container that supports layout with flexbox, style, some touch handling,
@@ -19,7 +19,7 @@ import {HostInstance} from '../../../types/public/ReactNativeTypes';
* whether that is a UIView, <div>, android.view, etc.
*/
declare class ViewComponent extends React.Component<ViewProps> {}
declare const ViewBase: Constructor<HostInstance> & typeof ViewComponent;
declare const ViewBase: Constructor<NativeMethods> & typeof ViewComponent;
export class View extends ViewBase {
/**
* Is 3D Touch / Force Touch available (i.e. will touch events include `force`)
@@ -21,8 +21,8 @@ const ViewNativeComponent: HostComponent<Props> =
}));
interface NativeCommands {
+focus: (viewRef: HostInstance) => void;
+blur: (viewRef: HostInstance) => void;
+focus: () => void;
+blur: () => void;
+hotspotUpdate: (viewRef: HostInstance, x: number, y: number) => void;
+setPressed: (viewRef: HostInstance, pressed: boolean) => void;
}
@@ -5,7 +5,6 @@
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @fantom_flags enableNativeCSSParsing:*
* @format
*/
@@ -230,56 +229,6 @@ describe('<View>', () => {
});
});
});
describe('background-image', () => {
it('it parses CSS and object syntax', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(
<>
<View
style={{
experimental_backgroundImage:
'radial-gradient(#e66465, #9198e5)',
}}
/>
<View
style={{
experimental_backgroundImage: [
{
type: 'radial-gradient',
shape: 'ellipse',
position: {top: '50%', right: '50%'},
size: 'farthest-corner',
colorStops: [{color: '#e66465'}, {color: '#9198e5'}],
},
],
}}
/>
</>,
);
});
const expectedProps = {
backgroundImage:
'[radial-gradient(ellipse farthest-corner at 50% 50% , rgba(230, 100, 101, 1), rgba(145, 152, 229, 1))]',
};
expect(root.getRenderedOutput().toJSON()).toEqual([
{
children: [],
props: expectedProps,
type: 'View',
},
{
children: [],
props: expectedProps,
type: 'View',
},
]);
});
});
});
describe('pointerEvents', () => {
@@ -20,9 +20,7 @@ if (NativePerformance) {
// $FlowExpectedError[cannot-write]
global.performance = {
mark: () => {},
clearMarks: () => {},
measure: () => {},
clearMeasures: () => {},
now: () => {
const performanceNow = global.nativePerformanceNow || Date.now;
return performanceNow();
@@ -332,9 +332,7 @@ class DebuggingOverlayRegistry {
instance.measure((x, y, width, height, left, top) => {
// measure can execute callback without any values provided to signal error.
if (left == null || top == null || width == null || height == null) {
reject(
new Error('Unexpectedly failed to call measure on an instance.'),
);
reject('Unexpectedly failed to call measure on an instance.');
}
resolve({
@@ -482,11 +480,7 @@ class DebuggingOverlayRegistry {
width == null ||
height == null
) {
reject(
new Error(
'Unexpectedly failed to call measure on an instance.',
),
);
reject('Unexpectedly failed to call measure on an instance.');
}
resolve({x: left, y: top, width, height});
@@ -30,11 +30,8 @@ class RCTDeviceEventEmitterImpl extends EventEmitter<RCTDeviceEventDefinitions>
...args: RCTDeviceEventDefinitions[TEvent]
): void {
beginEvent(() => `RCTDeviceEventEmitter.emit#${eventType}`);
try {
super.emit(eventType, ...args);
} finally {
endEvent();
}
super.emit(eventType, ...args);
endEvent();
}
}
const RCTDeviceEventEmitter: IEventEmitter<RCTDeviceEventDefinitions> =
@@ -26,81 +26,68 @@ class LazyIterator {
public:
LazyIterator() = default;
LazyIterator(U vector, convert_type convert, size_type i) : _v(vector), _i(i), _convert(std::move(convert)) {}
LazyIterator(U vector, convert_type convert, size_type i)
: _v(vector), _i(i), _convert(std::move(convert)) {}
bool operator==(const LazyIterator &other) const
{
bool operator==(const LazyIterator& other) const {
return _i == other._i && _v == other._v;
}
bool operator<(const LazyIterator &b) const
{
bool operator<(const LazyIterator& b) const {
return _i < b._i;
}
value_type operator*() const
{
value_type operator*() const {
return _convert(_v[_i]);
}
std::unique_ptr<value_type> operator->() const
{
std::unique_ptr<value_type> operator->() const {
return std::make_unique<value_type>(*this);
}
LazyIterator operator+(difference_type n) const
{
LazyIterator operator+(difference_type n) const {
return LazyIterator(_v, _convert, _i + n);
}
LazyIterator &operator+=(difference_type n)
{
LazyIterator& operator+=(difference_type n) {
_i += n;
return *this;
}
LazyIterator &operator-=(difference_type n)
{
LazyIterator& operator-=(difference_type n) {
_i -= n;
return *this;
}
LazyIterator operator-(difference_type n) const
{
LazyIterator operator-(difference_type n) const {
return LazyIterator(_v, _i - n);
}
difference_type operator-(const LazyIterator &a) const
{
difference_type operator-(const LazyIterator& a) const {
return _i - a._i;
}
LazyIterator &operator++()
{
LazyIterator& operator++() {
return *this += 1;
}
LazyIterator operator++(int)
{
LazyIterator operator++(int) {
auto tmp = *this;
++*this;
return tmp;
}
LazyIterator &operator--()
{
LazyIterator& operator--() {
return *this -= 1;
}
LazyIterator operator--(int)
{
LazyIterator operator--(int) {
auto tmp = *this;
--*this;
return tmp;
}
value_type operator[](difference_type n) const
{
value_type operator[](difference_type n) const {
return _convert(_v[_i + n]);
}
@@ -111,32 +98,29 @@ class LazyIterator {
};
template <typename T, typename U>
LazyIterator<T, U> operator+(typename LazyIterator<T, U>::difference_type n, const LazyIterator<T, U> &i)
{
LazyIterator<T, U> operator+(
typename LazyIterator<T, U>::difference_type n,
const LazyIterator<T, U>& i) {
return i + n;
}
template <typename T, typename U>
bool operator!=(const LazyIterator<T, U> &a, const LazyIterator<T, U> &b)
{
bool operator!=(const LazyIterator<T, U>& a, const LazyIterator<T, U>& b) {
return !(a == b);
}
template <typename T, typename U>
bool operator<=(const LazyIterator<T, U> &a, const LazyIterator<T, U> &b)
{
bool operator<=(const LazyIterator<T, U>& a, const LazyIterator<T, U>& b) {
return a < b || a == b;
}
template <typename T, typename U>
bool operator>(const LazyIterator<T, U> &a, const LazyIterator<T, U> &b)
{
bool operator>(const LazyIterator<T, U>& a, const LazyIterator<T, U>& b) {
return b < a;
}
template <typename T, typename U>
bool operator>=(const LazyIterator<T, U> &a, const LazyIterator<T, U> &b)
{
bool operator>=(const LazyIterator<T, U>& a, const LazyIterator<T, U>& b) {
return a > b || a == b;
}
@@ -31,28 +31,24 @@ class LazyVector {
using size_type = std::int32_t;
using convert_type = std::function<T(U)>;
static LazyVector<T, U> fromUnsafeRawValue(U v, size_type size, convert_type convert)
{
static LazyVector<T, U>
fromUnsafeRawValue(U v, size_type size, convert_type convert) {
return {v, size, convert};
}
U unsafeRawValue() const
{
U unsafeRawValue() const {
return _v;
}
bool empty() const
{
bool empty() const {
return _size == 0;
}
size_type size() const
{
size_type size() const {
return _size;
}
const_reference at(size_type pos) const
{
const_reference at(size_type pos) const {
#ifndef _LIBCPP_NO_EXCEPTIONS
if (!(pos < _size)) {
throw std::out_of_range("out of range");
@@ -63,47 +59,41 @@ class LazyVector {
return _convert(_v[pos]);
}
const_reference operator[](size_type pos) const
{
const_reference operator[](size_type pos) const {
assert(pos < _size);
return _convert(_v[pos]);
}
const_reference front() const
{
const_reference front() const {
assert(_size);
return (*this)[0];
}
const_reference back() const
{
const_reference back() const {
assert(_size);
return (*this)[_size - 1];
}
const_iterator begin() const
{
const_iterator begin() const {
return const_iterator(_v, _convert, 0);
}
const_iterator cbegin() const
{
const_iterator cbegin() const {
return begin();
}
const_iterator end() const
{
const_iterator end() const {
return const_iterator(_v, _convert, _size);
}
const_iterator cend() const
{
const_iterator cend() const {
return end();
}
private:
/** Wrapped vector */
LazyVector(U vector, size_type size, convert_type convert) : _v(vector), _size(size), _convert(convert) {}
LazyVector(U vector, size_type size, convert_type convert)
: _v(vector), _size(size), _convert(convert) {}
U _v;
size_type _size;
+3 -3
View File
@@ -11,7 +11,7 @@ import * as React from 'react';
import {Constructor} from '../../types/private/Utilities';
import {AccessibilityProps} from '../Components/View/ViewAccessibility';
import {Insets} from '../../types/public/Insets';
import {HostInstance} from '../../types/public/ReactNativeTypes';
import {NativeMethods} from '../../types/public/ReactNativeTypes';
import {ColorValue, StyleProp} from '../StyleSheet/StyleSheet';
import {ImageStyle, ViewStyle} from '../StyleSheet/StyleSheetTypes';
import {LayoutChangeEvent, NativeSyntheticEvent} from '../Types/CoreEventTypes';
@@ -338,7 +338,7 @@ export interface ImageSize {
}
declare class ImageComponent extends React.Component<ImageProps> {}
declare const ImageBase: Constructor<HostInstance> & typeof ImageComponent;
declare const ImageBase: Constructor<NativeMethods> & typeof ImageComponent;
export class Image extends ImageBase {
static getSize(uri: string): Promise<ImageSize>;
static getSize(
@@ -384,6 +384,6 @@ export interface ImageBackgroundProps extends ImagePropsBase {
}
declare class ImageBackgroundComponent extends React.Component<ImageBackgroundProps> {}
declare const ImageBackgroundBase: Constructor<HostInstance> &
declare const ImageBackgroundBase: Constructor<NativeMethods> &
typeof ImageBackgroundComponent;
export class ImageBackground extends ImageBackgroundBase {}
@@ -38,9 +38,11 @@ RCT_EXPORT_MODULE()
* be scaled down to `displaySize` rather than `size`.
* All units are in px (not points).
*/
RCT_EXPORT_METHOD(
cropImage : (NSURLRequest *)imageRequest cropData : (JS::NativeImageEditor::Options &)cropData successCallback : (
RCTResponseSenderBlock)successCallback errorCallback : (RCTResponseSenderBlock)errorCallback)
RCT_EXPORT_METHOD(cropImage
: (NSURLRequest *)imageRequest cropData
: (JS::NativeImageEditor::Options &)cropData successCallback
: (RCTResponseSenderBlock)successCallback errorCallback
: (RCTResponseSenderBlock)errorCallback)
{
CGRect rect = {
[RCTConvert CGPoint:@{
@@ -331,9 +331,9 @@ static RCTImageLoaderCancellationBlock RCTLoadImageURLFromLoader(
RCTImageLoaderPartialLoadBlock partialLoadHandler,
RCTImageLoaderCompletionBlockWithMetadata completionHandler)
{
if ([loadHandler
respondsToSelector:@selector
(loadImageForURL:size:scale:resizeMode:progressHandler:partialLoadHandler:completionHandlerWithMetadata:)]) {
if ([loadHandler respondsToSelector:@selector(loadImageForURL:
size:scale:resizeMode:progressHandler:partialLoadHandler
:completionHandlerWithMetadata:)]) {
return [loadHandler loadImageForURL:imageURL
size:size
scale:scale
@@ -410,17 +410,17 @@ static RCTImageLoaderCancellationBlock RCTLoadImageURLFromLoader(
completionBlock:(RCTImageLoaderCompletionBlock)completionBlock
{
RCTImageURLLoaderRequest *request = [self loadImageWithURLRequest:imageURLRequest
size:size
scale:scale
clipped:clipped
resizeMode:resizeMode
priority:priority
attribution:{}
progressBlock:progressBlock
partialLoadBlock:partialLoadBlock
completionBlock:^(NSError *error, UIImage *image, id metadata) {
completionBlock(error, image);
}];
size:size
scale:scale
clipped:clipped
resizeMode:resizeMode
priority:priority
attribution:{}
progressBlock:progressBlock
partialLoadBlock:partialLoadBlock
completionBlock:^(NSError *error, UIImage *image, id metadata) {
completionBlock(error, image);
}];
return ^{
[request cancel];
};
@@ -1229,8 +1229,10 @@ static RCTImageLoaderCancellationBlock RCTLoadImageURLFromLoader(
return std::make_shared<facebook::react::NativeImageLoaderIOSSpecJSI>(params);
}
RCT_EXPORT_METHOD(
getSize : (NSString *)uri resolve : (RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject)
RCT_EXPORT_METHOD(getSize
: (NSString *)uri resolve
: (RCTPromiseResolveBlock)resolve reject
: (RCTPromiseRejectBlock)reject)
{
NSURLRequest *request = [RCTConvert NSURLRequest:uri];
[self getImageSizeForURLRequest:request
@@ -1246,9 +1248,11 @@ RCT_EXPORT_METHOD(
}];
}
RCT_EXPORT_METHOD(
getSizeWithHeaders : (NSString *)uri headers : (NSDictionary *)headers resolve : (RCTPromiseResolveBlock)
resolve reject : (RCTPromiseRejectBlock)reject)
RCT_EXPORT_METHOD(getSizeWithHeaders
: (NSString *)uri headers
: (NSDictionary *)headers resolve
: (RCTPromiseResolveBlock)resolve reject
: (RCTPromiseRejectBlock)reject)
{
NSURL *URL = [RCTConvert NSURL:uri];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
@@ -1265,15 +1269,20 @@ RCT_EXPORT_METHOD(
}];
}
RCT_EXPORT_METHOD(
prefetchImage : (NSString *)uri resolve : (RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject)
RCT_EXPORT_METHOD(prefetchImage
: (NSString *)uri resolve
: (RCTPromiseResolveBlock)resolve reject
: (RCTPromiseRejectBlock)reject)
{
[self prefetchImageWithMetadata:uri queryRootName:nil rootTag:0 resolve:resolve reject:reject];
}
RCT_EXPORT_METHOD(
prefetchImageWithMetadata : (NSString *)uri queryRootName : (NSString *)queryRootName rootTag : (double)
rootTag resolve : (RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject)
RCT_EXPORT_METHOD(prefetchImageWithMetadata
: (NSString *)uri queryRootName
: (NSString *)queryRootName rootTag
: (double)rootTag resolve
: (RCTPromiseResolveBlock)resolve reject
: (RCTPromiseRejectBlock)reject)
{
NSURLRequest *request = [RCTConvert NSURLRequest:uri];
[self loadImageWithURLRequest:request
@@ -1297,8 +1306,10 @@ RCT_EXPORT_METHOD(
}];
}
RCT_EXPORT_METHOD(
queryCache : (NSArray *)uris resolve : (RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject)
RCT_EXPORT_METHOD(queryCache
: (NSArray *)uris resolve
: (RCTPromiseResolveBlock)resolve reject
: (RCTPromiseRejectBlock)reject)
{
resolve([self getImageCacheStatus:uris]);
}
@@ -106,9 +106,10 @@ RCT_EXPORT_METHOD(hasImageForTag : (NSString *)imageTag callback : (RCTResponseS
}
// TODO (#5906496): Name could be more explicit - something like getBase64EncodedDataForTag:?
RCT_EXPORT_METHOD(
getBase64ForTag : (NSString *)imageTag successCallback : (RCTResponseSenderBlock)
successCallback errorCallback : (RCTResponseSenderBlock)errorCallback)
RCT_EXPORT_METHOD(getBase64ForTag
: (NSString *)imageTag successCallback
: (RCTResponseSenderBlock)successCallback errorCallback
: (RCTResponseSenderBlock)errorCallback)
{
NSData *imageData = _store[imageTag];
if (imageData == nullptr) {
@@ -122,9 +123,10 @@ RCT_EXPORT_METHOD(
});
}
RCT_EXPORT_METHOD(
addImageFromBase64 : (NSString *)base64String successCallback : (RCTResponseSenderBlock)
successCallback errorCallback : (RCTResponseSenderBlock)errorCallback)
RCT_EXPORT_METHOD(addImageFromBase64
: (NSString *)base64String successCallback
: (RCTResponseSenderBlock)successCallback errorCallback
: (RCTResponseSenderBlock)errorCallback)
{
// Dispatching to a background thread to perform base64 decoding
@@ -101,11 +101,12 @@ CGRect RCTTargetRect(CGSize sourceSize, CGSize destSize, CGFloat destScale, RCTR
sourceSize.height = destSize.height;
sourceSize.width = sourceSize.height * aspect;
}
return (CGRect){{
RCTFloorValue((destSize.width - sourceSize.width) / 2, destScale),
RCTFloorValue((destSize.height - sourceSize.height) / 2, destScale),
},
RCTCeilSize(sourceSize, destScale)};
return (CGRect){
{
RCTFloorValue((destSize.width - sourceSize.width) / 2, destScale),
RCTFloorValue((destSize.height - sourceSize.height) / 2, destScale),
},
RCTCeilSize(sourceSize, destScale)};
case RCTResizeModeCover:
@@ -114,16 +115,17 @@ CGRect RCTTargetRect(CGSize sourceSize, CGSize destSize, CGFloat destScale, RCTR
sourceSize.height = destSize.height;
sourceSize.width = sourceSize.height * aspect;
destSize.width = destSize.height * targetAspect;
return (CGRect){{RCTFloorValue((destSize.width - sourceSize.width) / 2, destScale), 0},
RCTCeilSize(sourceSize, destScale)};
return (CGRect){
{RCTFloorValue((destSize.width - sourceSize.width) / 2, destScale), 0}, RCTCeilSize(sourceSize, destScale)};
} else { // target is wider than content
sourceSize.width = destSize.width;
sourceSize.height = sourceSize.width / aspect;
destSize.height = destSize.width / targetAspect;
return (CGRect){{0, RCTFloorValue((destSize.height - sourceSize.height) / 2, destScale)},
RCTCeilSize(sourceSize, destScale)};
return (CGRect){
{0, RCTFloorValue((destSize.height - sourceSize.height) / 2, destScale)},
RCTCeilSize(sourceSize, destScale)};
}
case RCTResizeModeCenter:
@@ -138,11 +140,12 @@ CGRect RCTTargetRect(CGSize sourceSize, CGSize destSize, CGFloat destScale, RCTR
sourceSize.width = sourceSize.height * aspect;
}
return (CGRect){{
RCTFloorValue((destSize.width - sourceSize.width) / 2, destScale),
RCTFloorValue((destSize.height - sourceSize.height) / 2, destScale),
},
RCTCeilSize(sourceSize, destScale)};
return (CGRect){
{
RCTFloorValue((destSize.width - sourceSize.width) / 2, destScale),
RCTFloorValue((destSize.height - sourceSize.height) / 2, destScale),
},
RCTCeilSize(sourceSize, destScale)};
}
}
@@ -290,31 +293,18 @@ UIImage *__nullable RCTDecodeImageWithData(NSData *data, CGSize destSize, CGFloa
// Calculate target size
CGSize targetSize = RCTTargetSize(sourceSize, 1, destSize, destScale, resizeMode, NO);
CGSize targetPixelSize = RCTSizeInPixels(targetSize, destScale);
CGImageRef imageRef;
BOOL createThumbnail = targetPixelSize.width != 0 && targetPixelSize.height != 0 &&
(sourceSize.width > targetPixelSize.width || sourceSize.height > targetPixelSize.height);
CGFloat maxPixelSize =
fmax(fmin(sourceSize.width, targetPixelSize.width), fmin(sourceSize.height, targetPixelSize.height));
if (createThumbnail) {
CGFloat maxPixelSize = fmax(targetPixelSize.width, targetPixelSize.height);
// Get a thumbnail of the source image. This is usually slower than creating a full-sized image,
// but takes up less memory once it's done.
imageRef = CGImageSourceCreateThumbnailAtIndex(
sourceRef, 0, (__bridge CFDictionaryRef) @{
(id)kCGImageSourceShouldAllowFloat : @YES,
(id)kCGImageSourceCreateThumbnailWithTransform : @YES,
(id)kCGImageSourceCreateThumbnailFromImageAlways : @YES,
(id)kCGImageSourceThumbnailMaxPixelSize : @(maxPixelSize),
});
} else {
// Get an image in full size. This is faster than `CGImageSourceCreateThumbnailAtIndex`
// and consumes less memory if only the target size doesn't require downscaling.
imageRef = CGImageSourceCreateImageAtIndex(
sourceRef, 0, (__bridge CFDictionaryRef) @{
(id)kCGImageSourceShouldAllowFloat : @YES,
});
}
NSDictionary<NSString *, NSNumber *> *options = @{
(id)kCGImageSourceShouldAllowFloat : @YES,
(id)kCGImageSourceCreateThumbnailWithTransform : @YES,
(id)kCGImageSourceCreateThumbnailFromImageAlways : @YES,
(id)kCGImageSourceThumbnailMaxPixelSize : @(maxPixelSize),
};
// Get thumbnail
CGImageRef imageRef = CGImageSourceCreateThumbnailAtIndex(sourceRef, 0, (__bridge CFDictionaryRef)options);
CFRelease(sourceRef);
if (!imageRef) {
return nil;
@@ -53,9 +53,10 @@ RCT_CUSTOM_VIEW_PROPERTY(tintColor, UIColor, RCTImageView)
view.renderingMode = json ? UIImageRenderingModeAlwaysTemplate : defaultView.renderingMode;
}
RCT_EXPORT_METHOD(
getSize : (NSURLRequest *)request successBlock : (RCTResponseSenderBlock)
successBlock errorBlock : (RCTResponseErrorBlock)errorBlock)
RCT_EXPORT_METHOD(getSize
: (NSURLRequest *)request successBlock
: (RCTResponseSenderBlock)successBlock errorBlock
: (RCTResponseErrorBlock)errorBlock)
{
[[self.bridge moduleForName:@"ImageLoader"
lazilyLoadIfNecessary:YES] getImageSizeForURLRequest:request
@@ -68,9 +69,10 @@ RCT_EXPORT_METHOD(
}];
}
RCT_EXPORT_METHOD(
getSizeWithHeaders : (RCTImageSource *)source resolve : (RCTPromiseResolveBlock)
resolve reject : (RCTPromiseRejectBlock)reject)
RCT_EXPORT_METHOD(getSizeWithHeaders
: (RCTImageSource *)source resolve
: (RCTPromiseResolveBlock)resolve reject
: (RCTPromiseRejectBlock)reject)
{
[[self.bridge moduleForName:@"ImageLoader" lazilyLoadIfNecessary:YES]
getImageSizeForURLRequest:source.request
@@ -83,9 +85,10 @@ RCT_EXPORT_METHOD(
}];
}
RCT_EXPORT_METHOD(
prefetchImage : (NSURLRequest *)request resolve : (RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)
reject)
RCT_EXPORT_METHOD(prefetchImage
: (NSURLRequest *)request resolve
: (RCTPromiseResolveBlock)resolve reject
: (RCTPromiseRejectBlock)reject)
{
if (!request) {
reject(@"E_INVALID_URI", @"Cannot prefetch an image for an empty URI", nil);
@@ -104,8 +107,10 @@ RCT_EXPORT_METHOD(
}];
}
RCT_EXPORT_METHOD(
queryCache : (NSArray *)requests resolve : (RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject)
RCT_EXPORT_METHOD(queryCache
: (NSArray *)requests resolve
: (RCTPromiseResolveBlock)resolve reject
: (RCTPromiseRejectBlock)reject)
{
resolve([[self.bridge moduleForName:@"ImageLoader"] getImageCacheStatus:requests]);
}
@@ -87,8 +87,10 @@ RCT_EXPORT_MODULE()
[self sendEventWithName:@"url" body:notification.userInfo];
}
RCT_EXPORT_METHOD(
openURL : (NSURL *)URL resolve : (RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject)
RCT_EXPORT_METHOD(openURL
: (NSURL *)URL resolve
: (RCTPromiseResolveBlock)resolve reject
: (RCTPromiseRejectBlock)reject)
{
[RCTSharedApplication() openURL:URL
options:@{}
@@ -112,8 +114,10 @@ RCT_EXPORT_METHOD(
}];
}
RCT_EXPORT_METHOD(
canOpenURL : (NSURL *)URL resolve : (RCTPromiseResolveBlock)resolve reject : (__unused RCTPromiseRejectBlock)reject)
RCT_EXPORT_METHOD(canOpenURL
: (NSURL *)URL resolve
: (RCTPromiseResolveBlock)resolve reject
: (__unused RCTPromiseRejectBlock)reject)
{
if (RCTRunningInAppExtension()) {
// Technically Today widgets can open urls, but supporting that would require
@@ -177,9 +181,11 @@ RCT_EXPORT_METHOD(openSettings : (RCTPromiseResolveBlock)resolve reject : (__unu
}];
}
RCT_EXPORT_METHOD(
sendIntent : (NSString *)action extras : (NSArray *_Nullable)extras resolve : (RCTPromiseResolveBlock)
resolve reject : (RCTPromiseRejectBlock)reject)
RCT_EXPORT_METHOD(sendIntent
: (NSString *)action extras
: (NSArray *_Nullable)extras resolve
: (RCTPromiseResolveBlock)resolve reject
: (RCTPromiseRejectBlock)reject)
{
RCTLogError(@"Not implemented: %@", NSStringFromSelector(_cmd));
}
+1 -4
View File
@@ -87,7 +87,7 @@ export default function Ansi({
<View style={styles.container}>
{parsedLines.map((items, i) => (
<View style={styles.line} key={i}>
<Text style={styles.text}>
<Text>
{items.map((bundle, key) => {
const textStyle =
bundle.fg && COLORS[bundle.fg]
@@ -122,7 +122,4 @@ const styles = StyleSheet.create({
line: {
flexDirection: 'row',
},
text: {
flexGrow: 1,
},
});
@@ -118,9 +118,11 @@ RCT_EXPORT_METHOD(disconnectAnimatedNodes : (double)parentTag childTag : (double
}];
}
RCT_EXPORT_METHOD(
startAnimatingNode : (double)animationId nodeTag : (double)nodeTag config : (NSDictionary<NSString *, id> *)
config endCallback : (RCTResponseSenderBlock)callBack)
RCT_EXPORT_METHOD(startAnimatingNode
: (double)animationId nodeTag
: (double)nodeTag config
: (NSDictionary<NSString *, id> *)config endCallback
: (RCTResponseSenderBlock)callBack)
{
[self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) {
[nodesManager startAnimatingNode:[NSNumber numberWithDouble:animationId]
@@ -226,9 +228,10 @@ RCT_EXPORT_METHOD(stopListeningToAnimatedNodeValue : (double)tag)
}];
}
RCT_EXPORT_METHOD(
addAnimatedEventToView : (double)viewTag eventName : (nonnull NSString *)
eventName eventMapping : (JS::NativeAnimatedModule::EventMapping &)eventMapping)
RCT_EXPORT_METHOD(addAnimatedEventToView
: (double)viewTag eventName
: (nonnull NSString *)eventName eventMapping
: (JS::NativeAnimatedModule::EventMapping &)eventMapping)
{
NSMutableDictionary *eventMappingDict = [NSMutableDictionary new];
eventMappingDict[@"nativeEventPath"] = RCTConvertVecToArray(eventMapping.nativeEventPath());
@@ -244,9 +247,10 @@ RCT_EXPORT_METHOD(
}];
}
RCT_EXPORT_METHOD(
removeAnimatedEventFromView : (double)viewTag eventName : (nonnull NSString *)eventName animatedNodeTag : (double)
animatedNodeTag)
RCT_EXPORT_METHOD(removeAnimatedEventFromView
: (double)viewTag eventName
: (nonnull NSString *)eventName animatedNodeTag
: (double)animatedNodeTag)
{
[self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) {
[nodesManager removeAnimatedEventFromView:[NSNumber numberWithDouble:viewTag]
@@ -108,9 +108,11 @@ RCT_EXPORT_METHOD(disconnectAnimatedNodes : (double)parentTag childTag : (double
}];
}
RCT_EXPORT_METHOD(
startAnimatingNode : (double)animationId nodeTag : (double)nodeTag config : (NSDictionary<NSString *, id> *)
config endCallback : (RCTResponseSenderBlock)callBack)
RCT_EXPORT_METHOD(startAnimatingNode
: (double)animationId nodeTag
: (double)nodeTag config
: (NSDictionary<NSString *, id> *)config endCallback
: (RCTResponseSenderBlock)callBack)
{
[self queueFlushedOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) {
[nodesManager startAnimatingNode:[NSNumber numberWithDouble:animationId]
@@ -202,9 +204,10 @@ RCT_EXPORT_METHOD(stopListeningToAnimatedNodeValue : (double)tag)
}];
}
RCT_EXPORT_METHOD(
addAnimatedEventToView : (double)viewTag eventName : (nonnull NSString *)
eventName eventMapping : (JS::NativeAnimatedModule::EventMapping &)eventMapping)
RCT_EXPORT_METHOD(addAnimatedEventToView
: (double)viewTag eventName
: (nonnull NSString *)eventName eventMapping
: (JS::NativeAnimatedModule::EventMapping &)eventMapping)
{
NSMutableDictionary *eventMappingDict = [NSMutableDictionary new];
eventMappingDict[@"nativeEventPath"] = RCTConvertVecToArray(eventMapping.nativeEventPath());
@@ -220,9 +223,10 @@ RCT_EXPORT_METHOD(
}];
}
RCT_EXPORT_METHOD(
removeAnimatedEventFromView : (double)viewTag eventName : (nonnull NSString *)eventName animatedNodeTag : (double)
animatedNodeTag)
RCT_EXPORT_METHOD(removeAnimatedEventFromView
: (double)viewTag eventName
: (nonnull NSString *)eventName animatedNodeTag
: (double)animatedNodeTag)
{
[self queueOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) {
[nodesManager removeAnimatedEventFromView:[NSNumber numberWithDouble:viewTag]
@@ -179,17 +179,8 @@ const validAttributesForNonEventProps = {
backgroundColor: {process: require('../StyleSheet/processColor').default},
transform: true,
transformOrigin: true,
experimental_backgroundImage: ReactNativeFeatureFlags.enableNativeCSSParsing()
? (true as const)
: {process: require('../StyleSheet/processBackgroundImage').default},
experimental_backgroundSize: {
process: require('../StyleSheet/processBackgroundSize').default,
},
experimental_backgroundPosition: {
process: require('../StyleSheet/processBackgroundPosition').default,
},
experimental_backgroundRepeat: {
process: require('../StyleSheet/processBackgroundRepeat').default,
experimental_backgroundImage: {
process: require('../StyleSheet/processBackgroundImage').default,
},
boxShadow: ReactNativeFeatureFlags.enableNativeCSSParsing()
? (true as const)
@@ -23,9 +23,7 @@ export function unstable_hasComponent(name: string): boolean {
hasNativeComponent = global.__nativeComponentRegistry__hasComponent(name);
componentNameToExists.set(name, hasNativeComponent);
} else {
throw new Error(
`unstable_hasComponent('${name}'): Global function is not registered`,
);
throw `unstable_hasComponent('${name}'): Global function is not registered`;
}
}
return hasNativeComponent;
@@ -27,7 +27,7 @@
* - Corresponds to `PerformanceResourceTiming.requestStart` (specifically,
* marking when the native request was initiated).
*/
+ (void)reportRequestStart:(NSString *)requestId
+ (void)reportRequestStart:(NSNumber *)requestId
request:(NSURLRequest *)request
encodedDataLength:(int)encodedDataLength;
@@ -40,7 +40,7 @@
* `PerformanceResourceTiming.connectStart`. Defined as "immediately before
* the browser starts to establish the connection to the server".
*/
+ (void)reportConnectionTiming:(NSString *)requestId request:(NSURLRequest *)request;
+ (void)reportConnectionTiming:(NSNumber *)requestId request:(NSURLRequest *)request;
/**
* Report when HTTP response headers have been received, corresponding to
@@ -49,7 +49,7 @@
* - Corresponds to `Network.responseReceived` in CDP.
* - Corresponds to `PerformanceResourceTiming.responseStart`.
*/
+ (void)reportResponseStart:(NSString *)requestId
+ (void)reportResponseStart:(NSNumber *)requestId
response:(NSURLResponse *)response
statusCode:(int)statusCode
headers:(NSDictionary<NSString *, NSString *> *)headers;
@@ -59,7 +59,7 @@
*
* Corresponds to `Network.dataReceived` in CDP.
*/
+ (void)reportDataReceived:(NSString *)requestId data:(NSData *)data;
+ (void)reportDataReceived:(NSNumber *)requestId data:(NSData *)data;
/**
* Report when a network request is complete and we are no longer receiving
@@ -68,20 +68,20 @@
* - Corresponds to `Network.loadingFinished` in CDP.
* - Corresponds to `PerformanceResourceTiming.responseEnd`.
*/
+ (void)reportResponseEnd:(NSString *)requestId encodedDataLength:(int)encodedDataLength;
+ (void)reportResponseEnd:(NSNumber *)requestId encodedDataLength:(int)encodedDataLength;
/**
* Report when a network request has failed.
*
* - Corresponds to `Network.loadingFailed` in CDP.
*/
+ (void)reportRequestFailed:(NSString *)requestId cancelled:(BOOL)cancelled;
+ (void)reportRequestFailed:(NSNumber *)requestId cancelled:(BOOL)cancelled;
/**
* Store response body preview. This is an optional reporting method, and is a
* no-op if CDP debugging is disabled.
*/
+ (void)maybeStoreResponseBody:(NSString *)requestId data:(NSData *)data base64Encoded:(bool)base64Encoded;
+ (void)maybeStoreResponseBody:(NSNumber *)requestId data:(NSData *)data base64Encoded:(bool)base64Encoded;
/**
* Incrementally store a response body preview, when a string response is
@@ -91,6 +91,6 @@
* As with `maybeStoreResponseBody`, calling this method is optional and a
* no-op if CDP debugging is disabled.
*/
+ (void)maybeStoreResponseBodyIncremental:(NSString *)requestId data:(NSString *)data;
+ (void)maybeStoreResponseBodyIncremental:(NSNumber *)requestId data:(NSString *)data;
@end
@@ -48,14 +48,14 @@ std::string convertRequestBodyToStringTruncated(NSURLRequest *request)
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
// Dictionary to buffer incremental response bodies (CDP debugging active only)
static const NSMutableDictionary<NSString *, NSMutableString *> *responseBuffers = nil;
static const NSMutableDictionary<NSNumber *, NSMutableString *> *responseBuffers = nil;
#endif
@implementation RCTInspectorNetworkReporter {
}
+ (void)reportRequestStart:(NSString *)requestId
+ (void)reportRequestStart:(NSNumber *)requestId
request:(NSURLRequest *)request
encodedDataLength:(int)encodedDataLength
{
@@ -68,10 +68,11 @@ static const NSMutableDictionary<NSString *, NSMutableString *> *responseBuffers
requestInfo.httpBody = convertRequestBodyToStringTruncated(request);
#endif
NetworkReporter::getInstance().reportRequestStart(requestId.UTF8String, requestInfo, encodedDataLength, std::nullopt);
NetworkReporter::getInstance().reportRequestStart(
requestId.stringValue.UTF8String, requestInfo, encodedDataLength, std::nullopt);
}
+ (void)reportConnectionTiming:(NSString *)requestId request:(NSURLRequest *)request
+ (void)reportConnectionTiming:(NSNumber *)requestId request:(NSURLRequest *)request
{
Headers headersMap;
@@ -80,10 +81,10 @@ static const NSMutableDictionary<NSString *, NSMutableString *> *responseBuffers
headersMap = convertNSDictionaryToHeaders(request.allHTTPHeaderFields);
#endif
NetworkReporter::getInstance().reportConnectionTiming(requestId.UTF8String, headersMap);
NetworkReporter::getInstance().reportConnectionTiming(requestId.stringValue.UTF8String, headersMap);
}
+ (void)reportResponseStart:(NSString *)requestId
+ (void)reportResponseStart:(NSNumber *)requestId
response:(NSURLResponse *)response
statusCode:(int)statusCode
headers:(NSDictionary<NSString *, NSString *> *)headers
@@ -98,17 +99,17 @@ static const NSMutableDictionary<NSString *, NSMutableString *> *responseBuffers
#endif
NetworkReporter::getInstance().reportResponseStart(
requestId.UTF8String, responseInfo, response.expectedContentLength);
requestId.stringValue.UTF8String, responseInfo, response.expectedContentLength);
}
+ (void)reportDataReceived:(NSString *)requestId data:(NSData *)data
+ (void)reportDataReceived:(NSNumber *)requestId data:(NSData *)data
{
NetworkReporter::getInstance().reportDataReceived(requestId.UTF8String, (int)data.length, std::nullopt);
NetworkReporter::getInstance().reportDataReceived(requestId.stringValue.UTF8String, (int)data.length, std::nullopt);
}
+ (void)reportResponseEnd:(NSString *)requestId encodedDataLength:(int)encodedDataLength
+ (void)reportResponseEnd:(NSNumber *)requestId encodedDataLength:(int)encodedDataLength
{
NetworkReporter::getInstance().reportResponseEnd(requestId.UTF8String, encodedDataLength);
NetworkReporter::getInstance().reportResponseEnd(requestId.stringValue.UTF8String, encodedDataLength);
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
// Debug build: Check for buffered response body and flush to NetworkReporter
@@ -117,7 +118,7 @@ static const NSMutableDictionary<NSString *, NSMutableString *> *responseBuffers
if (buffer != nullptr) {
if (buffer.length > 0) {
NetworkReporter::getInstance().storeResponseBody(
requestId.UTF8String, RCTStringViewFromNSString(buffer), false);
requestId.stringValue.UTF8String, RCTStringViewFromNSString(buffer), false);
}
[responseBuffers removeObjectForKey:requestId];
}
@@ -125,9 +126,9 @@ static const NSMutableDictionary<NSString *, NSMutableString *> *responseBuffers
#endif
}
+ (void)reportRequestFailed:(NSString *)requestId cancelled:(bool)cancelled
+ (void)reportRequestFailed:(NSNumber *)requestId cancelled:(bool)cancelled
{
NetworkReporter::getInstance().reportRequestFailed(requestId.UTF8String, cancelled);
NetworkReporter::getInstance().reportRequestFailed(requestId.stringValue.UTF8String, cancelled);
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
// Debug build: Clear buffer for request
@@ -137,7 +138,7 @@ static const NSMutableDictionary<NSString *, NSMutableString *> *responseBuffers
#endif
}
+ (void)maybeStoreResponseBody:(NSString *)requestId data:(id)data base64Encoded:(bool)base64Encoded
+ (void)maybeStoreResponseBody:(NSNumber *)requestId data:(id)data base64Encoded:(bool)base64Encoded
{
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
// Debug build: Process response body and report to NetworkReporter
@@ -151,7 +152,7 @@ static const NSMutableDictionary<NSString *, NSMutableString *> *responseBuffers
NSString *encodedString = [(NSData *)data base64EncodedStringWithOptions:0];
if (encodedString != nullptr) {
networkReporter.storeResponseBody(
requestId.UTF8String, RCTStringViewFromNSString(encodedString), base64Encoded);
requestId.stringValue.UTF8String, RCTStringViewFromNSString(encodedString), base64Encoded);
} else {
RCTLogWarn(@"Failed to encode response data for request %@", requestId);
}
@@ -159,12 +160,13 @@ static const NSMutableDictionary<NSString *, NSMutableString *> *responseBuffers
RCTLogWarn(@"Exception while encoding response data: %@", exception.reason);
}
} else if ([data isKindOfClass:[NSString class]] && [(NSString *)data length] > 0) {
networkReporter.storeResponseBody(requestId.UTF8String, RCTStringViewFromNSString((NSString *)data), base64Encoded);
networkReporter.storeResponseBody(
requestId.stringValue.UTF8String, RCTStringViewFromNSString((NSString *)data), base64Encoded);
}
#endif
}
+ (void)maybeStoreResponseBodyIncremental:(NSString *)requestId data:(NSString *)data
+ (void)maybeStoreResponseBodyIncremental:(NSNumber *)requestId data:(NSString *)data
{
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
// Debug build: Buffer incremental response body contents

Some files were not shown because too many files have changed in this diff Show More