mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Compare commits
128
Commits
v0.72.2
...
0.72-stable
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
75dc002a52 | ||
|
|
6304cce015 | ||
|
|
ce34674382 | ||
|
|
ab7e77c024 | ||
|
|
cedd6385b5 | ||
|
|
ccdb8b58db | ||
|
|
123cec3de5 | ||
|
|
bb8ddab2a8 | ||
|
|
524a48dce6 | ||
|
|
337dcaa54a | ||
|
|
da0f8ac060 | ||
|
|
350779af17 | ||
|
|
b5b3f3c43d | ||
|
|
e24be3072c | ||
|
|
4cee0a4c06 | ||
|
|
5c77748632 | ||
|
|
b7c2a1c88d | ||
|
|
38ad610021 | ||
|
|
48e9e62846 | ||
|
|
d724007364 | ||
|
|
33865b9899 | ||
|
|
9322b5cabf | ||
|
|
d357a61ead | ||
|
|
ee14572e24 | ||
|
|
ae4c62a933 | ||
|
|
21010037e1 | ||
|
|
9a369f4036 | ||
|
|
f3ecc0bf73 | ||
|
|
250ab8211c | ||
|
|
d5648f8e79 | ||
|
|
b418498807 | ||
|
|
dd311c9782 | ||
|
|
1d69e2fbac | ||
|
|
a316e0154e | ||
|
|
0724c2769a | ||
|
|
a215805eb7 | ||
|
|
e8e03a4240 | ||
|
|
a0142432a7 | ||
|
|
2f77e408a3 | ||
|
|
c57a29a08c | ||
|
|
a4282a91c3 | ||
|
|
5de1d4f932 | ||
|
|
c8e9836c18 | ||
|
|
6939021518 | ||
|
|
c3fda24003 | ||
|
|
ddff36f770 | ||
|
|
08fd9170fc | ||
|
|
19f3ddd5c1 | ||
|
|
1f70f58aa4 | ||
|
|
91872826f3 | ||
|
|
89ef9cb81d | ||
|
|
cb25ab9fa7 | ||
|
|
565281105e | ||
|
|
7b20c5b5e5 | ||
|
|
d62d714ada | ||
|
|
b7c1a40db4 | ||
|
|
7c7baad7bd | ||
|
|
34da08755d | ||
|
|
f63a721e89 | ||
|
|
e5e15a8115 | ||
|
|
0db45a5590 | ||
|
|
c3c6cf4646 | ||
|
|
ed5a798932 | ||
|
|
99cdaaacce | ||
|
|
e70166a3a8 | ||
|
|
df2bbba50b | ||
|
|
52904ffc42 | ||
|
|
55c2c33b46 | ||
|
|
f399afc395 | ||
|
|
a304cb43c6 | ||
|
|
5858fd768e | ||
|
|
2f08813bc7 | ||
|
|
981a0a08de | ||
|
|
e844a62ce9 | ||
|
|
3e23e14763 | ||
|
|
945c429b6a | ||
|
|
3a4d79e775 | ||
|
|
e031c05cdc | ||
|
|
4fd3da2a87 | ||
|
|
6e3a130860 | ||
|
|
9b3bd63723 | ||
|
|
785f91b67a | ||
|
|
355025dae4 | ||
|
|
3c4cc59542 | ||
|
|
1e38d4d4b1 | ||
|
|
2a041cb967 | ||
|
|
8ccdb2cbe6 | ||
|
|
a5e110adcf | ||
|
|
f6fd6b8db0 | ||
|
|
4da991407d | ||
|
|
6f02d55deb | ||
|
|
a8ec20db21 | ||
|
|
f77e9af761 | ||
|
|
e9eca07f52 | ||
|
|
66441e7e5d | ||
|
|
05d36d9860 | ||
|
|
26b49f9ff9 | ||
|
|
7aeadbc249 | ||
|
|
1794832a26 | ||
|
|
ef8ac7a329 | ||
|
|
33fc55dc6e | ||
|
|
ff27568f62 | ||
|
|
fe804b8597 | ||
|
|
c7073fd685 | ||
|
|
f3e7572a10 | ||
|
|
9f792180b5 | ||
|
|
768c9604a2 | ||
|
|
2f6c200eff | ||
|
|
40ea8ffcc7 | ||
|
|
5f503b8427 | ||
|
|
4f8c87ce0d | ||
|
|
7aa8cd55be | ||
|
|
e9ea926ba3 | ||
|
|
5b45e973f4 | ||
|
|
a601b22d14 | ||
|
|
3350dd8652 | ||
|
|
7aed30a037 | ||
|
|
e4429fa1c8 | ||
|
|
22c9739042 | ||
|
|
3cf94df45f | ||
|
|
938bd78fbb | ||
|
|
e90733776e | ||
|
|
a3cfdf0a08 | ||
|
|
03187b68e5 | ||
|
|
79c4ec1a9a | ||
|
|
ff37ddb2e2 | ||
|
|
24b682081b | ||
|
|
8f41f25c21 |
+57
-140
@@ -57,20 +57,19 @@ references:
|
||||
|
||||
cache_keys:
|
||||
checkout_cache_key: &checkout_cache_key v1-checkout
|
||||
gems_cache_key: &gems_cache_key v1-gems-{{ checksum "Gemfile.lock" }}
|
||||
gems_cache_key: &gems_cache_key v1-gems-{{ arch }}-{{ checksum "Gemfile.lock" }}
|
||||
gradle_cache_key: &gradle_cache_key v1-gradle-{{ checksum "gradle/wrapper/gradle-wrapper.properties" }}-{{ checksum "packages/react-native/ReactAndroid/gradle.properties" }}
|
||||
hermes_workspace_cache_key: &hermes_workspace_cache_key v4-hermes-{{ .Environment.CIRCLE_JOB }}-{{ checksum "/tmp/hermes/hermesversion" }}
|
||||
hermes_workspace_debug_cache_key: &hermes_workspace_debug_cache_key v2-hermes-{{ .Environment.CIRCLE_JOB }}-debug-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
|
||||
hermes_workspace_release_cache_key: &hermes_workspace_release_cache_key v2-hermes-{{ .Environment.CIRCLE_JOB }}-release-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
|
||||
hermes_workspace_debug_cache_key: &hermes_workspace_debug_cache_key v2-hermes-{{ arch }}-{{ .Environment.CIRCLE_JOB }}-debug-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}-{{ checksum "packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh" }}
|
||||
hermes_workspace_release_cache_key: &hermes_workspace_release_cache_key v2-hermes-{{ arch }}-{{ .Environment.CIRCLE_JOB }}-release-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}-{{ checksum "packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh" }}
|
||||
hermes_linux_cache_key: &hermes_linux_cache_key v1-hermes-{{ .Environment.CIRCLE_JOB }}-linux-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
|
||||
hermes_windows_cache_key: &hermes_windows_cache_key v2-hermes-{{ .Environment.CIRCLE_JOB }}-windows-{{ checksum "/Users/circleci/project/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
|
||||
hermes_tarball_debug_cache_key: &hermes_tarball_debug_cache_key v4-hermes-tarball-debug-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
|
||||
hermes_tarball_release_cache_key: &hermes_tarball_release_cache_key v3-hermes-tarball-release-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
|
||||
pods_cache_key: &pods_cache_key v8-pods-{{ .Environment.CIRCLE_JOB }}-{{ checksum "packages/rn-tester/Podfile.lock.bak" }}-{{ checksum "packages/rn-tester/Podfile" }}
|
||||
hermes_tarball_debug_cache_key: &hermes_tarball_debug_cache_key v4-hermes-tarball-debug-{{ arch }}-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
|
||||
hermes_tarball_release_cache_key: &hermes_tarball_release_cache_key v3-hermes-tarball-release-{{ arch }}-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
|
||||
pods_cache_key: &pods_cache_key v8-pods-{{ arch }}-{{ .Environment.CIRCLE_JOB }}-{{ checksum "packages/rn-tester/Podfile.lock.bak" }}-{{ checksum "packages/rn-tester/Podfile" }}
|
||||
windows_yarn_cache_key: &windows_yarn_cache_key v1-win-yarn-cache-{{ arch }}-{{ checksum "yarn.lock" }}
|
||||
windows_choco_cache_key: &windows_choco_cache_key v1-win-choco-cache-{{ .Environment.CIRCLE_JOB }}
|
||||
yarn_cache_key: &yarn_cache_key v5-yarn-cache-{{ .Environment.CIRCLE_JOB }}
|
||||
rbenv_cache_key: &rbenv_cache_key v1-rbenv-{{ checksum "/tmp/required_ruby" }}
|
||||
rbenv_cache_key: &rbenv_cache_key v1-rbenv-{{ arch }}-{{ checksum "/tmp/required_ruby" }}
|
||||
|
||||
cache_paths:
|
||||
hermes_workspace_macos_cache_paths: &hermes_workspace_macos_cache_paths
|
||||
@@ -129,9 +128,9 @@ executors:
|
||||
<<: *defaults
|
||||
macos:
|
||||
xcode: *xcode_version
|
||||
resource_class: macos.x86.medium.gen2
|
||||
resource_class: macos.m1.medium.gen1
|
||||
environment:
|
||||
- BUILD_FROM_SOURCE: true
|
||||
- RCT_BUILD_HERMES_FROM_SOURCE: true
|
||||
|
||||
# -------------------------
|
||||
# COMMANDS
|
||||
@@ -172,7 +171,7 @@ commands:
|
||||
- restore_cache:
|
||||
key: *rbenv_cache_key
|
||||
- run:
|
||||
name: Bundle Install
|
||||
name: Install the proper Ruby and run Bundle install
|
||||
command: |
|
||||
# Check if rbenv is installed. CircleCI is migrating to rbenv so we may not need to always install it.
|
||||
|
||||
@@ -202,7 +201,13 @@ commands:
|
||||
|
||||
# Set ruby dependencies
|
||||
rbenv global << parameters.ruby_version >>
|
||||
gem install bundler
|
||||
if [[ $(echo << parameters.ruby_version >> | awk -F'.' '{print $1}') == "2" ]]; then
|
||||
rbenv rehash
|
||||
gem install bundler -v 2.4.22
|
||||
else
|
||||
rbenv rehash
|
||||
gem install bundler
|
||||
fi
|
||||
bundle check || bundle install --path vendor/bundle --clean
|
||||
- save_cache:
|
||||
key: *rbenv_cache_key
|
||||
@@ -998,116 +1003,6 @@ jobs:
|
||||
-scheme RNTester \
|
||||
-sdk iphonesimulator
|
||||
|
||||
# -------------------------
|
||||
# JOBS: Windows
|
||||
# -------------------------
|
||||
test_windows:
|
||||
executor:
|
||||
name: win/default
|
||||
parameters:
|
||||
run_disabled_tests:
|
||||
type: boolean
|
||||
default: false
|
||||
environment:
|
||||
- ANDROID_HOME: "C:\\Android\\android-sdk"
|
||||
- ANDROID_NDK: "C:\\Android\\android-sdk\\ndk\\20.1.5948944"
|
||||
- ANDROID_BUILD_VERSION: 33
|
||||
- ANDROID_TOOLS_VERSION: 33.0.0
|
||||
- GRADLE_OPTS: -Dorg.gradle.daemon=false
|
||||
- CHOCO_CACHE_DIR: "C:\\ChocoCache"
|
||||
steps:
|
||||
- checkout_code_with_cache
|
||||
|
||||
- restore_cache:
|
||||
keys:
|
||||
- *windows_choco_cache_key
|
||||
|
||||
- run:
|
||||
name: Choco cache
|
||||
# Cache our dependencies which can be flakey to download
|
||||
command: |
|
||||
if (!Test-Path $env:CHOCO_CACHE_DIR) {
|
||||
mkdir $env:CHOCO_CACHE_DIR
|
||||
}
|
||||
choco config set --name cacheLocation --value $env:CHOCO_CACHE_DIR
|
||||
|
||||
- run:
|
||||
name: Disable NVM
|
||||
# Use choco to manage node versions due to https://github.com/npm/cli/issues/4234
|
||||
command: nvm off
|
||||
|
||||
- run:
|
||||
name: Install Node JS
|
||||
# Note: Version set separately for non-Windows builds, see above.
|
||||
command: choco install nodejs-lts
|
||||
|
||||
# Setup Dependencies
|
||||
- run:
|
||||
name: Enable Yarn with corepack
|
||||
command: corepack enable
|
||||
|
||||
# it looks like that, last week, envinfo released version 7.9.0 which does not works
|
||||
# with Windows. I have opened an issue here: https://github.com/tabrindle/envinfo/issues/238
|
||||
# TODO: T156811874 - Revert this to npx envinfo@latest when the issue is addressed
|
||||
- run:
|
||||
name: Display Environment info
|
||||
command: |
|
||||
npm install -g envinfo
|
||||
envinfo -v
|
||||
envinfo
|
||||
|
||||
- restore_cache:
|
||||
keys:
|
||||
- *windows_yarn_cache_key
|
||||
- run:
|
||||
name: "Yarn: Install Dependencies"
|
||||
command: yarn install --frozen-lockfile --non-interactive
|
||||
|
||||
- save_cache:
|
||||
key: *windows_yarn_cache_key
|
||||
paths:
|
||||
- C:\Users\circleci\AppData\Local\Yarn
|
||||
|
||||
- run:
|
||||
name: Install Android SDK Tools
|
||||
command: choco install android-sdk;
|
||||
|
||||
- save_cache:
|
||||
key: *windows_choco_cache_key
|
||||
paths:
|
||||
- $env:CHOCO_CACHE_DIR
|
||||
|
||||
- run:
|
||||
name: Setup Android SDKs
|
||||
command: |
|
||||
sdkmanager --licenses
|
||||
sdkmanager "system-images;android-21;google_apis;armeabi-v7a"
|
||||
sdkmanager "platforms;android-%ANDROID_BUILD_VERSION%"
|
||||
sdkmanager "build-tools;%ANDROID_TOOLS_VERSION%"
|
||||
sdkmanager "add-ons;addon-google_apis-google-23"
|
||||
sdkmanager "extras;android;m2repository"
|
||||
|
||||
# -------------------------
|
||||
# Run Tests
|
||||
- run:
|
||||
name: "Flow: Check Android"
|
||||
command: yarn flow-check-android
|
||||
- run:
|
||||
name: "Flow: Check iOS"
|
||||
command: yarn flow-check-ios
|
||||
- run:
|
||||
name: "Run Tests: JavaScript Tests"
|
||||
command: yarn test
|
||||
|
||||
# Optionally, run disabled tests
|
||||
- when:
|
||||
condition: << parameters.run_disabled_tests >>
|
||||
steps:
|
||||
- run: echo "Failing tests may be moved here temporarily."
|
||||
- run:
|
||||
name: Android Build
|
||||
command: ./gradlew.bat packages:rn-tester:android:app:assembleRelease
|
||||
|
||||
# -------------------------
|
||||
# JOBS: Coverage
|
||||
# -------------------------
|
||||
@@ -1142,14 +1037,22 @@ jobs:
|
||||
environment:
|
||||
- HERMES_WS_DIR: *hermes_workspace_root
|
||||
- HERMES_VERSION_FILE: "packages/react-native/sdks/.hermesversion"
|
||||
- BUILD_FROM_SOURCE: true
|
||||
- RCT_BUILD_HERMES_FROM_SOURCE: true
|
||||
steps:
|
||||
- run:
|
||||
name: Install dependencies
|
||||
command: |
|
||||
apt update
|
||||
apt install -y wget git curl
|
||||
curl -sL https://deb.nodesource.com/setup_16.x | bash -
|
||||
|
||||
apt-get update
|
||||
apt-get install -y ca-certificates curl gnupg
|
||||
mkdir -p /etc/apt/keyrings
|
||||
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
|
||||
NODE_MAJOR=16
|
||||
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list
|
||||
apt-get update
|
||||
|
||||
apt install -y nodejs
|
||||
npm install --global yarn
|
||||
- checkout
|
||||
@@ -1362,9 +1265,9 @@ jobs:
|
||||
name: Build HermesC for Windows
|
||||
command: |
|
||||
if (-not(Test-Path -Path $Env:HERMES_WS_DIR\win64-bin\hermesc.exe)) {
|
||||
choco install --no-progress cmake --version 3.14.7
|
||||
choco install -y --no-progress cmake --version 3.14.7
|
||||
if (-not $?) { throw "Failed to install CMake" }
|
||||
choco install --no-progress python3
|
||||
choco install -y --no-progress python3
|
||||
if (-not $?) { throw "Failed to install Python" }
|
||||
|
||||
cd $Env:HERMES_WS_DIR\icu
|
||||
@@ -1564,6 +1467,19 @@ jobs:
|
||||
-d "{\"event_type\": \"publish\", \"client_payload\": { \"version\": \"${CIRCLE_TAG:1}\" }}"
|
||||
# END: Stable releases
|
||||
|
||||
poll_maven:
|
||||
docker:
|
||||
- image: cimg/node:current
|
||||
resource_class: small
|
||||
steps:
|
||||
- checkout_code_with_cache
|
||||
- run_yarn
|
||||
- run:
|
||||
name: Poll Maven for Artifacts
|
||||
command: |
|
||||
node scripts/circleci/poll-maven.js
|
||||
|
||||
|
||||
# -------------------------
|
||||
# JOBS: Nightly
|
||||
# -------------------------
|
||||
@@ -1668,15 +1584,15 @@ workflows:
|
||||
- test_ios_template:
|
||||
requires:
|
||||
- build_npm_package
|
||||
name: "Test Template with Ruby 2.7.7"
|
||||
ruby_version: "2.7.7"
|
||||
name: "Test Template with Ruby 2.7.8"
|
||||
ruby_version: "2.7.8"
|
||||
architecture: "NewArch"
|
||||
flavor: "Debug"
|
||||
- test_ios_template:
|
||||
requires:
|
||||
- build_npm_package
|
||||
name: "Test Template with Ruby 3.2.0"
|
||||
ruby_version: "3.2.0"
|
||||
name: "Test Template with Ruby 3.2.2"
|
||||
ruby_version: "3.2.2"
|
||||
architecture: "NewArch"
|
||||
flavor: "Debug"
|
||||
- test_ios_template:
|
||||
@@ -1813,14 +1729,14 @@ workflows:
|
||||
- test_ios_rntester:
|
||||
requires:
|
||||
- build_hermes_macos
|
||||
name: "Test RNTester with Ruby 2.7.7"
|
||||
ruby_version: "2.7.7"
|
||||
name: "Test RNTester with Ruby 2.7.8"
|
||||
ruby_version: "2.7.8"
|
||||
architecture: "NewArch"
|
||||
- test_ios_rntester:
|
||||
requires:
|
||||
- build_hermes_macos
|
||||
name: "Test RNTester with Ruby 3.2.0"
|
||||
ruby_version: "3.2.0"
|
||||
name: "Test RNTester with Ruby 3.2.2"
|
||||
ruby_version: "3.2.2"
|
||||
architecture: "NewArch"
|
||||
- test_ios_rntester:
|
||||
requires:
|
||||
@@ -1830,17 +1746,17 @@ workflows:
|
||||
architecture: ["NewArch", "OldArch"]
|
||||
jsengine: ["Hermes", "JSC"]
|
||||
- test_ios:
|
||||
name: "Test iOS with Ruby 2.7.7"
|
||||
name: "Test iOS with Ruby 2.7.8"
|
||||
run_unit_tests: true
|
||||
requires:
|
||||
- build_hermes_macos
|
||||
ruby_version: "2.7.7"
|
||||
ruby_version: "2.7.8"
|
||||
- test_ios:
|
||||
name: "Test iOS with Ruby 3.2.0"
|
||||
name: "Test iOS with Ruby 3.2.2"
|
||||
run_unit_tests: true
|
||||
requires:
|
||||
- build_hermes_macos
|
||||
ruby_version: "3.2.0"
|
||||
ruby_version: "3.2.2"
|
||||
- test_ios:
|
||||
run_unit_tests: true
|
||||
requires:
|
||||
@@ -1858,8 +1774,6 @@ workflows:
|
||||
- test_js:
|
||||
name: test_js_prev_lts
|
||||
executor: nodeprevlts
|
||||
- test_windows:
|
||||
run_disabled_tests: false
|
||||
|
||||
# This workflow should only be triggered by release script
|
||||
package_release:
|
||||
@@ -1900,6 +1814,9 @@ workflows:
|
||||
- build_hermesc_linux
|
||||
- build_hermes_macos
|
||||
- build_hermesc_windows
|
||||
- poll_maven:
|
||||
requires:
|
||||
- build_and_publish_npm_package
|
||||
|
||||
package_and_publish_release_dryrun:
|
||||
when:
|
||||
|
||||
@@ -107,6 +107,8 @@ package-lock.json
|
||||
/packages/react-native/template/vendor
|
||||
.ruby-version
|
||||
/**/.ruby-version
|
||||
./vendor/
|
||||
vendor/
|
||||
|
||||
# iOS / CocoaPods
|
||||
/packages/react-native/template/ios/build/
|
||||
|
||||
@@ -4,4 +4,4 @@ source 'https://rubygems.org'
|
||||
ruby ">= 2.6.10"
|
||||
|
||||
gem 'cocoapods', '~> 1.12'
|
||||
gem 'activesupport', '>= 6.1.7.1'
|
||||
gem 'activesupport', '>= 6.1.7.3', '< 7.1.0'
|
||||
|
||||
+26
-20
@@ -1,26 +1,29 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
CFPropertyList (3.0.6)
|
||||
CFPropertyList (3.0.7)
|
||||
base64
|
||||
nkf
|
||||
rexml
|
||||
activesupport (7.0.6)
|
||||
activesupport (7.0.8.4)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
i18n (>= 1.6, < 2)
|
||||
minitest (>= 5.1)
|
||||
tzinfo (~> 2.0)
|
||||
addressable (2.8.4)
|
||||
public_suffix (>= 2.0.2, < 6.0)
|
||||
addressable (2.8.7)
|
||||
public_suffix (>= 2.0.2, < 7.0)
|
||||
algoliasearch (1.27.5)
|
||||
httpclient (~> 2.8, >= 2.8.3)
|
||||
json (>= 1.5.1)
|
||||
atomos (0.1.3)
|
||||
base64 (0.2.0)
|
||||
claide (1.1.0)
|
||||
cocoapods (1.12.1)
|
||||
cocoapods (1.15.2)
|
||||
addressable (~> 2.8)
|
||||
claide (>= 1.0.2, < 2.0)
|
||||
cocoapods-core (= 1.12.1)
|
||||
cocoapods-core (= 1.15.2)
|
||||
cocoapods-deintegrate (>= 1.0.3, < 2.0)
|
||||
cocoapods-downloader (>= 1.6.0, < 2.0)
|
||||
cocoapods-downloader (>= 2.1, < 3.0)
|
||||
cocoapods-plugins (>= 1.0.0, < 2.0)
|
||||
cocoapods-search (>= 1.0.0, < 2.0)
|
||||
cocoapods-trunk (>= 1.6.0, < 2.0)
|
||||
@@ -32,8 +35,8 @@ GEM
|
||||
molinillo (~> 0.8.0)
|
||||
nap (~> 1.0)
|
||||
ruby-macho (>= 2.3.0, < 3.0)
|
||||
xcodeproj (>= 1.21.0, < 2.0)
|
||||
cocoapods-core (1.12.1)
|
||||
xcodeproj (>= 1.23.0, < 2.0)
|
||||
cocoapods-core (1.15.2)
|
||||
activesupport (>= 5.0, < 8)
|
||||
addressable (~> 2.8)
|
||||
algoliasearch (~> 1.0)
|
||||
@@ -44,7 +47,7 @@ GEM
|
||||
public_suffix (~> 4.0)
|
||||
typhoeus (~> 1.0)
|
||||
cocoapods-deintegrate (1.0.5)
|
||||
cocoapods-downloader (1.6.3)
|
||||
cocoapods-downloader (2.1)
|
||||
cocoapods-plugins (1.0.0)
|
||||
nap
|
||||
cocoapods-search (1.0.1)
|
||||
@@ -53,43 +56,46 @@ GEM
|
||||
netrc (~> 0.11)
|
||||
cocoapods-try (1.2.0)
|
||||
colored2 (3.1.2)
|
||||
concurrent-ruby (1.2.2)
|
||||
concurrent-ruby (1.3.4)
|
||||
escape (0.0.4)
|
||||
ethon (0.16.0)
|
||||
ffi (>= 1.15.0)
|
||||
ffi (1.15.5)
|
||||
ffi (1.17.0)
|
||||
fourflusher (2.3.1)
|
||||
fuzzy_match (2.0.4)
|
||||
gh_inspector (1.1.3)
|
||||
httpclient (2.8.3)
|
||||
i18n (1.14.1)
|
||||
i18n (1.14.5)
|
||||
concurrent-ruby (~> 1.0)
|
||||
json (2.6.3)
|
||||
minitest (5.18.1)
|
||||
json (2.7.2)
|
||||
minitest (5.25.1)
|
||||
molinillo (0.8.0)
|
||||
nanaimo (0.3.0)
|
||||
nap (1.1.0)
|
||||
netrc (0.11.0)
|
||||
nkf (0.2.0)
|
||||
public_suffix (4.0.7)
|
||||
rexml (3.2.5)
|
||||
rexml (3.3.5)
|
||||
strscan
|
||||
ruby-macho (2.5.1)
|
||||
typhoeus (1.4.0)
|
||||
strscan (3.1.0)
|
||||
typhoeus (1.4.1)
|
||||
ethon (>= 0.9.0)
|
||||
tzinfo (2.0.6)
|
||||
concurrent-ruby (~> 1.0)
|
||||
xcodeproj (1.22.0)
|
||||
xcodeproj (1.25.0)
|
||||
CFPropertyList (>= 2.3.3, < 4.0)
|
||||
atomos (~> 0.1.3)
|
||||
claide (>= 1.0.2, < 2.0)
|
||||
colored2 (~> 3.1)
|
||||
nanaimo (~> 0.3.0)
|
||||
rexml (~> 3.2.4)
|
||||
rexml (>= 3.3.2, < 4.0)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
activesupport (>= 6.1.7.1)
|
||||
activesupport (>= 6.1.7.3, < 7.1.0)
|
||||
cocoapods (~> 1.12)
|
||||
|
||||
RUBY VERSION
|
||||
|
||||
@@ -39,6 +39,8 @@ nexusPublishing {
|
||||
sonatype {
|
||||
username.set(sonatypeUsername)
|
||||
password.set(sonatypePassword)
|
||||
nexusUrl.set(uri("https://ossrh-staging-api.central.sonatype.com/service/local/"))
|
||||
snapshotRepositoryUrl.set(uri("https://central.sonatype.com/repository/maven-snapshots/"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-5
@@ -40,7 +40,8 @@
|
||||
"test-ios": "./scripts/objc-test.sh test",
|
||||
"test-typescript": "dtslint packages/react-native/types",
|
||||
"test-typescript-offline": "dtslint --localTs node_modules/typescript/lib packages/react-native/types",
|
||||
"bump-all-updated-packages": "node ./scripts/monorepo/bump-all-updated-packages"
|
||||
"bump-all-updated-packages": "node ./scripts/monorepo/bump-all-updated-packages",
|
||||
"trigger-react-native-release": "node ./scripts/trigger-react-native-release.js"
|
||||
},
|
||||
"workspaces": [
|
||||
"packages/*"
|
||||
@@ -56,7 +57,7 @@
|
||||
"@definitelytyped/dtslint": "^0.0.127",
|
||||
"@jest/create-cache-key-function": "^29.2.1",
|
||||
"@reactions/component": "^2.0.2",
|
||||
"@react-native/metro-config": "^0.72.9",
|
||||
"@react-native/metro-config": "^0.72.12",
|
||||
"@types/react": "^18.0.18",
|
||||
"@typescript-eslint/parser": "^5.30.5",
|
||||
"async": "^3.2.2",
|
||||
@@ -84,9 +85,9 @@
|
||||
"jest": "^29.2.1",
|
||||
"jest-junit": "^10.0.0",
|
||||
"jscodeshift": "^0.14.0",
|
||||
"metro-babel-register": "0.76.7",
|
||||
"metro-memory-fs": "0.76.7",
|
||||
"metro-react-native-babel-transformer": "0.76.7",
|
||||
"metro-babel-register": "^0.76.9",
|
||||
"metro-memory-fs": "^0.76.9",
|
||||
"metro-react-native-babel-transformer": "^0.76.9",
|
||||
"mkdirp": "^0.5.1",
|
||||
"mock-fs": "^5.1.4",
|
||||
"prettier": "^2.4.1",
|
||||
|
||||
@@ -82,7 +82,7 @@ function getDefaultConfig(
|
||||
watchFolders: [],
|
||||
};
|
||||
|
||||
// Set global hook so that the CLI can detect when this config has been loaded
|
||||
// Set global hook, so that the CLI can detect when this config has been loaded
|
||||
global.__REACT_NATIVE_METRO_CONFIG_LOADED = true;
|
||||
|
||||
return mergeConfig(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/metro-config",
|
||||
"version": "0.72.9",
|
||||
"version": "0.72.12",
|
||||
"description": "Metro configuration for React Native.",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -11,8 +11,8 @@
|
||||
"exports": "./index.js",
|
||||
"dependencies": {
|
||||
"@react-native/js-polyfills": "^0.72.1",
|
||||
"metro-config": "0.76.7",
|
||||
"metro-react-native-babel-transformer": "0.76.7",
|
||||
"metro-runtime": "0.76.7"
|
||||
"metro-config": "^0.76.9",
|
||||
"metro-react-native-babel-transformer": "^0.76.9",
|
||||
"metro-runtime": "^0.76.9"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/codegen",
|
||||
"version": "0.72.6",
|
||||
"version": "0.72.8",
|
||||
"description": "⚛️ Code generation tools for React Native",
|
||||
"homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/react-native-codegen",
|
||||
"repository": {
|
||||
@@ -20,7 +20,10 @@
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.20.0",
|
||||
"flow-parser": "^0.206.0",
|
||||
"glob": "^7.1.1",
|
||||
"invariant": "^2.2.4",
|
||||
"jscodeshift": "^0.14.0",
|
||||
"mkdirp": "^0.5.1",
|
||||
"nullthrows": "^1.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -35,10 +38,7 @@
|
||||
"@babel/plugin-transform-flow-strip-types": "^7.20.0",
|
||||
"@babel/preset-env": "^7.20.0",
|
||||
"chalk": "^4.0.0",
|
||||
"glob": "^7.1.1",
|
||||
"invariant": "^2.2.4",
|
||||
"micromatch": "^4.0.4",
|
||||
"mkdirp": "^0.5.1",
|
||||
"prettier": "^2.4.1",
|
||||
"rimraf": "^3.0.2"
|
||||
},
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
const combine = require('./combine-js-to-schema');
|
||||
const fs = require('fs');
|
||||
const glob = require('glob');
|
||||
const path = require('path');
|
||||
const {parseArgs, filterJSFile} = require('./combine-utils');
|
||||
|
||||
const {platform, outfile, fileList} = parseArgs(process.argv);
|
||||
@@ -21,9 +22,14 @@ const {platform, outfile, fileList} = parseArgs(process.argv);
|
||||
const allFiles = [];
|
||||
fileList.forEach(file => {
|
||||
if (fs.lstatSync(file).isDirectory()) {
|
||||
const filePattern = path.sep === '\\' ? file.replace(/\\/g, '/') : file;
|
||||
const dirFiles = glob
|
||||
.sync(`${file}/**/*.{js,ts,tsx}`, {
|
||||
.sync(`${filePattern}/**/*.{js,ts,tsx}`, {
|
||||
nodir: true,
|
||||
// TODO: This will remove the need of slash substitution above for Windows,
|
||||
// but it requires glob@v9+; with the package currenlty relying on
|
||||
// glob@7.1.1; and flow-typed repo not having definitions for glob@9+.
|
||||
// windowsPathsNoEscape: true,
|
||||
})
|
||||
.filter(element => filterJSFile(element, platform));
|
||||
allFiles.push(...dirFiles);
|
||||
|
||||
@@ -562,10 +562,13 @@ function transformDataType(value: number | string): number | string {
|
||||
if (typeof value !== 'string') {
|
||||
return value;
|
||||
}
|
||||
if (/deg$/.test(value)) {
|
||||
|
||||
// Normalize degrees and radians to a number expressed in radians
|
||||
if (value.endsWith('deg')) {
|
||||
const degrees = parseFloat(value) || 0;
|
||||
const radians = (degrees * Math.PI) / 180.0;
|
||||
return radians;
|
||||
return (degrees * Math.PI) / 180.0;
|
||||
} else if (value.endsWith('rad')) {
|
||||
return parseFloat(value) || 0;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -349,4 +349,20 @@ describe('Interpolation', () => {
|
||||
expect(interpolation(1e-12)).toBe('rgba(0, 0, 0, 0)');
|
||||
expect(interpolation(2 / 3)).toBe('rgba(0, 0, 0, 0.667)');
|
||||
});
|
||||
|
||||
it.each([
|
||||
['radians', ['1rad', '2rad'], [1, 2]],
|
||||
['degrees', ['90deg', '180deg'], [Math.PI / 2, Math.PI]],
|
||||
['numbers', [1024, Math.PI], [1024, Math.PI]],
|
||||
['unknown', ['5foo', '10foo'], ['5foo', '10foo']],
|
||||
])(
|
||||
'should convert %s to numbers in the native config',
|
||||
(_, outputRange, expected) => {
|
||||
const config = new AnimatedInterpolation(
|
||||
{},
|
||||
{inputRange: [0, 1], outputRange},
|
||||
).__getNativeConfig();
|
||||
expect(config.outputRange).toEqual(expected);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
@@ -96,15 +96,19 @@ Pod::Spec.new do |s|
|
||||
s.dependency "React-utils"
|
||||
s.dependency "React-debug"
|
||||
|
||||
rel_path_from_pods_root_to_app = Pathname.new(ENV['APP_PATH']).relative_path_from(Pod::Config.instance.installation_root)
|
||||
rel_path_from_pods_to_app = Pathname.new(ENV['APP_PATH']).relative_path_from(File.join(Pod::Config.instance.installation_root, 'Pods'))
|
||||
|
||||
|
||||
s.script_phases = {
|
||||
:name => "Generate Legacy Components Interop",
|
||||
:script => "
|
||||
WITH_ENVIRONMENT=\"$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh\"
|
||||
source $WITH_ENVIRONMENT
|
||||
${NODE_BINARY} ${REACT_NATIVE_PATH}/scripts/codegen/generate-legacy-interop-components.js -p #{ENV['APP_PATH']} -o ${REACT_NATIVE_PATH}/Libraries/AppDelegate
|
||||
${NODE_BINARY} ${REACT_NATIVE_PATH}/scripts/codegen/generate-legacy-interop-components.js -p #{rel_path_from_pods_to_app} -o ${REACT_NATIVE_PATH}/Libraries/AppDelegate
|
||||
",
|
||||
:execution_position => :before_compile,
|
||||
:input_files => ["#{ENV['APP_PATH']}/react-native.config.js"],
|
||||
:input_files => ["#{rel_path_from_pods_root_to_app}/react-native.config.js"],
|
||||
:output_files => ["${REACT_NATIVE_PATH}/Libraries/AppDelegate/RCTLegacyInteropComponents.mm"],
|
||||
}
|
||||
end
|
||||
|
||||
+1
@@ -86,6 +86,7 @@ export const __INTERNAL_VIEW_CONFIG: PartialViewConfig =
|
||||
process: require('../../StyleSheet/processColor').default,
|
||||
},
|
||||
pointerEvents: true,
|
||||
isInvertedVirtualizedList: true,
|
||||
},
|
||||
}
|
||||
: {
|
||||
|
||||
+1
@@ -41,6 +41,7 @@ export type ScrollViewNativeProps = $ReadOnly<{
|
||||
endFillColor?: ?ColorValue,
|
||||
fadingEdgeLength?: ?number,
|
||||
indicatorStyle?: ?('default' | 'black' | 'white'),
|
||||
isInvertedVirtualizedList?: ?boolean,
|
||||
keyboardDismissMode?: ?('none' | 'on-drag' | 'interactive'),
|
||||
maintainVisibleContentPosition?: ?$ReadOnly<{
|
||||
minIndexForVisible: number,
|
||||
|
||||
@@ -46,6 +46,7 @@ const ScrollViewViewConfig = {
|
||||
fadingEdgeLength: true,
|
||||
indicatorStyle: true,
|
||||
inverted: true,
|
||||
isInvertedVirtualizedList: true,
|
||||
keyboardDismissMode: true,
|
||||
maintainVisibleContentPosition: true,
|
||||
maximumZoomScale: true,
|
||||
|
||||
@@ -70,6 +70,15 @@ export type ReturnKeyTypeOptions =
|
||||
| ReturnKeyTypeAndroid
|
||||
| ReturnKeyTypeIOS;
|
||||
|
||||
export type EnterKeyHintTypeAndroid = 'previous';
|
||||
export type EnterKeyHintTypeIOS = 'enter';
|
||||
export type EnterKeyHintType = 'done' | 'go' | 'next' | 'search' | 'send';
|
||||
|
||||
export type EnterKeyHintTypeOptions =
|
||||
| EnterKeyHintType
|
||||
| EnterKeyHintTypeAndroid
|
||||
| EnterKeyHintTypeIOS;
|
||||
|
||||
type DataDetectorTypes =
|
||||
| 'phoneNumber'
|
||||
| 'link'
|
||||
@@ -779,6 +788,12 @@ export interface TextInputProps
|
||||
*/
|
||||
returnKeyType?: ReturnKeyTypeOptions | undefined;
|
||||
|
||||
/**
|
||||
* Determines what text should be shown to the return key on virtual keyboards.
|
||||
* Has precedence over the returnKeyType prop.
|
||||
*/
|
||||
enterKeyHint?: EnterKeyHintTypeOptions | undefined;
|
||||
|
||||
/**
|
||||
* If true, the text input obscures the text entered so that sensitive text like passwords stay secure.
|
||||
* The default value is false.
|
||||
|
||||
@@ -223,13 +223,16 @@ export type TextContentType =
|
||||
| 'oneTimeCode';
|
||||
|
||||
export type enterKeyHintType =
|
||||
| 'enter'
|
||||
// Cross Platform
|
||||
| 'done'
|
||||
| 'go'
|
||||
| 'next'
|
||||
| 'previous'
|
||||
| 'search'
|
||||
| 'send';
|
||||
| 'send'
|
||||
// Android-only
|
||||
| 'previous'
|
||||
// iOS-only
|
||||
| 'enter';
|
||||
|
||||
type PasswordRules = string;
|
||||
|
||||
@@ -1344,6 +1347,7 @@ function InternalTextInput(props: Props): React.Node {
|
||||
|
||||
const config = React.useMemo(
|
||||
() => ({
|
||||
hitSlop: props.hitSlop,
|
||||
onPress: (event: PressEvent) => {
|
||||
if (props.editable !== false) {
|
||||
if (inputRef.current != null) {
|
||||
@@ -1358,6 +1362,7 @@ function InternalTextInput(props: Props): React.Node {
|
||||
}),
|
||||
[
|
||||
props.editable,
|
||||
props.hitSlop,
|
||||
props.onPressIn,
|
||||
props.onPressOut,
|
||||
props.rejectResponderTermination,
|
||||
|
||||
@@ -12,6 +12,6 @@
|
||||
exports.version = {
|
||||
major: 0,
|
||||
minor: 72,
|
||||
patch: 2,
|
||||
patch: 17,
|
||||
prerelease: null,
|
||||
};
|
||||
|
||||
@@ -30,6 +30,7 @@ export type LogData = $ReadOnly<{|
|
||||
message: Message,
|
||||
category: Category,
|
||||
componentStack: ComponentStack,
|
||||
stack?: string,
|
||||
|}>;
|
||||
|
||||
export type Observer = (
|
||||
@@ -198,7 +199,7 @@ export function addLog(log: LogData): void {
|
||||
// otherwise spammy logs would pause rendering.
|
||||
setImmediate(() => {
|
||||
try {
|
||||
const stack = parseErrorStack(errorForStackTrace?.stack);
|
||||
const stack = parseErrorStack(log.stack ?? errorForStackTrace?.stack);
|
||||
|
||||
appendNewLog(
|
||||
new LogBoxLog({
|
||||
|
||||
@@ -1020,6 +1020,54 @@ Please follow the instructions at: fburl.com/rn-remote-assets`,
|
||||
});
|
||||
});
|
||||
|
||||
it('detects a component stack for ts, tsx, jsx, and js files', () => {
|
||||
expect(
|
||||
parseLogBoxLog([
|
||||
'Some kind of message\n in MyTSComponent (at MyTSXComponent.ts:1)\n in MyTSXComponent (at MyTSCComponent.tsx:1)\n in MyJSXComponent (at MyJSXComponent.jsx:1)\n in MyJSComponent (at MyJSComponent.js:1)',
|
||||
]),
|
||||
).toEqual({
|
||||
componentStack: [
|
||||
{
|
||||
content: 'MyTSComponent',
|
||||
fileName: 'MyTSXComponent.ts',
|
||||
location: {
|
||||
column: -1,
|
||||
row: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
content: 'MyTSXComponent',
|
||||
fileName: 'MyTSCComponent.tsx',
|
||||
location: {
|
||||
column: -1,
|
||||
row: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
content: 'MyJSXComponent',
|
||||
fileName: 'MyJSXComponent.jsx',
|
||||
location: {
|
||||
column: -1,
|
||||
row: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
content: 'MyJSComponent',
|
||||
fileName: 'MyJSComponent.js',
|
||||
location: {
|
||||
column: -1,
|
||||
row: 1,
|
||||
},
|
||||
},
|
||||
],
|
||||
category: 'Some kind of message',
|
||||
message: {
|
||||
content: 'Some kind of message',
|
||||
substitutions: [],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('detects a component stack in the first argument (JSC)', () => {
|
||||
expect(
|
||||
parseLogBoxLog([
|
||||
|
||||
+51
-21
@@ -14,12 +14,38 @@ import type {LogBoxLogData} from './LogBoxLog';
|
||||
import parseErrorStack from '../../Core/Devtools/parseErrorStack';
|
||||
import UTFSequence from '../../UTFSequence';
|
||||
import stringifySafe from '../../Utilities/stringifySafe';
|
||||
import ansiRegex from 'ansi-regex';
|
||||
|
||||
const ANSI_REGEX = ansiRegex().source;
|
||||
|
||||
const BABEL_TRANSFORM_ERROR_FORMAT =
|
||||
/^(?:TransformError )?(?:SyntaxError: |ReferenceError: )(.*): (.*) \((\d+):(\d+)\)\n\n([\s\S]+)/;
|
||||
|
||||
// https://github.com/babel/babel/blob/33dbb85e9e9fe36915273080ecc42aee62ed0ade/packages/babel-code-frame/src/index.ts#L183-L184
|
||||
const BABEL_CODE_FRAME_MARKER_PATTERN = new RegExp(
|
||||
[
|
||||
// Beginning of a line (per 'm' flag)
|
||||
'^',
|
||||
// Optional ANSI escapes for colors
|
||||
`(?:${ANSI_REGEX})*`,
|
||||
// Marker
|
||||
'>',
|
||||
// Optional ANSI escapes for colors
|
||||
`(?:${ANSI_REGEX})*`,
|
||||
// Left padding for line number
|
||||
' +',
|
||||
// Line number
|
||||
'[0-9]+',
|
||||
// Gutter
|
||||
' \\|',
|
||||
].join(''),
|
||||
'm',
|
||||
);
|
||||
|
||||
const BABEL_CODE_FRAME_ERROR_FORMAT =
|
||||
// eslint-disable-next-line no-control-regex
|
||||
/^(?:TransformError )?(?:.*):? (?:.*?)(\/.*): ([\s\S]+?)\n([ >]{2}[\d\s]+ \|[\s\S]+|\u{001b}[\s\S]+)/u;
|
||||
|
||||
const METRO_ERROR_FORMAT =
|
||||
/^(?:InternalError Metro has encountered an error:) (.*): (.*) \((\d+):(\d+)\)\n\n([\s\S]+)/u;
|
||||
|
||||
@@ -166,7 +192,7 @@ export function parseComponentStack(message: string): ComponentStack {
|
||||
if (!s) {
|
||||
return null;
|
||||
}
|
||||
const match = s.match(/(.*) \(at (.*\.js):([\d]+)\)/);
|
||||
const match = s.match(/(.*) \(at (.*\.(?:js|jsx|ts|tsx)):([\d]+)\)/);
|
||||
if (!match) {
|
||||
return null;
|
||||
}
|
||||
@@ -241,27 +267,31 @@ export function parseLogBoxException(
|
||||
};
|
||||
}
|
||||
|
||||
const babelCodeFrameError = message.match(BABEL_CODE_FRAME_ERROR_FORMAT);
|
||||
// Perform a cheap match first before trying to parse the full message, which
|
||||
// can get expensive for arbitrary input.
|
||||
if (BABEL_CODE_FRAME_MARKER_PATTERN.test(message)) {
|
||||
const babelCodeFrameError = message.match(BABEL_CODE_FRAME_ERROR_FORMAT);
|
||||
|
||||
if (babelCodeFrameError) {
|
||||
// Codeframe errors are thrown from any use of buildCodeFrameError.
|
||||
const [fileName, content, codeFrame] = babelCodeFrameError.slice(1);
|
||||
return {
|
||||
level: 'syntax',
|
||||
stack: [],
|
||||
isComponentError: false,
|
||||
componentStack: [],
|
||||
codeFrame: {
|
||||
fileName,
|
||||
location: null, // We are not given the location.
|
||||
content: codeFrame,
|
||||
},
|
||||
message: {
|
||||
content,
|
||||
substitutions: [],
|
||||
},
|
||||
category: `${fileName}-${1}-${1}`,
|
||||
};
|
||||
if (babelCodeFrameError) {
|
||||
// Codeframe errors are thrown from any use of buildCodeFrameError.
|
||||
const [fileName, content, codeFrame] = babelCodeFrameError.slice(1);
|
||||
return {
|
||||
level: 'syntax',
|
||||
stack: [],
|
||||
isComponentError: false,
|
||||
componentStack: [],
|
||||
codeFrame: {
|
||||
fileName,
|
||||
location: null, // We are not given the location.
|
||||
content: codeFrame,
|
||||
},
|
||||
message: {
|
||||
content,
|
||||
substitutions: [],
|
||||
},
|
||||
category: `${fileName}-${1}-${1}`,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (message.match(/^TransformError /)) {
|
||||
|
||||
+32
-9
@@ -17,6 +17,8 @@ import {type EventSubscription} from '../vendor/emitter/EventEmitter';
|
||||
import {RootTagContext, createRootTag} from './RootTag';
|
||||
import * as React from 'react';
|
||||
|
||||
const reactDevToolsHook = window.__REACT_DEVTOOLS_GLOBAL_HOOK__;
|
||||
|
||||
type Props = $ReadOnly<{|
|
||||
children?: React.Node,
|
||||
fabric?: boolean,
|
||||
@@ -47,9 +49,21 @@ class AppContainer extends React.Component<Props, State> {
|
||||
};
|
||||
_mainRef: ?React.ElementRef<typeof View>;
|
||||
_subscription: ?EventSubscription = null;
|
||||
_reactDevToolsAgentListener: ?() => void = null;
|
||||
|
||||
static getDerivedStateFromError: any = undefined;
|
||||
|
||||
mountReactDevToolsOverlays(): void {
|
||||
const DevtoolsOverlay = require('../Inspector/DevtoolsOverlay').default;
|
||||
const devtoolsOverlay = <DevtoolsOverlay inspectedView={this._mainRef} />;
|
||||
|
||||
const TraceUpdateOverlay =
|
||||
require('../Components/TraceUpdateOverlay/TraceUpdateOverlay').default;
|
||||
const traceUpdateOverlay = <TraceUpdateOverlay />;
|
||||
|
||||
this.setState({devtoolsOverlay, traceUpdateOverlay});
|
||||
}
|
||||
|
||||
componentDidMount(): void {
|
||||
if (__DEV__) {
|
||||
if (!this.props.internal_excludeInspector) {
|
||||
@@ -71,16 +85,21 @@ class AppContainer extends React.Component<Props, State> {
|
||||
this.setState({inspector});
|
||||
},
|
||||
);
|
||||
if (window.__REACT_DEVTOOLS_GLOBAL_HOOK__ != null) {
|
||||
const DevtoolsOverlay =
|
||||
require('../Inspector/DevtoolsOverlay').default;
|
||||
const devtoolsOverlay = (
|
||||
<DevtoolsOverlay inspectedView={this._mainRef} />
|
||||
|
||||
if (reactDevToolsHook != null) {
|
||||
if (reactDevToolsHook.reactDevtoolsAgent) {
|
||||
// In case if this is not the first AppContainer rendered and React DevTools are already attached
|
||||
this.mountReactDevToolsOverlays();
|
||||
return;
|
||||
}
|
||||
|
||||
this._reactDevToolsAgentListener = () =>
|
||||
this.mountReactDevToolsOverlays();
|
||||
|
||||
reactDevToolsHook.on(
|
||||
'react-devtools',
|
||||
this._reactDevToolsAgentListener,
|
||||
);
|
||||
const TraceUpdateOverlay =
|
||||
require('../Components/TraceUpdateOverlay/TraceUpdateOverlay').default;
|
||||
const traceUpdateOverlay = <TraceUpdateOverlay />;
|
||||
this.setState({devtoolsOverlay, traceUpdateOverlay});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -90,6 +109,10 @@ class AppContainer extends React.Component<Props, State> {
|
||||
if (this._subscription != null) {
|
||||
this._subscription.remove();
|
||||
}
|
||||
|
||||
if (reactDevToolsHook != null && this._reactDevToolsAgentListener != null) {
|
||||
reactDevToolsHook.off('react-devtools', this._reactDevToolsAgentListener);
|
||||
}
|
||||
}
|
||||
|
||||
render(): React.Node {
|
||||
|
||||
@@ -190,6 +190,7 @@ export interface TransformsStyle {
|
||||
| SkewYTransform
|
||||
| MatrixTransform
|
||||
)[]
|
||||
| string
|
||||
| undefined;
|
||||
/**
|
||||
* @deprecated Use matrix in transform prop instead.
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
|
||||
import typeof {enable} from 'promise/setimmediate/rejection-tracking';
|
||||
|
||||
import LogBox from './LogBox/LogBox';
|
||||
|
||||
type ExtractOptionsType = <P>(((options?: ?P) => void)) => P;
|
||||
|
||||
let rejectionTrackingOptions: $Call<ExtractOptionsType, enable> = {
|
||||
@@ -34,19 +36,36 @@ let rejectionTrackingOptions: $Call<ExtractOptionsType, enable> = {
|
||||
? rejection
|
||||
: JSON.stringify((rejection: $FlowFixMe));
|
||||
}
|
||||
// It could although this object is not a standard error, it still has stack information to unwind
|
||||
// $FlowFixMe ignore types just check if stack is there
|
||||
if (rejection.stack && typeof rejection.stack === 'string') {
|
||||
stack = rejection.stack;
|
||||
}
|
||||
}
|
||||
|
||||
const warning =
|
||||
`Possible Unhandled Promise Rejection (id: ${id}):\n` +
|
||||
`${message ?? ''}\n` +
|
||||
(stack == null ? '' : stack);
|
||||
console.warn(warning);
|
||||
const warning = `Possible unhandled promise rejection (id: ${id}):\n${
|
||||
message ?? ''
|
||||
}`;
|
||||
if (__DEV__) {
|
||||
LogBox.addLog({
|
||||
level: 'warn',
|
||||
message: {
|
||||
content: warning,
|
||||
substitutions: [],
|
||||
},
|
||||
componentStack: [],
|
||||
stack,
|
||||
category: 'possible_unhandled_promise_rejection',
|
||||
});
|
||||
} else {
|
||||
console.warn(warning);
|
||||
}
|
||||
},
|
||||
onHandled: id => {
|
||||
const warning =
|
||||
`Promise Rejection Handled (id: ${id})\n` +
|
||||
`Promise rejection handled (id: ${id})\n` +
|
||||
'This means you can ignore any previous messages of the form ' +
|
||||
`"Possible Unhandled Promise Rejection (id: ${id}):"`;
|
||||
`"Possible unhandled promise rejection (id: ${id}):"`;
|
||||
console.warn(warning);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -109,7 +109,9 @@ export default class EventEmitter<TEventToArgsMap: {...}>
|
||||
Registration<$ElementType<TEventToArgsMap, TEvent>>,
|
||||
> = this._registry[eventType];
|
||||
if (registrations != null) {
|
||||
for (const registration of [...registrations]) {
|
||||
// Copy `registrations` to take a snapshot when we invoke `emit`, in case
|
||||
// registrations are added or removed when listeners are invoked.
|
||||
for (const registration of Array.from(registrations)) {
|
||||
registration.listener.apply(registration.context, args);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,6 +101,7 @@ RCT_EXTERN void RCTBundleURLProviderAllowPackagerServerAccess(BOOL allowed);
|
||||
|
||||
@property (nonatomic, assign) BOOL enableMinification;
|
||||
@property (nonatomic, assign) BOOL enableDev;
|
||||
@property (nonatomic, assign) BOOL inlineSourceMap;
|
||||
|
||||
/**
|
||||
* The scheme/protocol used of the packager, the default is the http protocol
|
||||
@@ -125,13 +126,32 @@ RCT_EXTERN void RCTBundleURLProviderAllowPackagerServerAccess(BOOL allowed);
|
||||
+ (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot
|
||||
packagerHost:(NSString *)packagerHost
|
||||
enableDev:(BOOL)enableDev
|
||||
enableMinification:(BOOL)enableMinification;
|
||||
enableMinification:(BOOL)enableMinification
|
||||
__deprecated_msg(
|
||||
"Use `jsBundleURLForBundleRoot:packagerHost:enableDev:enableMinification:inlineSourceMap:` instead");
|
||||
|
||||
+ (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot
|
||||
packagerHost:(NSString *)packagerHost
|
||||
packagerScheme:(NSString *)scheme
|
||||
enableDev:(BOOL)enableDev
|
||||
enableMinification:(BOOL)enableMinification
|
||||
modulesOnly:(BOOL)modulesOnly
|
||||
runModule:(BOOL)runModule
|
||||
__deprecated_msg(
|
||||
"Use jsBundleURLForBundleRoot:packagerHost:enableDev:enableMinification:inlineSourceMap:modulesOnly:runModule:` instead");
|
||||
|
||||
+ (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot
|
||||
packagerHost:(NSString *)packagerHost
|
||||
enableDev:(BOOL)enableDev
|
||||
enableMinification:(BOOL)enableMinification
|
||||
inlineSourceMap:(BOOL)inlineSourceMap;
|
||||
|
||||
+ (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot
|
||||
packagerHost:(NSString *)packagerHost
|
||||
packagerScheme:(NSString *)scheme
|
||||
enableDev:(BOOL)enableDev
|
||||
enableMinification:(BOOL)enableMinification
|
||||
inlineSourceMap:(BOOL)inlineSourceMap
|
||||
modulesOnly:(BOOL)modulesOnly
|
||||
runModule:(BOOL)runModule;
|
||||
/**
|
||||
@@ -142,6 +162,17 @@ RCT_EXTERN void RCTBundleURLProviderAllowPackagerServerAccess(BOOL allowed);
|
||||
+ (NSURL *)resourceURLForResourcePath:(NSString *)path
|
||||
packagerHost:(NSString *)packagerHost
|
||||
scheme:(NSString *)scheme
|
||||
query:(NSString *)query;
|
||||
query:(NSString *)query
|
||||
__deprecated_msg("Use version with queryItems parameter instead");
|
||||
|
||||
/**
|
||||
* Given a hostname for the packager and a resource path (including "/"), return the URL to the resource.
|
||||
* In general, please use the instance method to decide if the packager is running and fallback to the pre-packaged
|
||||
* resource if it is not: -resourceURLForResourceRoot:resourceName:resourceExtension:offlineBundle:
|
||||
*/
|
||||
+ (NSURL *)resourceURLForResourcePath:(NSString *)path
|
||||
packagerHost:(NSString *)packagerHost
|
||||
scheme:(NSString *)scheme
|
||||
queryItems:(NSArray<NSURLQueryItem *> *)queryItems;
|
||||
|
||||
@end
|
||||
|
||||
@@ -22,10 +22,12 @@ void RCTBundleURLProviderAllowPackagerServerAccess(BOOL allowed)
|
||||
kRCTAllowPackagerAccess = allowed;
|
||||
}
|
||||
#endif
|
||||
static NSString *const kRCTPlatformName = @"ios";
|
||||
static NSString *const kRCTPackagerSchemeKey = @"RCT_packager_scheme";
|
||||
static NSString *const kRCTJsLocationKey = @"RCT_jsLocation";
|
||||
static NSString *const kRCTEnableDevKey = @"RCT_enableDev";
|
||||
static NSString *const kRCTEnableMinificationKey = @"RCT_enableMinification";
|
||||
static NSString *const kRCTInlineSourceMapKey = @"RCT_inlineSourceMap";
|
||||
|
||||
@implementation RCTBundleURLProvider
|
||||
|
||||
@@ -187,6 +189,7 @@ static NSURL *serverRootWithHostPort(NSString *hostPort, NSString *scheme)
|
||||
packagerScheme:[self packagerScheme]
|
||||
enableDev:[self enableDev]
|
||||
enableMinification:[self enableMinification]
|
||||
inlineSourceMap:[self inlineSourceMap]
|
||||
modulesOnly:NO
|
||||
runModule:YES];
|
||||
}
|
||||
@@ -199,6 +202,7 @@ static NSURL *serverRootWithHostPort(NSString *hostPort, NSString *scheme)
|
||||
packagerScheme:[self packagerScheme]
|
||||
enableDev:[self enableDev]
|
||||
enableMinification:[self enableMinification]
|
||||
inlineSourceMap:[self inlineSourceMap]
|
||||
modulesOnly:YES
|
||||
runModule:NO];
|
||||
}
|
||||
@@ -238,13 +242,29 @@ static NSURL *serverRootWithHostPort(NSString *hostPort, NSString *scheme)
|
||||
return [[self class] resourceURLForResourcePath:path
|
||||
packagerHost:packagerServerHostPort
|
||||
scheme:packagerServerScheme
|
||||
query:nil];
|
||||
queryItems:nil];
|
||||
}
|
||||
|
||||
+ (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot
|
||||
packagerHost:(NSString *)packagerHost
|
||||
enableDev:(BOOL)enableDev
|
||||
enableMinification:(BOOL)enableMinification
|
||||
{
|
||||
return [self jsBundleURLForBundleRoot:bundleRoot
|
||||
packagerHost:packagerHost
|
||||
packagerScheme:nil
|
||||
enableDev:enableDev
|
||||
enableMinification:enableMinification
|
||||
inlineSourceMap:NO
|
||||
modulesOnly:NO
|
||||
runModule:YES];
|
||||
}
|
||||
|
||||
+ (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot
|
||||
packagerHost:(NSString *)packagerHost
|
||||
enableDev:(BOOL)enableDev
|
||||
enableMinification:(BOOL)enableMinification
|
||||
inlineSourceMap:(BOOL)inlineSourceMap
|
||||
|
||||
{
|
||||
return [self jsBundleURLForBundleRoot:bundleRoot
|
||||
@@ -252,6 +272,7 @@ static NSURL *serverRootWithHostPort(NSString *hostPort, NSString *scheme)
|
||||
packagerScheme:nil
|
||||
enableDev:enableDev
|
||||
enableMinification:enableMinification
|
||||
inlineSourceMap:inlineSourceMap
|
||||
modulesOnly:NO
|
||||
runModule:YES];
|
||||
}
|
||||
@@ -264,26 +285,44 @@ static NSURL *serverRootWithHostPort(NSString *hostPort, NSString *scheme)
|
||||
modulesOnly:(BOOL)modulesOnly
|
||||
runModule:(BOOL)runModule
|
||||
{
|
||||
NSString *path = [NSString stringWithFormat:@"/%@.bundle", bundleRoot];
|
||||
#ifdef HERMES_BYTECODE_VERSION
|
||||
NSString *runtimeBytecodeVersion = [NSString stringWithFormat:@"&runtimeBytecodeVersion=%u", HERMES_BYTECODE_VERSION];
|
||||
#else
|
||||
NSString *runtimeBytecodeVersion = @"";
|
||||
#endif
|
||||
return [self jsBundleURLForBundleRoot:bundleRoot
|
||||
packagerHost:packagerHost
|
||||
packagerScheme:nil
|
||||
enableDev:enableDev
|
||||
enableMinification:enableMinification
|
||||
inlineSourceMap:NO
|
||||
modulesOnly:modulesOnly
|
||||
runModule:runModule];
|
||||
}
|
||||
|
||||
// When we support only iOS 8 and above, use queryItems for a better API.
|
||||
NSString *query = [NSString stringWithFormat:@"platform=ios&dev=%@&minify=%@&modulesOnly=%@&runModule=%@%@",
|
||||
enableDev ? @"true" : @"false",
|
||||
enableMinification ? @"true" : @"false",
|
||||
modulesOnly ? @"true" : @"false",
|
||||
runModule ? @"true" : @"false",
|
||||
runtimeBytecodeVersion];
|
||||
+ (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot
|
||||
packagerHost:(NSString *)packagerHost
|
||||
packagerScheme:(NSString *)scheme
|
||||
enableDev:(BOOL)enableDev
|
||||
enableMinification:(BOOL)enableMinification
|
||||
inlineSourceMap:(BOOL)inlineSourceMap
|
||||
modulesOnly:(BOOL)modulesOnly
|
||||
runModule:(BOOL)runModule
|
||||
{
|
||||
NSString *path = [NSString stringWithFormat:@"/%@.bundle", bundleRoot];
|
||||
BOOL lazy = enableDev;
|
||||
NSArray<NSURLQueryItem *> *queryItems = @[
|
||||
[[NSURLQueryItem alloc] initWithName:@"platform" value:kRCTPlatformName],
|
||||
[[NSURLQueryItem alloc] initWithName:@"dev" value:enableDev ? @"true" : @"false"],
|
||||
[[NSURLQueryItem alloc] initWithName:@"minify" value:enableMinification ? @"true" : @"false"],
|
||||
[[NSURLQueryItem alloc] initWithName:@"inlineSourceMap" value:inlineSourceMap ? @"true" : @"false"],
|
||||
[[NSURLQueryItem alloc] initWithName:@"modulesOnly" value:modulesOnly ? @"true" : @"false"],
|
||||
[[NSURLQueryItem alloc] initWithName:@"runModule" value:runModule ? @"true" : @"false"],
|
||||
#ifdef HERMES_BYTECODE_VERSION
|
||||
[[NSURLQueryItem alloc] initWithName:@"runtimeBytecodeVersion" value:HERMES_BYTECODE_VERSION],
|
||||
#endif
|
||||
];
|
||||
|
||||
NSString *bundleID = [[NSBundle mainBundle] objectForInfoDictionaryKey:(NSString *)kCFBundleIdentifierKey];
|
||||
if (bundleID) {
|
||||
query = [NSString stringWithFormat:@"%@&app=%@", query, bundleID];
|
||||
queryItems = [queryItems arrayByAddingObject:[[NSURLQueryItem alloc] initWithName:@"app" value:bundleID]];
|
||||
}
|
||||
return [[self class] resourceURLForResourcePath:path packagerHost:packagerHost scheme:scheme query:query];
|
||||
return [[self class] resourceURLForResourcePath:path packagerHost:packagerHost scheme:scheme queryItems:queryItems];
|
||||
}
|
||||
|
||||
+ (NSURL *)resourceURLForResourcePath:(NSString *)path
|
||||
@@ -300,6 +339,20 @@ static NSURL *serverRootWithHostPort(NSString *hostPort, NSString *scheme)
|
||||
return components.URL;
|
||||
}
|
||||
|
||||
+ (NSURL *)resourceURLForResourcePath:(NSString *)path
|
||||
packagerHost:(NSString *)packagerHost
|
||||
scheme:(NSString *)scheme
|
||||
queryItems:(NSArray<NSURLQueryItem *> *)queryItems
|
||||
{
|
||||
NSURLComponents *components = [NSURLComponents componentsWithURL:serverRootWithHostPort(packagerHost, scheme)
|
||||
resolvingAgainstBaseURL:NO];
|
||||
components.path = path;
|
||||
if (queryItems != nil) {
|
||||
components.queryItems = queryItems;
|
||||
}
|
||||
return components.URL;
|
||||
}
|
||||
|
||||
- (void)updateValue:(id)object forKey:(NSString *)key
|
||||
{
|
||||
[[NSUserDefaults standardUserDefaults] setObject:object forKey:key];
|
||||
@@ -317,6 +370,11 @@ static NSURL *serverRootWithHostPort(NSString *hostPort, NSString *scheme)
|
||||
return [[NSUserDefaults standardUserDefaults] boolForKey:kRCTEnableMinificationKey];
|
||||
}
|
||||
|
||||
- (BOOL)inlineSourceMap
|
||||
{
|
||||
return [[NSUserDefaults standardUserDefaults] boolForKey:kRCTInlineSourceMapKey];
|
||||
}
|
||||
|
||||
- (NSString *)jsLocation
|
||||
{
|
||||
return [[NSUserDefaults standardUserDefaults] stringForKey:kRCTJsLocationKey];
|
||||
@@ -346,6 +404,11 @@ static NSURL *serverRootWithHostPort(NSString *hostPort, NSString *scheme)
|
||||
[self updateValue:@(enableMinification) forKey:kRCTEnableMinificationKey];
|
||||
}
|
||||
|
||||
- (void)setInlineSourceMap:(BOOL)inlineSourceMap
|
||||
{
|
||||
[self updateValue:@(inlineSourceMap) forKey:kRCTInlineSourceMapKey];
|
||||
}
|
||||
|
||||
- (void)setPackagerScheme:(NSString *)packagerScheme
|
||||
{
|
||||
[self updateValue:packagerScheme forKey:kRCTPackagerSchemeKey];
|
||||
|
||||
@@ -23,7 +23,7 @@ NSDictionary* RCTGetReactNativeVersion(void)
|
||||
__rnVersion = @{
|
||||
RCTVersionMajor: @(0),
|
||||
RCTVersionMinor: @(72),
|
||||
RCTVersionPatch: @(2),
|
||||
RCTVersionPatch: @(17),
|
||||
RCTVersionPrerelease: [NSNull null],
|
||||
};
|
||||
});
|
||||
|
||||
@@ -128,6 +128,11 @@ RCT_EXPORT_MODULE()
|
||||
_paused = YES;
|
||||
_timers = [NSMutableDictionary new];
|
||||
_inBackground = NO;
|
||||
RCTExecuteOnMainQueue(^{
|
||||
if (!self->_inBackground && [RCTSharedApplication() applicationState] == UIApplicationStateBackground) {
|
||||
[self appDidMoveToBackground];
|
||||
}
|
||||
});
|
||||
|
||||
for (NSString *name in @[
|
||||
UIApplicationWillResignActiveNotification,
|
||||
|
||||
@@ -243,7 +243,7 @@ task createNativeDepsDirectories {
|
||||
}
|
||||
|
||||
task downloadBoost(dependsOn: createNativeDepsDirectories, type: Download) {
|
||||
src("https://boostorg.jfrog.io/artifactory/main/release/${BOOST_VERSION.replace("_", ".")}/source/boost_${BOOST_VERSION}.tar.gz")
|
||||
src("https://archives.boost.io/release/${BOOST_VERSION.replace("_", ".")}/source/boost_${BOOST_VERSION}.tar.gz")
|
||||
onlyIfModified(true)
|
||||
overwrite(false)
|
||||
retries(5)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
VERSION_NAME=0.72.2
|
||||
VERSION_NAME=0.72.17
|
||||
GROUP=com.facebook.react
|
||||
|
||||
# JVM Versions
|
||||
|
||||
@@ -113,6 +113,7 @@ public abstract class ReactActivity extends AppCompatActivity
|
||||
@Override
|
||||
public void onRequestPermissionsResult(
|
||||
int requestCode, String[] permissions, int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
mDelegate.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
}
|
||||
|
||||
|
||||
+19
-1
@@ -20,6 +20,7 @@ import android.content.pm.PackageManager;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Typeface;
|
||||
import android.hardware.SensorManager;
|
||||
import android.os.Build;
|
||||
import android.util.Pair;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
@@ -1142,7 +1143,7 @@ public abstract class DevSupportManagerBase implements DevSupportManager {
|
||||
if (!mIsReceiverRegistered) {
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(getReloadAppAction(mApplicationContext));
|
||||
mApplicationContext.registerReceiver(mReloadAppBroadcastReceiver, filter);
|
||||
compatRegisterReceiver(mApplicationContext, mReloadAppBroadcastReceiver, filter, true);
|
||||
mIsReceiverRegistered = true;
|
||||
}
|
||||
|
||||
@@ -1258,4 +1259,21 @@ public abstract class DevSupportManagerBase implements DevSupportManager {
|
||||
|
||||
return mSurfaceDelegateFactory.createSurfaceDelegate(moduleName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starting with Android 14, apps and services that target Android 14 and use context-registered
|
||||
* receivers are required to specify a flag to indicate whether or not the receiver should be
|
||||
* exported to all other apps on the device: either RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED
|
||||
*
|
||||
* <p>https://developer.android.com/about/versions/14/behavior-changes-14#runtime-receivers-exported
|
||||
*/
|
||||
private void compatRegisterReceiver(
|
||||
Context context, BroadcastReceiver receiver, IntentFilter filter, boolean exported) {
|
||||
if (Build.VERSION.SDK_INT >= 34 && context.getApplicationInfo().targetSdkVersion >= 34) {
|
||||
context.registerReceiver(
|
||||
receiver, filter, exported ? Context.RECEIVER_EXPORTED : Context.RECEIVER_NOT_EXPORTED);
|
||||
} else {
|
||||
context.registerReceiver(receiver, filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+38
-10
@@ -53,7 +53,6 @@ import com.facebook.react.bridge.WritableMap;
|
||||
import com.facebook.react.common.build.ReactBuildConfig;
|
||||
import com.facebook.react.common.mapbuffer.ReadableMapBuffer;
|
||||
import com.facebook.react.config.ReactFeatureFlags;
|
||||
import com.facebook.react.fabric.events.EventBeatManager;
|
||||
import com.facebook.react.fabric.events.EventEmitterWrapper;
|
||||
import com.facebook.react.fabric.events.FabricEventEmitter;
|
||||
import com.facebook.react.fabric.interop.InteropEventEmitter;
|
||||
@@ -61,6 +60,7 @@ import com.facebook.react.fabric.mounting.MountItemDispatcher;
|
||||
import com.facebook.react.fabric.mounting.MountingManager;
|
||||
import com.facebook.react.fabric.mounting.SurfaceMountingManager;
|
||||
import com.facebook.react.fabric.mounting.SurfaceMountingManager.ViewEvent;
|
||||
import com.facebook.react.fabric.mounting.mountitems.DispatchCommandMountItem;
|
||||
import com.facebook.react.fabric.mounting.mountitems.DispatchIntCommandMountItem;
|
||||
import com.facebook.react.fabric.mounting.mountitems.DispatchStringCommandMountItem;
|
||||
import com.facebook.react.fabric.mounting.mountitems.IntBufferBatchMountItem;
|
||||
@@ -79,6 +79,7 @@ import com.facebook.react.uimanager.ThemedReactContext;
|
||||
import com.facebook.react.uimanager.UIManagerHelper;
|
||||
import com.facebook.react.uimanager.ViewManagerPropertyUpdater;
|
||||
import com.facebook.react.uimanager.ViewManagerRegistry;
|
||||
import com.facebook.react.uimanager.events.BatchEventDispatchedListener;
|
||||
import com.facebook.react.uimanager.events.EventCategoryDef;
|
||||
import com.facebook.react.uimanager.events.EventDispatcher;
|
||||
import com.facebook.react.uimanager.events.EventDispatcherImpl;
|
||||
@@ -168,7 +169,7 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
|
||||
@NonNull private final MountItemDispatcher mMountItemDispatcher;
|
||||
@NonNull private final ViewManagerRegistry mViewManagerRegistry;
|
||||
|
||||
@NonNull private final EventBeatManager mEventBeatManager;
|
||||
@NonNull private final BatchEventDispatchedListener mBatchEventDispatchedListener;
|
||||
|
||||
@NonNull
|
||||
private final CopyOnWriteArrayList<UIManagerListener> mListeners = new CopyOnWriteArrayList<>();
|
||||
@@ -208,16 +209,16 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
|
||||
};
|
||||
|
||||
public FabricUIManager(
|
||||
ReactApplicationContext reactContext,
|
||||
ViewManagerRegistry viewManagerRegistry,
|
||||
EventBeatManager eventBeatManager) {
|
||||
@NonNull ReactApplicationContext reactContext,
|
||||
@NonNull ViewManagerRegistry viewManagerRegistry,
|
||||
@NonNull BatchEventDispatchedListener batchEventDispatchedListener) {
|
||||
mDispatchUIFrameCallback = new DispatchUIFrameCallback(reactContext);
|
||||
mReactApplicationContext = reactContext;
|
||||
mMountingManager = new MountingManager(viewManagerRegistry, mMountItemExecutor);
|
||||
mMountItemDispatcher =
|
||||
new MountItemDispatcher(mMountingManager, new MountItemDispatchListener());
|
||||
mEventDispatcher = new EventDispatcherImpl(reactContext);
|
||||
mEventBeatManager = eventBeatManager;
|
||||
mBatchEventDispatchedListener = batchEventDispatchedListener;
|
||||
mReactApplicationContext.addLifecycleEventListener(this);
|
||||
|
||||
mViewManagerRegistry = viewManagerRegistry;
|
||||
@@ -385,7 +386,7 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
|
||||
@Override
|
||||
public void initialize() {
|
||||
mEventDispatcher.registerEventEmitter(FABRIC, new FabricEventEmitter(this));
|
||||
mEventDispatcher.addBatchEventDispatchedListener(mEventBeatManager);
|
||||
mEventDispatcher.addBatchEventDispatchedListener(mBatchEventDispatchedListener);
|
||||
if (ENABLE_FABRIC_PERF_LOGS) {
|
||||
mDevToolsReactPerfLogger = new DevToolsReactPerfLogger();
|
||||
mDevToolsReactPerfLogger.addDevToolsReactPerfLoggerListener(FABRIC_PERF_LOGGER);
|
||||
@@ -424,10 +425,11 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
|
||||
// memory immediately.
|
||||
mDispatchUIFrameCallback.stop();
|
||||
|
||||
mEventDispatcher.removeBatchEventDispatchedListener(mEventBeatManager);
|
||||
mEventDispatcher.removeBatchEventDispatchedListener(mBatchEventDispatchedListener);
|
||||
mEventDispatcher.unregisterEventEmitter(FABRIC);
|
||||
|
||||
mReactApplicationContext.unregisterComponentCallbacks(mViewManagerRegistry);
|
||||
mViewManagerRegistry.invalidate();
|
||||
|
||||
// Remove lifecycle listeners (onHostResume, onHostPause) since the FabricUIManager is going
|
||||
// away. Then stop the mDispatchUIFrameCallback false will cause the choreographer
|
||||
@@ -1039,8 +1041,16 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
|
||||
final int reactTag,
|
||||
final String commandId,
|
||||
@Nullable final ReadableArray commandArgs) {
|
||||
mMountItemDispatcher.dispatchCommandMountItem(
|
||||
new DispatchStringCommandMountItem(surfaceId, reactTag, commandId, commandArgs));
|
||||
if (ReactFeatureFlags.unstable_useFabricInterop) {
|
||||
// For Fabric Interop, we check if the commandId is an integer. If it is, we use the integer
|
||||
// overload of dispatchCommand. Otherwise, we use the string overload.
|
||||
// and the events won't be correctly dispatched.
|
||||
mMountItemDispatcher.dispatchCommandMountItem(
|
||||
createDispatchCommandMountItemForInterop(surfaceId, reactTag, commandId, commandArgs));
|
||||
} else {
|
||||
mMountItemDispatcher.dispatchCommandMountItem(
|
||||
new DispatchStringCommandMountItem(surfaceId, reactTag, commandId, commandArgs));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1200,6 +1210,24 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Util function that takes care of handling commands for Fabric Interop. If the command is a
|
||||
* string that represents a number (say "42"), it will be parsed as an integer and the
|
||||
* corresponding dispatch command mount item will be created.
|
||||
*/
|
||||
/* package */ DispatchCommandMountItem createDispatchCommandMountItemForInterop(
|
||||
final int surfaceId,
|
||||
final int reactTag,
|
||||
final String commandId,
|
||||
@Nullable final ReadableArray commandArgs) {
|
||||
try {
|
||||
int commandIdInteger = Integer.parseInt(commandId);
|
||||
return new DispatchIntCommandMountItem(surfaceId, reactTag, commandIdInteger, commandArgs);
|
||||
} catch (NumberFormatException e) {
|
||||
return new DispatchStringCommandMountItem(surfaceId, reactTag, commandId, commandArgs);
|
||||
}
|
||||
}
|
||||
|
||||
private class DispatchUIFrameCallback extends GuardedFrameCallback {
|
||||
|
||||
private volatile boolean mIsMountingEnabled = true;
|
||||
|
||||
+1
-1
@@ -17,6 +17,6 @@ public class ReactNativeVersion {
|
||||
public static final Map<String, Object> VERSION = MapBuilder.<String, Object>of(
|
||||
"major", 0,
|
||||
"minor", 72,
|
||||
"patch", 2,
|
||||
"patch", 17,
|
||||
"prerelease", null);
|
||||
}
|
||||
|
||||
+5
@@ -25,6 +25,7 @@ import com.facebook.react.modules.blob.BlobModule;
|
||||
import com.facebook.react.modules.blob.FileReaderModule;
|
||||
import com.facebook.react.modules.camera.ImageStoreManager;
|
||||
import com.facebook.react.modules.clipboard.ClipboardModule;
|
||||
import com.facebook.react.modules.devloading.DevLoadingModule;
|
||||
import com.facebook.react.modules.devtoolssettings.DevToolsSettingsManagerModule;
|
||||
import com.facebook.react.modules.dialog.DialogModule;
|
||||
import com.facebook.react.modules.fresco.FrescoModule;
|
||||
@@ -72,6 +73,7 @@ import javax.inject.Provider;
|
||||
AppearanceModule.class,
|
||||
AppStateModule.class,
|
||||
BlobModule.class,
|
||||
DevLoadingModule.class,
|
||||
FileReaderModule.class,
|
||||
ClipboardModule.class,
|
||||
DialogModule.class,
|
||||
@@ -113,6 +115,8 @@ public class MainReactPackage extends TurboReactPackage implements ViewManagerOn
|
||||
return new AppStateModule(context);
|
||||
case BlobModule.NAME:
|
||||
return new BlobModule(context);
|
||||
case DevLoadingModule.NAME:
|
||||
return new DevLoadingModule(context);
|
||||
case FileReaderModule.NAME:
|
||||
return new FileReaderModule(context);
|
||||
case ClipboardModule.NAME:
|
||||
@@ -371,6 +375,7 @@ public class MainReactPackage extends TurboReactPackage implements ViewManagerOn
|
||||
AppearanceModule.class,
|
||||
AppStateModule.class,
|
||||
BlobModule.class,
|
||||
DevLoadingModule.class,
|
||||
FileReaderModule.class,
|
||||
ClipboardModule.class,
|
||||
DialogModule.class,
|
||||
|
||||
+2
-7
@@ -175,7 +175,7 @@ public class UIImplementation {
|
||||
*
|
||||
* @return The num of root view
|
||||
*/
|
||||
private int getRootViewNum() {
|
||||
public int getRootViewNum() {
|
||||
return mOperationsQueue.getNativeViewHierarchyManager().getRootViewNum();
|
||||
}
|
||||
|
||||
@@ -608,12 +608,6 @@ public class UIImplementation {
|
||||
|
||||
/** Invoked at the end of the transaction to commit any updates to the node hierarchy. */
|
||||
public void dispatchViewUpdates(int batchId) {
|
||||
if (getRootViewNum() <= 0) {
|
||||
// If there are no RootViews registered, there will be no View updates to dispatch.
|
||||
// This is a hack to prevent this from being called when Fabric is used everywhere.
|
||||
// This should no longer be necessary in Bridgeless Mode.
|
||||
return;
|
||||
}
|
||||
SystraceMessage.beginSection(
|
||||
Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "UIImplementation.dispatchViewUpdates")
|
||||
.arg("batchId", batchId)
|
||||
@@ -792,6 +786,7 @@ public class UIImplementation {
|
||||
|
||||
public void onCatalystInstanceDestroyed() {
|
||||
mViewOperationsEnabled = false;
|
||||
mViewManagers.invalidate();
|
||||
}
|
||||
|
||||
public void setViewHierarchyUpdateDebugListener(
|
||||
|
||||
+6
-1
@@ -719,7 +719,12 @@ public class UIManagerModule extends ReactContextBaseJavaModule
|
||||
listener.willDispatchViewUpdates(this);
|
||||
}
|
||||
try {
|
||||
mUIImplementation.dispatchViewUpdates(batchId);
|
||||
// If there are no RootViews registered, there will be no View updates to dispatch.
|
||||
// This is a hack to prevent this from being called when Fabric is used everywhere.
|
||||
// This should no longer be necessary in Bridgeless Mode.
|
||||
if (mUIImplementation.getRootViewNum() > 0) {
|
||||
mUIImplementation.dispatchViewUpdates(batchId);
|
||||
}
|
||||
} finally {
|
||||
Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
|
||||
}
|
||||
|
||||
+6
-1
@@ -117,7 +117,6 @@ import java.util.Set;
|
||||
|
||||
Map viewManagerBubblingEvents = viewManager.getExportedCustomBubblingEventTypeConstants();
|
||||
if (viewManagerBubblingEvents != null) {
|
||||
|
||||
if (ReactFeatureFlags.enableFabricRenderer && ReactFeatureFlags.unstable_useFabricInterop) {
|
||||
// For Fabric, events needs to be fired with a "top" prefix.
|
||||
// For the sake of Fabric Interop, here we normalize events adding "top" in their
|
||||
@@ -133,6 +132,12 @@ import java.util.Set;
|
||||
|
||||
Map viewManagerDirectEvents = viewManager.getExportedCustomDirectEventTypeConstants();
|
||||
if (viewManagerDirectEvents != null) {
|
||||
if (ReactFeatureFlags.enableFabricRenderer && ReactFeatureFlags.unstable_useFabricInterop) {
|
||||
// For Fabric, events needs to be fired with a "top" prefix.
|
||||
// For the sake of Fabric Interop, here we normalize events adding "top" in their
|
||||
// name if the user hasn't provided it.
|
||||
normalizeEventTypes(viewManagerDirectEvents);
|
||||
}
|
||||
recursiveMerge(cumulativeDirectEventTypes, viewManagerDirectEvents);
|
||||
recursiveMerge(viewManagerDirectEvents, defaultDirectEvents);
|
||||
viewManagerConstants.put(DIRECT_EVENTS_KEY, viewManagerDirectEvents);
|
||||
|
||||
+13
@@ -10,6 +10,8 @@ package com.facebook.react.uimanager;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.facebook.common.logging.FLog;
|
||||
import com.facebook.react.common.ReactConstants;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
@@ -65,6 +67,17 @@ public class ViewGroupDrawingOrderHelper {
|
||||
* ViewGroup#getChildDrawingOrder}.
|
||||
*/
|
||||
public int getChildDrawingOrder(int childCount, int index) {
|
||||
if (mDrawingOrderIndices != null
|
||||
&& (index >= mDrawingOrderIndices.length || mDrawingOrderIndices[index] >= childCount)) {
|
||||
FLog.w(
|
||||
ReactConstants.TAG,
|
||||
"getChildDrawingOrder index out of bounds! Please check any custom view manipulations you"
|
||||
+ " may have done. childCount = %d, index = %d",
|
||||
childCount,
|
||||
index);
|
||||
update();
|
||||
}
|
||||
|
||||
if (mDrawingOrderIndices == null) {
|
||||
ArrayList<View> viewsToSort = new ArrayList<>();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
|
||||
+22
-6
@@ -103,12 +103,28 @@ public final class ViewManagerRegistry implements ComponentCallbacks2 {
|
||||
viewManagers = new ArrayList<>(mViewManagers.values());
|
||||
}
|
||||
Runnable runnable =
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (ViewManager viewManager : viewManagers) {
|
||||
viewManager.onSurfaceStopped(surfaceId);
|
||||
}
|
||||
() -> {
|
||||
for (ViewManager viewManager : viewManagers) {
|
||||
viewManager.onSurfaceStopped(surfaceId);
|
||||
}
|
||||
};
|
||||
if (UiThreadUtil.isOnUiThread()) {
|
||||
runnable.run();
|
||||
} else {
|
||||
UiThreadUtil.runOnUiThread(runnable);
|
||||
}
|
||||
}
|
||||
|
||||
/** Called on instance destroy */
|
||||
public void invalidate() {
|
||||
final List<ViewManager> viewManagers;
|
||||
synchronized (this) {
|
||||
viewManagers = new ArrayList<>(mViewManagers.values());
|
||||
}
|
||||
Runnable runnable =
|
||||
() -> {
|
||||
for (ViewManager viewManager : viewManagers) {
|
||||
viewManager.invalidate();
|
||||
}
|
||||
};
|
||||
if (UiThreadUtil.isOnUiThread()) {
|
||||
|
||||
+19
-2
@@ -204,6 +204,11 @@ import java.util.Map;
|
||||
mDefaultValue = defaultValue;
|
||||
}
|
||||
|
||||
public ColorPropSetter(ReactPropGroup prop, Method setter, int index, int defaultValue) {
|
||||
super(prop, "mixed", setter, index);
|
||||
mDefaultValue = defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getValueOrDefault(Object value, Context context) {
|
||||
if (value == null) {
|
||||
@@ -331,6 +336,10 @@ import java.util.Map;
|
||||
super(prop, "mixed", setter);
|
||||
}
|
||||
|
||||
public BoxedColorPropSetter(ReactPropGroup prop, Method setter, int index) {
|
||||
super(prop, "mixed", setter, index);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable Object getValueOrDefault(Object value, Context context) {
|
||||
if (value != null) {
|
||||
@@ -463,7 +472,11 @@ import java.util.Map;
|
||||
}
|
||||
} else if (propTypeClass == int.class) {
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
props.put(names[i], new IntPropSetter(annotation, method, i, annotation.defaultInt()));
|
||||
if ("Color".equals(annotation.customType())) {
|
||||
props.put(names[i], new ColorPropSetter(annotation, method, i, annotation.defaultInt()));
|
||||
} else {
|
||||
props.put(names[i], new IntPropSetter(annotation, method, i, annotation.defaultInt()));
|
||||
}
|
||||
}
|
||||
} else if (propTypeClass == float.class) {
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
@@ -476,7 +489,11 @@ import java.util.Map;
|
||||
}
|
||||
} else if (propTypeClass == Integer.class) {
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
props.put(names[i], new BoxedIntPropSetter(annotation, method, i));
|
||||
if ("Color".equals(annotation.customType())) {
|
||||
props.put(names[i], new BoxedColorPropSetter(annotation, method, i));
|
||||
} else {
|
||||
props.put(names[i], new BoxedIntPropSetter(annotation, method, i));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException(
|
||||
|
||||
+4
@@ -103,6 +103,10 @@ public class MaintainVisibleScrollPositionHelper<ScrollViewT extends ViewGroup &
|
||||
}
|
||||
|
||||
View firstVisibleView = mFirstVisibleView.get();
|
||||
if (firstVisibleView == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Rect newFrame = new Rect();
|
||||
firstVisibleView.getHitRect(newFrame);
|
||||
|
||||
|
||||
+6
-1
@@ -218,6 +218,12 @@ public class ReactScrollView extends ScrollView
|
||||
}
|
||||
}
|
||||
|
||||
public void abortAnimation() {
|
||||
if (mScroller != null && !mScroller.isFinished()) {
|
||||
mScroller.abortAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
public void setSnapInterval(int snapInterval) {
|
||||
mSnapInterval = snapInterval;
|
||||
}
|
||||
@@ -1076,7 +1082,6 @@ public class ReactScrollView extends ScrollView
|
||||
*/
|
||||
@Override
|
||||
public void scrollTo(int x, int y) {
|
||||
mScroller.abortAnimation();
|
||||
super.scrollTo(x, y);
|
||||
ReactScrollViewHelper.updateFabricScrollState(this);
|
||||
setPendingContentOffsets(x, y);
|
||||
|
||||
+19
@@ -213,6 +213,7 @@ public class ReactScrollViewManager extends ViewGroupManager<ReactScrollView>
|
||||
@Override
|
||||
public void scrollTo(
|
||||
ReactScrollView scrollView, ReactScrollViewCommandHelper.ScrollToCommandData data) {
|
||||
scrollView.abortAnimation();
|
||||
if (data.mAnimated) {
|
||||
scrollView.reactSmoothScrollTo(data.mDestX, data.mDestY);
|
||||
} else {
|
||||
@@ -379,4 +380,22 @@ public class ReactScrollViewManager extends ViewGroupManager<ReactScrollView>
|
||||
public void setScrollEventThrottle(ReactScrollView view, int scrollEventThrottle) {
|
||||
view.setScrollEventThrottle(scrollEventThrottle);
|
||||
}
|
||||
|
||||
@ReactProp(name = "isInvertedVirtualizedList")
|
||||
public void setIsInvertedVirtualizedList(ReactScrollView view, boolean applyFix) {
|
||||
// Usually when inverting the scroll view we are using scaleY: -1 on the list
|
||||
// and on the parent container. HOWEVER, starting from android API 33 there is
|
||||
// a bug that can cause an ANR due to that. Thus we are using different transform
|
||||
// commands to circumvent the ANR. This however causes the vertical scrollbar to
|
||||
// be on the wrong side. Thus we are moving it to the other side, when the list
|
||||
// is inverted.
|
||||
// See also:
|
||||
// - https://github.com/facebook/react-native/issues/35350
|
||||
// - https://issuetracker.google.com/issues/287304310
|
||||
if (applyFix) {
|
||||
view.setVerticalScrollbarPosition(View.SCROLLBAR_POSITION_LEFT);
|
||||
} else {
|
||||
view.setVerticalScrollbarPosition(View.SCROLLBAR_POSITION_DEFAULT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+65
@@ -10,6 +10,8 @@ package com.facebook.react.views.textinput;
|
||||
import static com.facebook.react.uimanager.UIManagerHelper.getReactContext;
|
||||
import static com.facebook.react.views.text.TextAttributeProps.UNSET;
|
||||
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
@@ -28,8 +30,11 @@ import android.text.TextWatcher;
|
||||
import android.text.method.KeyListener;
|
||||
import android.text.method.QwertyKeyListener;
|
||||
import android.util.TypedValue;
|
||||
import android.view.ActionMode;
|
||||
import android.view.Gravity;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
@@ -180,6 +185,35 @@ public class ReactEditText extends AppCompatEditText
|
||||
}
|
||||
};
|
||||
ViewCompat.setAccessibilityDelegate(this, editTextAccessibilityDelegate);
|
||||
ActionMode.Callback customActionModeCallback =
|
||||
new ActionMode.Callback() {
|
||||
/*
|
||||
* Editor onCreateActionMode adds the cut, copy, paste, share, autofill,
|
||||
* and paste as plain text items to the context menu.
|
||||
*/
|
||||
@Override
|
||||
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
|
||||
menu.removeItem(android.R.id.pasteAsPlainText);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyActionMode(ActionMode mode) {}
|
||||
};
|
||||
setCustomSelectionActionModeCallback(customActionModeCallback);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
setCustomInsertionActionModeCallback(customActionModeCallback);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -268,6 +302,37 @@ public class ReactEditText extends AppCompatEditText
|
||||
return inputConnection;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when a context menu option for the text view is selected.
|
||||
* React Native replaces copy (as rich text) with copy as plain text.
|
||||
*/
|
||||
@Override
|
||||
public boolean onTextContextMenuItem(int id) {
|
||||
if (id == android.R.id.paste) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
id = android.R.id.pasteAsPlainText;
|
||||
} else {
|
||||
ClipboardManager clipboard =
|
||||
(ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
ClipData previousClipData = clipboard.getPrimaryClip();
|
||||
if (previousClipData != null) {
|
||||
for (int i = 0; i < previousClipData.getItemCount(); i++) {
|
||||
final CharSequence text = previousClipData.getItemAt(i).coerceToText(getContext());
|
||||
final CharSequence paste = (text instanceof Spanned) ? text.toString() : text;
|
||||
if (paste != null) {
|
||||
ClipData clipData = ClipData.newPlainText(null, text);
|
||||
clipboard.setPrimaryClip(clipData);
|
||||
}
|
||||
}
|
||||
boolean actionPerformed = super.onTextContextMenuItem(id);
|
||||
clipboard.setPrimaryClip(previousClipData);
|
||||
return actionPerformed;
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.onTextContextMenuItem(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearFocus() {
|
||||
setFocusableInTouchMode(false);
|
||||
|
||||
+54
-21
@@ -420,10 +420,10 @@ public class ReactViewGroup extends ViewGroup
|
||||
if (!intersects && child.getParent() != null && !isAnimating) {
|
||||
// We can try saving on invalidate call here as the view that we remove is out of visible area
|
||||
// therefore invalidation is not necessary.
|
||||
super.removeViewsInLayout(idx - clippedSoFar, 1);
|
||||
removeViewsInLayout(idx - clippedSoFar, 1);
|
||||
needUpdateClippingRecursive = true;
|
||||
} else if (intersects && child.getParent() == null) {
|
||||
super.addViewInLayout(child, idx - clippedSoFar, sDefaultLayoutParam, true);
|
||||
addViewInLayout(child, idx - clippedSoFar, sDefaultLayoutParam, true);
|
||||
invalidate();
|
||||
needUpdateClippingRecursive = true;
|
||||
} else if (intersects) {
|
||||
@@ -501,23 +501,18 @@ public class ReactViewGroup extends ViewGroup
|
||||
return ViewUtil.getUIManagerType(getId()) == UIManagerType.FABRIC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addView(View child, int index, ViewGroup.LayoutParams params) {
|
||||
// This will get called for every overload of addView so there is not need to override every
|
||||
// method.
|
||||
private void handleAddView(View view) {
|
||||
UiThreadUtil.assertOnUiThread();
|
||||
|
||||
if (!customDrawOrderDisabled()) {
|
||||
getDrawingOrderHelper().handleAddView(child);
|
||||
getDrawingOrderHelper().handleAddView(view);
|
||||
setChildrenDrawingOrderEnabled(getDrawingOrderHelper().shouldEnableCustomDrawingOrder());
|
||||
} else {
|
||||
setChildrenDrawingOrderEnabled(false);
|
||||
}
|
||||
|
||||
super.addView(child, index, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeView(View view) {
|
||||
private void handleRemoveView(View view) {
|
||||
UiThreadUtil.assertOnUiThread();
|
||||
|
||||
if (!customDrawOrderDisabled()) {
|
||||
@@ -526,24 +521,62 @@ public class ReactViewGroup extends ViewGroup
|
||||
} else {
|
||||
setChildrenDrawingOrderEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleRemoveViews(int start, int count) {
|
||||
int endIndex = start + count;
|
||||
for (int index = start; index < endIndex; index++) {
|
||||
if (index < getChildCount()) {
|
||||
handleRemoveView(getChildAt(index));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addView(View child, int index, ViewGroup.LayoutParams params) {
|
||||
// This will get called for every overload of addView so there is not need to override every
|
||||
// method.
|
||||
handleAddView(child);
|
||||
super.addView(child, index, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean addViewInLayout(
|
||||
View child, int index, LayoutParams params, boolean preventRequestLayout) {
|
||||
handleAddView(child);
|
||||
return super.addViewInLayout(child, index, params, preventRequestLayout);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeView(View view) {
|
||||
handleRemoveView(view);
|
||||
super.removeView(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeViewAt(int index) {
|
||||
UiThreadUtil.assertOnUiThread();
|
||||
|
||||
if (!customDrawOrderDisabled()) {
|
||||
getDrawingOrderHelper().handleRemoveView(getChildAt(index));
|
||||
setChildrenDrawingOrderEnabled(getDrawingOrderHelper().shouldEnableCustomDrawingOrder());
|
||||
} else {
|
||||
setChildrenDrawingOrderEnabled(false);
|
||||
}
|
||||
|
||||
handleRemoveView(getChildAt(index));
|
||||
super.removeViewAt(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeViewInLayout(View view) {
|
||||
handleRemoveView(view);
|
||||
super.removeViewInLayout(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeViewsInLayout(int start, int count) {
|
||||
handleRemoveViews(start, count);
|
||||
super.removeViewsInLayout(start, count);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeViews(int start, int count) {
|
||||
handleRemoveViews(start, count);
|
||||
super.removeViews(start, count);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getChildDrawingOrder(int childCount, int index) {
|
||||
UiThreadUtil.assertOnUiThread();
|
||||
@@ -665,7 +698,7 @@ public class ReactViewGroup extends ViewGroup
|
||||
clippedSoFar++;
|
||||
}
|
||||
}
|
||||
super.removeViewsInLayout(index - clippedSoFar, 1);
|
||||
removeViewsInLayout(index - clippedSoFar, 1);
|
||||
}
|
||||
removeFromArray(index);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,11 @@ set(CMAKE_VERBOSE_MAKEFILE on)
|
||||
|
||||
project(ReactAndroid)
|
||||
|
||||
# Convert input paths to CMake format (with forward slashes)
|
||||
file(TO_CMAKE_PATH "${REACT_ANDROID_DIR}" REACT_ANDROID_DIR)
|
||||
file(TO_CMAKE_PATH "${REACT_BUILD_DIR}" REACT_BUILD_DIR)
|
||||
file(TO_CMAKE_PATH "${REACT_COMMON_DIR}" REACT_COMMON_DIR)
|
||||
|
||||
# If you have ccache installed, we're going to honor it.
|
||||
find_program(CCACHE_FOUND ccache)
|
||||
if(CCACHE_FOUND)
|
||||
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.facebook.react.fabric
|
||||
|
||||
import com.facebook.react.bridge.ReactApplicationContext
|
||||
import com.facebook.react.uimanager.ViewManagerRegistry
|
||||
import com.facebook.react.uimanager.events.BatchEventDispatchedListener
|
||||
import com.facebook.testutils.fakes.FakeBatchEventDispatchedListener
|
||||
import com.facebook.testutils.shadows.ShadowSoLoader
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.robolectric.RuntimeEnvironment
|
||||
import org.robolectric.annotation.Config
|
||||
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
@Config(shadows = [ShadowSoLoader::class])
|
||||
class FabricUIManagerTest {
|
||||
|
||||
private lateinit var reactContext: ReactApplicationContext
|
||||
private lateinit var viewManagerRegistry: ViewManagerRegistry
|
||||
private lateinit var batchEventDispatchedListener: BatchEventDispatchedListener
|
||||
private lateinit var underTest: FabricUIManager
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
reactContext = ReactApplicationContext(RuntimeEnvironment.getApplication())
|
||||
viewManagerRegistry = ViewManagerRegistry(emptyList())
|
||||
batchEventDispatchedListener = FakeBatchEventDispatchedListener()
|
||||
underTest = FabricUIManager(reactContext, viewManagerRegistry, batchEventDispatchedListener)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun createDispatchCommandMountItemForInterop_withValidString_returnsStringEvent() {
|
||||
val command = underTest.createDispatchCommandMountItemForInterop(11, 1, "anEvent", null)
|
||||
|
||||
// DispatchStringCommandMountItem is package private so we can `as` check it.
|
||||
val className = command::class.java.name.substringAfterLast(".")
|
||||
assertEquals("DispatchStringCommandMountItem", className)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun createDispatchCommandMountItemForInterop_withValidInt_returnsIntEvent() {
|
||||
val command = underTest.createDispatchCommandMountItemForInterop(11, 1, "42", null)
|
||||
|
||||
// DispatchIntCommandMountItem is package private so we can `as` check it.
|
||||
val className = command::class.java.name.substringAfterLast(".")
|
||||
assertEquals("DispatchIntCommandMountItem", className)
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.facebook.testutils.fakes
|
||||
|
||||
import com.facebook.react.uimanager.events.BatchEventDispatchedListener
|
||||
|
||||
/** A fake [BatchEventDispatchedListener] for testing that does nothing. */
|
||||
class FakeBatchEventDispatchedListener : BatchEventDispatchedListener {
|
||||
override fun onBatchEventDispatched() {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.facebook.testutils.shadows
|
||||
|
||||
import android.content.Context
|
||||
import com.facebook.soloader.SoLoader
|
||||
import kotlin.jvm.JvmStatic
|
||||
import org.robolectric.annotation.Implementation
|
||||
import org.robolectric.annotation.Implements
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
@Implements(SoLoader::class)
|
||||
class ShadowSoLoader {
|
||||
companion object {
|
||||
@JvmStatic @Implementation fun init(context: Context?, flags: Int) {}
|
||||
|
||||
@JvmStatic @Implementation fun loadLibrary(shortName: String?): Boolean = true
|
||||
}
|
||||
}
|
||||
@@ -37,7 +37,7 @@ Pod::Spec.new do |s|
|
||||
"DEFINES_MODULE" => "YES" }
|
||||
|
||||
if ENV['USE_FRAMEWORKS']
|
||||
s.header_mappings_dir = File.absolute_path('./')
|
||||
s.header_mappings_dir = './'
|
||||
s.module_name = 'React_Fabric'
|
||||
end
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ Pod::Spec.new do |s|
|
||||
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17",
|
||||
"GCC_WARN_PEDANTIC" => "YES" }
|
||||
if ENV['USE_FRAMEWORKS']
|
||||
s.header_mappings_dir = File.absolute_path("./")
|
||||
s.header_mappings_dir = './'
|
||||
end
|
||||
|
||||
# TODO (T48588859): Restructure this target to align with dir structure: "react/nativemodule/..."
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace facebook::react {
|
||||
constexpr struct {
|
||||
int32_t Major = 0;
|
||||
int32_t Minor = 72;
|
||||
int32_t Patch = 2;
|
||||
int32_t Patch = 17;
|
||||
std::string_view Prerelease = "";
|
||||
} ReactNativeVersion;
|
||||
|
||||
|
||||
@@ -302,6 +302,9 @@ class JSCRuntime : public jsi::Runtime {
|
||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_10_0
|
||||
#define _JSC_NO_ARRAY_BUFFERS
|
||||
#endif
|
||||
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 160400
|
||||
#define _JSC_HAS_INSPECTABLE
|
||||
#endif
|
||||
#endif
|
||||
#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
|
||||
#if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_11
|
||||
@@ -398,6 +401,15 @@ JSCRuntime::JSCRuntime(JSGlobalContextRef ctx)
|
||||
stringCounter_(0)
|
||||
#endif
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
#ifdef _JSC_HAS_INSPECTABLE
|
||||
#if (__OSX_AVAILABLE_STARTING(MAC_NA, IPHONE_16_4))
|
||||
if (__builtin_available(macOS 13.3, iOS 16.4, tvOS 16.4, *)) {
|
||||
JSGlobalContextSetInspectable(ctx_, true);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
JSCRuntime::~JSCRuntime() {
|
||||
|
||||
@@ -36,8 +36,7 @@ Pod::Spec.new do |s|
|
||||
|
||||
s.header_dir = "jsi"
|
||||
s.compiler_flags = folly_compiler_flags + ' ' + boost_compiler_flags
|
||||
s.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/RCT-Folly\" \"$(PODS_ROOT)/DoubleConversion\"",
|
||||
"DEFINES_MODULE" => "YES" }
|
||||
s.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/RCT-Folly\" \"$(PODS_ROOT)/DoubleConversion\"" }
|
||||
|
||||
s.dependency "boost", "1.76.0"
|
||||
s.dependency "DoubleConversion"
|
||||
|
||||
@@ -27,11 +27,13 @@ Pod::Spec.new do |s|
|
||||
s.source = source
|
||||
s.source_files = "**/*.{cpp,h}"
|
||||
s.header_dir = "react/debug"
|
||||
s.pod_target_xcconfig = { "CLANG_CXX_LANGUAGE_STANDARD" => "c++17",
|
||||
"DEFINES_MODULE" => "YES" }
|
||||
s.pod_target_xcconfig = {
|
||||
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17",
|
||||
"DEFINES_MODULE" => "YES"
|
||||
}
|
||||
|
||||
if ENV['USE_FRAMEWORKS']
|
||||
s.module_name = "React_debug"
|
||||
s.header_mappings_dir = File.absolute_path("../..")
|
||||
s.header_mappings_dir = "../.."
|
||||
end
|
||||
end
|
||||
|
||||
@@ -17,5 +17,7 @@
|
||||
// control and use as a more reliable xplat flag. For any build that doesn't
|
||||
// have NDEBUG defined, we enable REACT_NATIVE_DEBUG for convenience.
|
||||
#ifndef NDEBUG
|
||||
#ifndef COCOAPODS
|
||||
#define REACT_NATIVE_DEBUG 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ Pod::Spec.new do |s|
|
||||
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17",
|
||||
"GCC_WARN_PEDANTIC" => "YES" }
|
||||
if ENV['USE_FRAMEWORKS']
|
||||
s.header_mappings_dir = File.absolute_path('./')
|
||||
s.header_mappings_dir = './'
|
||||
end
|
||||
|
||||
s.source_files = "ReactCommon/**/*.{mm,cpp,h}"
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ Pod::Spec.new do |s|
|
||||
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17",
|
||||
"GCC_WARN_PEDANTIC" => "YES" }
|
||||
if ENV['USE_FRAMEWORKS']
|
||||
s.header_mappings_dir = File.absolute_path('./')
|
||||
s.header_mappings_dir = './'
|
||||
end
|
||||
|
||||
|
||||
|
||||
+22
-6
@@ -74,19 +74,35 @@ static Class getViewManagerFromComponentName(const std::string &componentName)
|
||||
return nil;
|
||||
}
|
||||
|
||||
static std::shared_ptr<void> const constructCoordinator(
|
||||
ContextContainer::Shared const &contextContainer,
|
||||
ComponentDescriptor::Flavor const &flavor)
|
||||
static Class getViewManagerClass(const std::string &componentName, RCTBridge *bridge)
|
||||
{
|
||||
Class viewManager = getViewManagerFromComponentName(componentName);
|
||||
if (viewManager != nil) {
|
||||
return viewManager;
|
||||
}
|
||||
|
||||
// If all the heuristics fail, let's try to retrieve the view manager from the bridge/bridgeProxy
|
||||
if (bridge != nil) {
|
||||
return [[bridge moduleForName:RCTNSStringFromString(componentName)] class];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
static const std::shared_ptr<void> constructCoordinator(
|
||||
const ContextContainer::Shared &contextContainer,
|
||||
const ComponentDescriptor::Flavor &flavor)
|
||||
{
|
||||
auto componentName = *std::static_pointer_cast<std::string const>(flavor);
|
||||
Class viewManagerClass = getViewManagerFromComponentName(componentName);
|
||||
assert(viewManagerClass);
|
||||
auto optionalBridge = contextContainer->find<std::shared_ptr<void>>("Bridge");
|
||||
RCTBridge *bridge;
|
||||
if (optionalBridge) {
|
||||
bridge = unwrapManagedObjectWeakly(optionalBridge.value());
|
||||
}
|
||||
|
||||
auto componentName = *std::static_pointer_cast<std::string const>(flavor);
|
||||
Class viewManagerClass = getViewManagerClass(componentName, bridge);
|
||||
assert(viewManagerClass);
|
||||
|
||||
auto optionalEventDispatcher = contextContainer->find<std::shared_ptr<void>>("RCTEventDispatcher");
|
||||
RCTEventDispatcher *eventDispatcher;
|
||||
if (optionalEventDispatcher) {
|
||||
|
||||
+4
@@ -92,6 +92,10 @@ using namespace facebook::react;
|
||||
if (props.isObject()) {
|
||||
NSDictionary<NSString *, id> *convertedProps = convertFollyDynamicToId(props);
|
||||
[_componentData setProps:convertedProps forView:view];
|
||||
|
||||
if ([view respondsToSelector:@selector(didSetProps:)]) {
|
||||
[view performSelector:@selector(didSetProps:) withObject:[convertedProps allKeys]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+15
-1
@@ -319,6 +319,15 @@ ScrollViewProps::ScrollViewProps(
|
||||
rawProps,
|
||||
"scrollToOverflowEnabled",
|
||||
sourceProps.scrollToOverflowEnabled,
|
||||
{})),
|
||||
isInvertedVirtualizedList(
|
||||
CoreFeatures::enablePropIteratorSetter
|
||||
? sourceProps.isInvertedVirtualizedList
|
||||
: convertRawProp(
|
||||
context,
|
||||
rawProps,
|
||||
"isInvertedVirtualizedList",
|
||||
sourceProps.isInvertedVirtualizedList,
|
||||
{})) {}
|
||||
|
||||
void ScrollViewProps::setProp(
|
||||
@@ -368,6 +377,7 @@ void ScrollViewProps::setProp(
|
||||
RAW_SET_PROP_SWITCH_CASE_BASIC(snapToEnd);
|
||||
RAW_SET_PROP_SWITCH_CASE_BASIC(contentInsetAdjustmentBehavior);
|
||||
RAW_SET_PROP_SWITCH_CASE_BASIC(scrollToOverflowEnabled);
|
||||
RAW_SET_PROP_SWITCH_CASE_BASIC(isInvertedVirtualizedList);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -492,7 +502,11 @@ SharedDebugStringConvertibleList ScrollViewProps::getDebugProps() const {
|
||||
debugStringConvertibleItem(
|
||||
"snapToStart", snapToStart, defaultScrollViewProps.snapToStart),
|
||||
debugStringConvertibleItem(
|
||||
"snapToEnd", snapToEnd, defaultScrollViewProps.snapToEnd)};
|
||||
"snapToEnd", snapToEnd, defaultScrollViewProps.snapToEnd),
|
||||
debugStringConvertibleItem(
|
||||
"isInvertedVirtualizedList",
|
||||
snapToEnd,
|
||||
defaultScrollViewProps.isInvertedVirtualizedList)};
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+1
@@ -69,6 +69,7 @@ class ScrollViewProps final : public ViewProps {
|
||||
ContentInsetAdjustmentBehavior contentInsetAdjustmentBehavior{
|
||||
ContentInsetAdjustmentBehavior::Never};
|
||||
bool scrollToOverflowEnabled{false};
|
||||
bool isInvertedVirtualizedList{false};
|
||||
|
||||
#pragma mark - DebugStringConvertible
|
||||
|
||||
|
||||
@@ -17,6 +17,11 @@ namespace react {
|
||||
// It should be used as infrequently as possible - most props can and should
|
||||
// be parsed without any context.
|
||||
struct PropsParserContext {
|
||||
PropsParserContext(
|
||||
SurfaceId const surfaceId,
|
||||
ContextContainer const &contextContainer)
|
||||
: surfaceId(surfaceId), contextContainer(contextContainer) {}
|
||||
|
||||
// Non-copyable
|
||||
PropsParserContext(const PropsParserContext &) = delete;
|
||||
PropsParserContext &operator=(const PropsParserContext &) = delete;
|
||||
|
||||
@@ -38,6 +38,8 @@ void RawPropsKeyMap::insert(
|
||||
item.value = value;
|
||||
key.render(item.name, &item.length);
|
||||
items_.push_back(item);
|
||||
react_native_assert(
|
||||
items_.size() < std::numeric_limits<RawPropsPropNameLength>::max());
|
||||
}
|
||||
|
||||
void RawPropsKeyMap::reindex() noexcept {
|
||||
|
||||
@@ -42,6 +42,7 @@ RawValue const *RawPropsParser::at(
|
||||
// This is not thread-safe part; this happens only during initialization of
|
||||
// a `ComponentDescriptor` where it is actually safe.
|
||||
keys_.push_back(key);
|
||||
react_native_assert(size < std::numeric_limits<RawPropsValueIndex>::max());
|
||||
nameToIndex_.insert(key, static_cast<RawPropsValueIndex>(size));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -16,11 +16,11 @@ namespace react {
|
||||
/*
|
||||
* Type used to represent an index of some stored values in small arrays.
|
||||
*/
|
||||
using RawPropsValueIndex = uint8_t;
|
||||
using RawPropsValueIndex = uint16_t;
|
||||
static_assert(
|
||||
sizeof(RawPropsValueIndex) == 1,
|
||||
"RawPropsValueIndex must be one byte size.");
|
||||
using RawPropsPropNameLength = uint8_t;
|
||||
sizeof(RawPropsValueIndex) == 2,
|
||||
"RawPropsValueIndex must be two byte size.");
|
||||
using RawPropsPropNameLength = uint16_t;
|
||||
using RawPropsPropNameHash = uint32_t;
|
||||
|
||||
/*
|
||||
|
||||
@@ -45,13 +45,15 @@ Pod::Spec.new do |s|
|
||||
|
||||
if ENV['USE_FRAMEWORKS']
|
||||
s.module_name = "React_graphics"
|
||||
s.header_mappings_dir = File.absolute_path("../../..")
|
||||
s.header_mappings_dir = "../../.."
|
||||
header_search_paths = header_search_paths + ["\"$(PODS_TARGET_SRCROOT)/platform/ios\""]
|
||||
end
|
||||
|
||||
s.pod_target_xcconfig = { "USE_HEADERMAP" => "NO",
|
||||
"HEADER_SEARCH_PATHS" => header_search_paths.join(" "),
|
||||
"DEFINES_MODULE" => "YES" }
|
||||
s.pod_target_xcconfig = {
|
||||
"USE_HEADERMAP" => "NO",
|
||||
"HEADER_SEARCH_PATHS" => header_search_paths.join(" "),
|
||||
"DEFINES_MODULE" => "YES"
|
||||
}
|
||||
|
||||
s.dependency "glog"
|
||||
s.dependency "RCT-Folly/Fabric", folly_version
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ Pod::Spec.new do |s|
|
||||
|
||||
if ENV['USE_FRAMEWORKS']
|
||||
s.module_name = "React_ImageManager"
|
||||
s.header_mappings_dir = File.absolute_path("./")
|
||||
s.header_mappings_dir = "./"
|
||||
header_search_paths = header_search_paths + [
|
||||
"\"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers\"",
|
||||
"\"$(PODS_ROOT)/DoubleConversion\"",
|
||||
|
||||
@@ -355,6 +355,11 @@ CommitStatus ShadowTree::tryCommit(
|
||||
newRootShadowNode = delegate_.shadowTreeWillCommit(
|
||||
*this, oldRootShadowNode, newRootShadowNode);
|
||||
|
||||
if (!newRootShadowNode ||
|
||||
(commitOptions.shouldYield && commitOptions.shouldYield())) {
|
||||
return CommitStatus::Cancelled;
|
||||
}
|
||||
|
||||
// Layout nodes.
|
||||
std::vector<LayoutableShadowNode const *> affectedLayoutableNodes{};
|
||||
affectedLayoutableNodes.reserve(1024);
|
||||
@@ -372,17 +377,16 @@ CommitStatus ShadowTree::tryCommit(
|
||||
// Updating `currentRevision_` in unique manner if it hasn't changed.
|
||||
std::unique_lock lock(commitMutex_);
|
||||
|
||||
if (commitOptions.shouldYield && commitOptions.shouldYield()) {
|
||||
return CommitStatus::Cancelled;
|
||||
}
|
||||
|
||||
if (currentRevision_.number != oldRevision.number) {
|
||||
return CommitStatus::Failed;
|
||||
}
|
||||
|
||||
auto newRevisionNumber = oldRevision.number + 1;
|
||||
|
||||
if (!newRootShadowNode ||
|
||||
(commitOptions.shouldYield && commitOptions.shouldYield())) {
|
||||
return CommitStatus::Cancelled;
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> dispatchLock(EventEmitter::DispatchMutex());
|
||||
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ Pod::Spec.new do |s|
|
||||
|
||||
if ENV['USE_FRAMEWORKS']
|
||||
s.module_name = "React_runtimescheduler"
|
||||
s.header_mappings_dir = File.absolute_path("../../..")
|
||||
s.header_mappings_dir = "../../.."
|
||||
end
|
||||
|
||||
s.dependency "React-jsi"
|
||||
|
||||
@@ -42,13 +42,15 @@ Pod::Spec.new do |s|
|
||||
s.compiler_flags = folly_compiler_flags
|
||||
s.header_dir = "react/utils"
|
||||
s.exclude_files = "tests"
|
||||
s.pod_target_xcconfig = { "CLANG_CXX_LANGUAGE_STANDARD" => "c++17",
|
||||
"HEADER_SEARCH_PATHS" => header_search_paths.join(' '),
|
||||
"DEFINES_MODULE" => "YES" }
|
||||
s.pod_target_xcconfig = {
|
||||
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17",
|
||||
"HEADER_SEARCH_PATHS" => header_search_paths.join(' '),
|
||||
"DEFINES_MODULE" => "YES"
|
||||
}
|
||||
|
||||
if ENV['USE_FRAMEWORKS']
|
||||
s.module_name = "React_utils"
|
||||
s.header_mappings_dir = File.absolute_path("../..")
|
||||
s.header_mappings_dir = "../.."
|
||||
end
|
||||
|
||||
s.dependency "RCT-Folly", folly_version
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* @flow strict
|
||||
* @format
|
||||
*/
|
||||
|
||||
declare module 'ansi-regex' {
|
||||
declare export type Options = {
|
||||
/**
|
||||
* Match only the first ANSI escape.
|
||||
*/
|
||||
+onlyFirst?: boolean,
|
||||
};
|
||||
declare export default function ansiRegex(options?: Options): RegExp;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-native",
|
||||
"version": "0.72.2",
|
||||
"version": "0.72.17",
|
||||
"bin": "./cli.js",
|
||||
"description": "A framework for building native apps using React",
|
||||
"license": "MIT",
|
||||
@@ -79,27 +79,28 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@jest/create-cache-key-function": "^29.2.1",
|
||||
"@react-native-community/cli": "11.3.5",
|
||||
"@react-native-community/cli-platform-android": "11.3.5",
|
||||
"@react-native-community/cli-platform-ios": "11.3.5",
|
||||
"@react-native-community/cli": "^11.4.1",
|
||||
"@react-native-community/cli-platform-android": "^11.4.1",
|
||||
"@react-native-community/cli-platform-ios": "^11.4.1",
|
||||
"@react-native/assets-registry": "^0.72.0",
|
||||
"@react-native/codegen": "^0.72.6",
|
||||
"@react-native/codegen": "^0.72.8",
|
||||
"@react-native/gradle-plugin": "^0.72.11",
|
||||
"@react-native/js-polyfills": "^0.72.1",
|
||||
"@react-native/normalize-colors": "^0.72.0",
|
||||
"@react-native/virtualized-lists": "^0.72.6",
|
||||
"@react-native/virtualized-lists": "^0.72.8",
|
||||
"abort-controller": "^3.0.0",
|
||||
"anser": "^1.4.9",
|
||||
"base64-js": "^1.1.2",
|
||||
"deprecated-react-native-prop-types": "4.1.0",
|
||||
"deprecated-react-native-prop-types": "^4.2.3",
|
||||
"ansi-regex": "^5.0.0",
|
||||
"event-target-shim": "^5.0.1",
|
||||
"flow-enums-runtime": "^0.0.5",
|
||||
"invariant": "^2.2.4",
|
||||
"jest-environment-node": "^29.2.1",
|
||||
"jsc-android": "^250231.0.0",
|
||||
"memoize-one": "^5.0.0",
|
||||
"metro-runtime": "0.76.7",
|
||||
"metro-source-map": "0.76.7",
|
||||
"metro-runtime": "^0.76.9",
|
||||
"metro-source-map": "^0.76.9",
|
||||
"mkdirp": "^0.5.1",
|
||||
"nullthrows": "^1.1.1",
|
||||
"pretty-format": "^26.5.2",
|
||||
|
||||
@@ -68,7 +68,7 @@ class CodegenTests < Test::Unit::TestCase
|
||||
assert_equal(Pod::Executable.executed_commands.length, 0)
|
||||
end
|
||||
|
||||
def testCheckAndGenerateEmptyThirdPartyProvider_whenHeaderMissingAndCodegenMissing_raiseError()
|
||||
def testCheckAndGenerateEmptyThirdPartyProvider_whenHeaderMissingAndCodegenMissing_dontBuildCodegen()
|
||||
|
||||
# Arrange
|
||||
FileMock.mocked_existing_files([
|
||||
@@ -76,7 +76,7 @@ class CodegenTests < Test::Unit::TestCase
|
||||
])
|
||||
|
||||
# Act
|
||||
assert_raise {
|
||||
assert_nothing_raised {
|
||||
checkAndGenerateEmptyThirdPartyProvider!(@prefix, false, dir_manager: DirMock, file_manager: FileMock)
|
||||
}
|
||||
|
||||
@@ -84,16 +84,16 @@ class CodegenTests < Test::Unit::TestCase
|
||||
assert_equal(Pathname.pwd_invocation_count, 1)
|
||||
assert_equal(Pod::Config.instance.installation_root.relative_path_from_invocation_count, 1)
|
||||
assert_equal(FileMock.exist_invocation_params, [
|
||||
@prefix + "/React/Fabric/" + @third_party_provider_header
|
||||
@prefix + "/React/Fabric/" + @third_party_provider_header,
|
||||
@prefix + "/React/Fabric/tmpSchemaList.txt",
|
||||
])
|
||||
assert_equal(DirMock.exist_invocation_params, [
|
||||
@base_path + "/"+ @prefix + "/../react-native-codegen",
|
||||
@base_path + "/"+ @prefix + "/../@react-native/codegen",
|
||||
])
|
||||
assert_equal(Pod::UI.collected_messages, [])
|
||||
assert_equal(Pod::UI.collected_messages, ["[Codegen] generating an empty RCTThirdPartyFabricComponentsProvider"])
|
||||
assert_equal($collected_commands, [])
|
||||
assert_equal(FileMock.open_files.length, 0)
|
||||
assert_equal(Pod::Executable.executed_commands.length, 0)
|
||||
assert_equal(FileMock.open_files.length, 1)
|
||||
assert_equal(Pod::Executable.executed_commands.length, 1)
|
||||
end
|
||||
|
||||
def testCheckAndGenerateEmptyThirdPartyProvider_whenImplementationMissingAndCodegenrepoExists_dontBuildCodegen()
|
||||
@@ -145,7 +145,7 @@ class CodegenTests < Test::Unit::TestCase
|
||||
|
||||
def testCheckAndGenerateEmptyThirdPartyProvider_whenBothMissing_buildCodegen()
|
||||
# Arrange
|
||||
codegen_cli_path = @base_path + "/" + @prefix + "/../@react-native/codegen"
|
||||
codegen_cli_path = @base_path + "/" + @prefix + "/../react-native-codegen"
|
||||
DirMock.mocked_existing_dirs([
|
||||
codegen_cli_path,
|
||||
])
|
||||
@@ -160,15 +160,14 @@ class CodegenTests < Test::Unit::TestCase
|
||||
@prefix + "/React/Fabric/" + @tmp_schema_list_file
|
||||
])
|
||||
assert_equal(DirMock.exist_invocation_params, [
|
||||
@base_path + "/" + @prefix + "/../react-native-codegen",
|
||||
codegen_cli_path,
|
||||
codegen_cli_path + "/lib",
|
||||
])
|
||||
assert_equal(Pod::UI.collected_messages, [
|
||||
"[Codegen] building #{codegen_cli_path}.",
|
||||
"[Codegen] building #{codegen_cli_path}",
|
||||
"[Codegen] generating an empty RCTThirdPartyFabricComponentsProvider"
|
||||
])
|
||||
assert_equal($collected_commands, ["~/app/ios/../../../@react-native/codegen/scripts/oss/build.sh"])
|
||||
assert_equal($collected_commands, ["~/app/ios/../../../react-native-codegen/scripts/oss/build.sh"])
|
||||
assert_equal(FileMock.open_files[0].collected_write, ["[]"])
|
||||
assert_equal(FileMock.open_files[0].fsync_invocation_count, 1)
|
||||
assert_equal(Pod::Executable.executed_commands[0], {
|
||||
|
||||
@@ -107,7 +107,6 @@ class JSEngineTests < Test::Unit::TestCase
|
||||
assert_equal($podInvocation["libevent"][:version], "~> 2.1.12")
|
||||
hermes_engine_pod_invocation = $podInvocation["hermes-engine"]
|
||||
assert_equal(hermes_engine_pod_invocation[:podspec], "../../sdks/hermes-engine/hermes-engine.podspec")
|
||||
assert_equal(hermes_engine_pod_invocation[:tag], "")
|
||||
end
|
||||
|
||||
def test_setupHermes_installsPods_installsFabricSubspecWhenFabricEnabled
|
||||
@@ -122,7 +121,6 @@ class JSEngineTests < Test::Unit::TestCase
|
||||
assert_equal($podInvocation["React-jsi"][:path], "../../ReactCommon/jsi")
|
||||
hermes_engine_pod_invocation = $podInvocation["hermes-engine"]
|
||||
assert_equal(hermes_engine_pod_invocation[:podspec], "../../sdks/hermes-engine/hermes-engine.podspec")
|
||||
assert_equal(hermes_engine_pod_invocation[:tag], "")
|
||||
assert_equal($podInvocation["React-hermes"][:path], "../../ReactCommon/hermes")
|
||||
assert_equal($podInvocation["libevent"][:version], "~> 2.1.12")
|
||||
end
|
||||
|
||||
@@ -128,7 +128,7 @@ class NewArchitectureTests < Test::Unit::TestCase
|
||||
NewArchitectureHelper.install_modules_dependencies(spec, true, '2021.07.22.00')
|
||||
|
||||
# Assert
|
||||
assert_equal(spec.compiler_flags, NewArchitectureHelper.folly_compiler_flags)
|
||||
assert_equal(spec.compiler_flags, "$(inherited) #{NewArchitectureHelper.folly_compiler_flags} -DRCT_NEW_ARCH_ENABLED=1")
|
||||
assert_equal(spec.pod_target_xcconfig["HEADER_SEARCH_PATHS"], "\"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/DoubleConversion\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTFabric/RCTFabric.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-utils/React_utils.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-debug/React_debug.framework/Headers\"")
|
||||
assert_equal(spec.pod_target_xcconfig["CLANG_CXX_LANGUAGE_STANDARD"], "c++17")
|
||||
assert_equal(spec.pod_target_xcconfig["OTHER_CPLUSPLUSFLAGS"], "$(inherited) -DRCT_NEW_ARCH_ENABLED=1 -DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1")
|
||||
@@ -166,7 +166,7 @@ class NewArchitectureTests < Test::Unit::TestCase
|
||||
NewArchitectureHelper.install_modules_dependencies(spec, false, '2021.07.22.00')
|
||||
|
||||
# Assert
|
||||
assert_equal(spec.compiler_flags, "-Wno-nullability-completeness #{NewArchitectureHelper.folly_compiler_flags}")
|
||||
assert_equal(spec.compiler_flags, "$(inherited) -Wno-nullability-completeness #{NewArchitectureHelper.folly_compiler_flags}")
|
||||
assert_equal(spec.pod_target_xcconfig["HEADER_SEARCH_PATHS"], "#{other_flags} \"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/DoubleConversion\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTFabric/RCTFabric.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-utils/React_utils.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-debug/React_debug.framework/Headers\"")
|
||||
assert_equal(spec.pod_target_xcconfig["CLANG_CXX_LANGUAGE_STANDARD"], "c++17")
|
||||
assert_equal(
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
# 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.
|
||||
|
||||
class XcodebuildMock < Xcodebuild
|
||||
@@version = ""
|
||||
@@version_invocation_count = 0
|
||||
|
||||
def self.set_version=(v)
|
||||
@@version = v
|
||||
end
|
||||
|
||||
def self.version
|
||||
@@version_invocation_count += 1
|
||||
@@version
|
||||
end
|
||||
|
||||
def self.version_invocation_count
|
||||
@@version_invocation_count
|
||||
end
|
||||
|
||||
def self.reset()
|
||||
@@version_invocation_count = 0
|
||||
end
|
||||
end
|
||||
@@ -14,6 +14,7 @@ require_relative "./test_utils/FileMock.rb"
|
||||
require_relative "./test_utils/systemUtils.rb"
|
||||
require_relative "./test_utils/PathnameMock.rb"
|
||||
require_relative "./test_utils/TargetDefinitionMock.rb"
|
||||
require_relative "./test_utils/XcodebuildMock.rb"
|
||||
|
||||
class UtilsTests < Test::Unit::TestCase
|
||||
def setup
|
||||
@@ -28,6 +29,7 @@ class UtilsTests < Test::Unit::TestCase
|
||||
Pod::Config.reset()
|
||||
SysctlChecker.reset()
|
||||
Environment.reset()
|
||||
XcodebuildMock.reset()
|
||||
ENV['RCT_NEW_ARCH_ENABLED'] = '0'
|
||||
ENV['USE_HERMES'] = '1'
|
||||
ENV['USE_FRAMEWORKS'] = nil
|
||||
@@ -177,11 +179,33 @@ class UtilsTests < Test::Unit::TestCase
|
||||
# ============================ #
|
||||
# Test - Exclude Architectures #
|
||||
# ============================ #
|
||||
def test_excludeArchitectures_whenHermesEngineIsNotIncluded_excludeNothing
|
||||
def test_excludeArchitectures_whenHermesEngineIsNotIncluded_withNoValue_leaveUnset
|
||||
# Arrange
|
||||
user_project_mock = prepare_empty_user_project_mock()
|
||||
pods_projects_mock = PodsProjectMock.new()
|
||||
installer = InstallerMock.new(PodsProjectMock.new(), [
|
||||
AggregatedProjectMock.new(user_project_mock)
|
||||
])
|
||||
|
||||
# Act
|
||||
ReactNativePodsUtils.exclude_i386_architecture_while_using_hermes(installer)
|
||||
|
||||
# Assert
|
||||
user_project_mock.build_configurations.each do |config|
|
||||
assert_equal(config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"], nil)
|
||||
end
|
||||
assert_equal(user_project_mock.save_invocation_count, 0)
|
||||
assert_equal(pods_projects_mock.save_invocation_count, 0)
|
||||
end
|
||||
|
||||
def test_excludeArchitectures_whenHermesEngineIsNotIncluded_withExistingValue_preserveExistingValue
|
||||
# Arrange
|
||||
user_project_mock = prepare_empty_user_project_mock()
|
||||
user_project_mock.build_configurations.each do |config|
|
||||
config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = "arm64"
|
||||
end
|
||||
pods_projects_mock = PodsProjectMock.new()
|
||||
installer = InstallerMock.new(PodsProjectMock.new(), [
|
||||
installer = InstallerMock.new(pods_projects_mock, [
|
||||
AggregatedProjectMock.new(user_project_mock)
|
||||
])
|
||||
|
||||
@@ -190,13 +214,14 @@ class UtilsTests < Test::Unit::TestCase
|
||||
|
||||
# Assert
|
||||
user_project_mock.build_configurations.each do |config|
|
||||
assert_equal(config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"], "")
|
||||
assert_equal(config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"], "arm64")
|
||||
end
|
||||
assert_equal(user_project_mock.save_invocation_count, 1)
|
||||
|
||||
assert_equal(user_project_mock.save_invocation_count, 0)
|
||||
assert_equal(pods_projects_mock.save_invocation_count, 0)
|
||||
end
|
||||
|
||||
def test_excludeArchitectures_whenHermesEngineIsIncluded_excludeI386
|
||||
def test_excludeArchitectures_whenHermesEngineIsIncluded_withNoValue_onlyExcludeI386
|
||||
# Arrange
|
||||
user_project_mock = prepare_empty_user_project_mock()
|
||||
pods_projects_mock = PodsProjectMock.new([], {"hermes-engine" => {}})
|
||||
@@ -216,6 +241,29 @@ class UtilsTests < Test::Unit::TestCase
|
||||
assert_equal(pods_projects_mock.save_invocation_count, 1)
|
||||
end
|
||||
|
||||
def test_excludeArchitectures_whenHermesEngineIsIncluded_withExistingValue_appendI386
|
||||
# Arrange
|
||||
user_project_mock = prepare_empty_user_project_mock()
|
||||
user_project_mock.build_configurations.each do |config|
|
||||
config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = "arm64"
|
||||
end
|
||||
pods_projects_mock = PodsProjectMock.new([], {"hermes-engine" => {}})
|
||||
installer = InstallerMock.new(pods_projects_mock, [
|
||||
AggregatedProjectMock.new(user_project_mock)
|
||||
])
|
||||
|
||||
# Act
|
||||
ReactNativePodsUtils.exclude_i386_architecture_while_using_hermes(installer)
|
||||
|
||||
# Assert
|
||||
user_project_mock.build_configurations.each do |config|
|
||||
assert_equal(config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"], "arm64 i386")
|
||||
end
|
||||
|
||||
assert_equal(user_project_mock.save_invocation_count, 1)
|
||||
assert_equal(pods_projects_mock.save_invocation_count, 1)
|
||||
end
|
||||
|
||||
# ================= #
|
||||
# Test - Fix Config #
|
||||
# ================= #
|
||||
@@ -437,9 +485,9 @@ class UtilsTests < Test::Unit::TestCase
|
||||
# ================================= #
|
||||
# Test - Apply Xcode 15 Patch #
|
||||
# ================================= #
|
||||
|
||||
def test_applyXcode15Patch_correctlyAppliesNecessaryPatch
|
||||
def test_applyXcode15Patch_whenXcodebuild14_correctlyAppliesNecessaryPatch
|
||||
# Arrange
|
||||
XcodebuildMock.set_version = "Xcode 14.3"
|
||||
first_target = prepare_target("FirstTarget")
|
||||
second_target = prepare_target("SecondTarget")
|
||||
third_target = TargetMock.new("ThirdTarget", [
|
||||
@@ -468,24 +516,117 @@ class UtilsTests < Test::Unit::TestCase
|
||||
])
|
||||
|
||||
# Act
|
||||
ReactNativePodsUtils.apply_xcode_15_patch(installer)
|
||||
user_project_mock.build_configurations.each do |config|
|
||||
assert_nil(config.build_settings["OTHER_LDFLAGS"])
|
||||
end
|
||||
|
||||
ReactNativePodsUtils.apply_xcode_15_patch(installer, :xcodebuild_manager => XcodebuildMock)
|
||||
|
||||
# Assert
|
||||
first_target.build_configurations.each do |config|
|
||||
assert_equal(config.build_settings["GCC_PREPROCESSOR_DEFINITIONS"].strip,
|
||||
'$(inherited) "_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION"'
|
||||
)
|
||||
user_project_mock.build_configurations.each do |config|
|
||||
assert_equal("$(inherited) _LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION", config.build_settings["GCC_PREPROCESSOR_DEFINITIONS"])
|
||||
assert_equal("$(inherited) ", config.build_settings["OTHER_LDFLAGS"])
|
||||
end
|
||||
second_target.build_configurations.each do |config|
|
||||
assert_equal(config.build_settings["GCC_PREPROCESSOR_DEFINITIONS"].strip,
|
||||
'$(inherited) "_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION"'
|
||||
)
|
||||
|
||||
# User project and Pods project
|
||||
assert_equal(2, XcodebuildMock.version_invocation_count)
|
||||
end
|
||||
|
||||
def test_applyXcode15Patch_whenXcodebuild15_correctlyAppliesNecessaryPatch
|
||||
# Arrange
|
||||
XcodebuildMock.set_version = "Xcode 15.0"
|
||||
first_target = prepare_target("FirstTarget")
|
||||
second_target = prepare_target("SecondTarget")
|
||||
third_target = TargetMock.new("ThirdTarget", [
|
||||
BuildConfigurationMock.new("Debug", {
|
||||
"GCC_PREPROCESSOR_DEFINITIONS" => '$(inherited) "SomeFlag=1" '
|
||||
}),
|
||||
BuildConfigurationMock.new("Release", {
|
||||
"GCC_PREPROCESSOR_DEFINITIONS" => '$(inherited) "SomeFlag=1" '
|
||||
}),
|
||||
], nil)
|
||||
|
||||
user_project_mock = UserProjectMock.new("/a/path", [
|
||||
prepare_config("Debug"),
|
||||
prepare_config("Release"),
|
||||
],
|
||||
:native_targets => [
|
||||
first_target,
|
||||
second_target
|
||||
]
|
||||
)
|
||||
pods_projects_mock = PodsProjectMock.new([], {"hermes-engine" => {}}, :native_targets => [
|
||||
third_target
|
||||
])
|
||||
installer = InstallerMock.new(pods_projects_mock, [
|
||||
AggregatedProjectMock.new(user_project_mock)
|
||||
])
|
||||
|
||||
# Act
|
||||
user_project_mock.build_configurations.each do |config|
|
||||
assert_nil(config.build_settings["OTHER_LDFLAGS"])
|
||||
end
|
||||
third_target.build_configurations.each do |config|
|
||||
assert_equal(config.build_settings["GCC_PREPROCESSOR_DEFINITIONS"].strip,
|
||||
'$(inherited) "SomeFlag=1" "_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION"'
|
||||
)
|
||||
|
||||
ReactNativePodsUtils.apply_xcode_15_patch(installer, :xcodebuild_manager => XcodebuildMock)
|
||||
|
||||
# Assert
|
||||
user_project_mock.build_configurations.each do |config|
|
||||
assert_equal("$(inherited) _LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION", config.build_settings["GCC_PREPROCESSOR_DEFINITIONS"])
|
||||
assert_equal("$(inherited) -Wl -ld_classic", config.build_settings["OTHER_LDFLAGS"])
|
||||
end
|
||||
|
||||
# User project and Pods project
|
||||
assert_equal(2, XcodebuildMock.version_invocation_count)
|
||||
end
|
||||
|
||||
def test_applyXcode15Patch_whenXcodebuild14ButProjectHasSettings_correctlyRemovesNecessaryPatch
|
||||
# Arrange
|
||||
XcodebuildMock.set_version = "Xcode 14.3"
|
||||
first_target = prepare_target("FirstTarget")
|
||||
second_target = prepare_target("SecondTarget")
|
||||
third_target = TargetMock.new("ThirdTarget", [
|
||||
BuildConfigurationMock.new("Debug", {
|
||||
"GCC_PREPROCESSOR_DEFINITIONS" => '$(inherited) "SomeFlag=1" '
|
||||
}),
|
||||
BuildConfigurationMock.new("Release", {
|
||||
"GCC_PREPROCESSOR_DEFINITIONS" => '$(inherited) "SomeFlag=1" '
|
||||
}),
|
||||
], nil)
|
||||
|
||||
debug_config = prepare_config("Debug", {"OTHER_LDFLAGS" => "$(inherited) -Wl -ld_classic "})
|
||||
release_config = prepare_config("Release", {"OTHER_LDFLAGS" => "$(inherited) -Wl -ld_classic "})
|
||||
|
||||
user_project_mock = UserProjectMock.new("/a/path", [
|
||||
debug_config,
|
||||
release_config,
|
||||
],
|
||||
:native_targets => [
|
||||
first_target,
|
||||
second_target
|
||||
]
|
||||
)
|
||||
pods_projects_mock = PodsProjectMock.new([debug_config.clone, release_config.clone], {"hermes-engine" => {}}, :native_targets => [
|
||||
third_target
|
||||
])
|
||||
installer = InstallerMock.new(pods_projects_mock, [
|
||||
AggregatedProjectMock.new(user_project_mock)
|
||||
])
|
||||
|
||||
# Act
|
||||
user_project_mock.build_configurations.each do |config|
|
||||
assert_equal("$(inherited) -Wl -ld_classic ", config.build_settings["OTHER_LDFLAGS"])
|
||||
end
|
||||
|
||||
ReactNativePodsUtils.apply_xcode_15_patch(installer, :xcodebuild_manager => XcodebuildMock)
|
||||
|
||||
# Assert
|
||||
user_project_mock.build_configurations.each do |config|
|
||||
assert_equal("$(inherited) _LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION", config.build_settings["GCC_PREPROCESSOR_DEFINITIONS"])
|
||||
assert_equal("$(inherited)", config.build_settings["OTHER_LDFLAGS"])
|
||||
end
|
||||
|
||||
# User project and Pods project
|
||||
assert_equal(2, XcodebuildMock.version_invocation_count)
|
||||
end
|
||||
|
||||
# ==================================== #
|
||||
@@ -744,12 +885,14 @@ def prepare_empty_user_project_mock
|
||||
])
|
||||
end
|
||||
|
||||
def prepare_config(config_name)
|
||||
return BuildConfigurationMock.new(config_name, {"LIBRARY_SEARCH_PATHS" => [
|
||||
def prepare_config(config_name, extra_config = {})
|
||||
config = {"LIBRARY_SEARCH_PATHS" => [
|
||||
"$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)",
|
||||
"\"$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)\"",
|
||||
"another/path",
|
||||
]})
|
||||
]}.merge(extra_config)
|
||||
|
||||
return BuildConfigurationMock.new(config_name, config)
|
||||
end
|
||||
|
||||
def prepare_target(name, product_type = nil, dependencies = [])
|
||||
|
||||
@@ -11,23 +11,12 @@
|
||||
# - dir_manager: a class that implements the `Dir` interface. Defaults to `Dir`, the Dependency can be injected for testing purposes.
|
||||
# @throws an error if it could not find the codegen folder.
|
||||
def build_codegen!(react_native_path, relative_installation_root, dir_manager: Dir)
|
||||
codegen_repo_path = "#{relative_installation_root}/#{react_native_path}/../react-native-codegen";
|
||||
codegen_npm_path = "#{relative_installation_root}/#{react_native_path}/../@react-native/codegen";
|
||||
codegen_cli_path = ""
|
||||
codegen_repo_path = "#{relative_installation_root}/#{react_native_path}/../react-native-codegen";
|
||||
return unless dir_manager.exist?(codegen_repo_path) && !dir_manager.exist?("#{codegen_repo_path}/lib")
|
||||
|
||||
if dir_manager.exist?(codegen_repo_path)
|
||||
codegen_cli_path = codegen_repo_path
|
||||
elsif dir_manager.exist?(codegen_npm_path)
|
||||
codegen_cli_path = codegen_npm_path
|
||||
else
|
||||
raise "[codegen] Could not find react-native-codegen."
|
||||
end
|
||||
|
||||
if !dir_manager.exist?("#{codegen_cli_path}/lib")
|
||||
Pod::UI.puts "[Codegen] building #{codegen_cli_path}."
|
||||
system("#{codegen_cli_path}/scripts/oss/build.sh")
|
||||
end
|
||||
end
|
||||
Pod::UI.puts "[Codegen] building #{codegen_repo_path}"
|
||||
system("#{codegen_repo_path}/scripts/oss/build.sh")
|
||||
end
|
||||
|
||||
# It generates an empty `ThirdPartyProvider`, required by Fabric to load the components
|
||||
#
|
||||
|
||||
@@ -11,6 +11,14 @@ class SysctlChecker
|
||||
end
|
||||
end
|
||||
|
||||
# Helper class that is used to easily send commands to Xcodebuild
|
||||
# And that can be subclassed for testing purposes.
|
||||
class Xcodebuild
|
||||
def self.version
|
||||
`xcodebuild -version`
|
||||
end
|
||||
end
|
||||
|
||||
# Helper object to wrap system properties like RUBY_PLATFORM
|
||||
# This makes it easier to mock the behaviour in tests
|
||||
class Environment
|
||||
@@ -26,3 +34,11 @@ class Finder
|
||||
return `find #{path} -type f \\( #{js_files} -or #{ts_files} \\)`.split("\n").sort()
|
||||
end
|
||||
end
|
||||
|
||||
module Helpers
|
||||
class Constants
|
||||
def self.min_ios_version_supported
|
||||
return '12.4'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -30,12 +30,8 @@ def setup_hermes!(react_native_path: "../node_modules/react-native", fabric_enab
|
||||
abort unless prep_status == 0
|
||||
|
||||
pod 'React-jsi', :path => "#{react_native_path}/ReactCommon/jsi"
|
||||
# This `:tag => hermestag` below is only to tell CocoaPods to update hermes-engine when React Native version changes.
|
||||
# We have custom logic to compute the source for hermes-engine. See sdks/hermes-engine/*
|
||||
hermestag_file = File.join(react_native_path, "sdks", ".hermesversion")
|
||||
hermestag = File.exist?(hermestag_file) ? File.read(hermestag_file).strip : ''
|
||||
|
||||
pod 'hermes-engine', :podspec => "#{react_native_path}/sdks/hermes-engine/hermes-engine.podspec", :tag => hermestag
|
||||
pod 'hermes-engine', :podspec => "#{react_native_path}/sdks/hermes-engine/hermes-engine.podspec"
|
||||
pod 'React-hermes', :path => "#{react_native_path}/ReactCommon/hermes"
|
||||
pod 'libevent', '~> 2.1.12'
|
||||
end
|
||||
|
||||
@@ -87,6 +87,10 @@ class NewArchitectureHelper
|
||||
current_config = hash["pod_target_xcconfig"] != nil ? hash["pod_target_xcconfig"] : {}
|
||||
current_headers = current_config["HEADER_SEARCH_PATHS"] != nil ? current_config["HEADER_SEARCH_PATHS"] : ""
|
||||
|
||||
flags_to_add = new_arch_enabled ?
|
||||
"#{@@folly_compiler_flags} -DRCT_NEW_ARCH_ENABLED=1" :
|
||||
"#{@@folly_compiler_flags}"
|
||||
|
||||
header_search_paths = ["\"$(PODS_ROOT)/boost\""]
|
||||
if ENV['USE_FRAMEWORKS']
|
||||
header_search_paths << "\"$(PODS_ROOT)/DoubleConversion\""
|
||||
@@ -100,7 +104,7 @@ class NewArchitectureHelper
|
||||
header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-debug/React_debug.framework/Headers\""
|
||||
end
|
||||
header_search_paths_string = header_search_paths.join(" ")
|
||||
spec.compiler_flags = compiler_flags.empty? ? @@folly_compiler_flags : "#{compiler_flags} #{@@folly_compiler_flags}"
|
||||
spec.compiler_flags = compiler_flags.empty? ? "$(inherited) #{flags_to_add}" : "$(inherited) #{compiler_flags} #{flags_to_add}"
|
||||
current_config["HEADER_SEARCH_PATHS"] = current_headers.empty? ?
|
||||
header_search_paths_string :
|
||||
"#{current_headers} #{header_search_paths_string}"
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
# 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.
|
||||
|
||||
module PrivacyManifestUtils
|
||||
def self.add_aggregated_privacy_manifest(installer)
|
||||
user_project = get_user_project_from(installer)
|
||||
targets = get_application_targets(user_project)
|
||||
file_path = get_privacyinfo_file_path(user_project, targets)
|
||||
|
||||
privacy_info = read_privacyinfo_file(file_path) || {
|
||||
"NSPrivacyCollectedDataTypes" => [],
|
||||
"NSPrivacyTracking" => false
|
||||
}
|
||||
|
||||
# Get all required reason APIs defined in current pods
|
||||
required_reason_apis = get_used_required_reason_apis(installer)
|
||||
|
||||
# Add the Required Reason APIs from React Native core
|
||||
get_core_accessed_apis.each do |accessed_api|
|
||||
api_type = accessed_api["NSPrivacyAccessedAPIType"]
|
||||
reasons = accessed_api["NSPrivacyAccessedAPITypeReasons"]
|
||||
required_reason_apis[api_type] ||= []
|
||||
required_reason_apis[api_type] += reasons
|
||||
end
|
||||
|
||||
# Merge the Required Reason APIs from pods with the ones from the existing PrivacyInfo file
|
||||
(privacy_info["NSPrivacyAccessedAPITypes"] || []).each do |accessed_api|
|
||||
api_type = accessed_api["NSPrivacyAccessedAPIType"]
|
||||
reasons = accessed_api["NSPrivacyAccessedAPITypeReasons"]
|
||||
# Add reasons from existing PrivacyInfo file to the ones from pods
|
||||
required_reason_apis[api_type] ||= []
|
||||
required_reason_apis[api_type] += reasons
|
||||
end
|
||||
|
||||
# Update the existing PrivacyInfo file with the new aggregated data
|
||||
privacy_info["NSPrivacyAccessedAPITypes"] = required_reason_apis.map { |api_type, reasons|
|
||||
{
|
||||
"NSPrivacyAccessedAPIType" => api_type,
|
||||
"NSPrivacyAccessedAPITypeReasons" => reasons.uniq
|
||||
}
|
||||
}
|
||||
|
||||
Xcodeproj::Plist.write_to_path(privacy_info, file_path)
|
||||
|
||||
targets.each do |target|
|
||||
ensure_reference(file_path, user_project, target)
|
||||
end
|
||||
end
|
||||
|
||||
def self.get_application_targets(user_project)
|
||||
return user_project.targets.filter { |t| t.symbol_type == :application }
|
||||
end
|
||||
|
||||
def self.read_privacyinfo_file(file_path)
|
||||
# Maybe add missing default NSPrivacyTracking, NSPrivacyTrackingDomains, NSPrivacyCollectedDataTypes, but this works without those keys
|
||||
source_data = nil
|
||||
# Try to read an existing PrivacyInfo.xcprivacy file
|
||||
begin
|
||||
source_data = Xcodeproj::Plist.read_from_path(file_path)
|
||||
Pod::UI.puts "[Privacy Manifest Aggregation] Appending aggregated reasons to existing PrivacyInfo.xcprivacy file."
|
||||
rescue => e
|
||||
Pod::UI.puts "[Privacy Manifest Aggregation] No existing PrivacyInfo.xcprivacy file found, creating a new one."
|
||||
end
|
||||
return source_data
|
||||
end
|
||||
|
||||
def self.ensure_reference(file_path, user_project, target)
|
||||
reference_exists = target.resources_build_phase.files_references.any? { |file_ref| file_ref.path&.end_with? "PrivacyInfo.xcprivacy" }
|
||||
unless reference_exists
|
||||
# We try to find the main group, but if it doesn't exist, we default to adding the file to the project root – both work
|
||||
file_root = user_project.root_object.main_group.children.first { |group| group.name == target.name } || user_project
|
||||
file_ref = file_root.new_file(file_path)
|
||||
build_file = target.resources_build_phase.add_file_reference(file_ref, true)
|
||||
end
|
||||
end
|
||||
|
||||
def self.get_privacyinfo_file_path(user_project, targets)
|
||||
file_refs = targets.flat_map { |target| target.resources_build_phase.files_references }
|
||||
existing_file = file_refs.find { |file_ref| file_ref.path&.end_with? "PrivacyInfo.xcprivacy" }
|
||||
if existing_file
|
||||
return existing_file.real_path
|
||||
end
|
||||
# We try to find a file we know exists in the project to get the path to the main group directory
|
||||
info_plist_path = user_project.files.find { |file_ref| file_ref.name == "Info.plist" }
|
||||
if info_plist_path.nil?
|
||||
# return path that is sibling to .xcodeproj
|
||||
path = user_project.path
|
||||
return File.join(File.dirname(path), "PrivacyInfo.xcprivacy")
|
||||
end
|
||||
return File.join(File.dirname(info_plist_path.real_path),"PrivacyInfo.xcprivacy")
|
||||
end
|
||||
|
||||
def self.get_used_required_reason_apis(installer)
|
||||
# A dictionary with keys of type string (NSPrivacyAccessedAPIType) and values of type string[] (NSPrivacyAccessedAPITypeReasons[])
|
||||
used_apis = {}
|
||||
Pod::UI.puts "[Privacy Manifest Aggregation] Reading .xcprivacy files to aggregate all used Required Reason APIs."
|
||||
installer.pod_targets.each do |pod_target|
|
||||
# puts pod_target
|
||||
pod_target.file_accessors.each do |file_accessor|
|
||||
file_accessor.resource_bundles.each do |bundle_name, bundle_files|
|
||||
bundle_files.each do |file_path|
|
||||
# This needs to be named like that due to apple requirements
|
||||
if File.basename(file_path) == 'PrivacyInfo.xcprivacy'
|
||||
content = Xcodeproj::Plist.read_from_path(file_path)
|
||||
accessed_api_types = content["NSPrivacyAccessedAPITypes"]
|
||||
accessed_api_types&.each do |accessed_api|
|
||||
api_type = accessed_api["NSPrivacyAccessedAPIType"]
|
||||
reasons = accessed_api["NSPrivacyAccessedAPITypeReasons"]
|
||||
next unless api_type
|
||||
used_apis[api_type] ||= []
|
||||
used_apis[api_type] += reasons
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return used_apis
|
||||
end
|
||||
|
||||
def self.get_privacy_manifest_paths_from(user_project)
|
||||
privacy_manifests = user_project
|
||||
.files
|
||||
.select { |p|
|
||||
p.path&.end_with?('PrivacyInfo.xcprivacy')
|
||||
}
|
||||
return privacy_manifests
|
||||
end
|
||||
|
||||
def self.get_core_accessed_apis()
|
||||
file_timestamp_accessed_api = {
|
||||
"NSPrivacyAccessedAPIType" => "NSPrivacyAccessedAPICategoryFileTimestamp",
|
||||
"NSPrivacyAccessedAPITypeReasons" => ["C617.1"],
|
||||
}
|
||||
user_defaults_accessed_api = {
|
||||
"NSPrivacyAccessedAPIType" => "NSPrivacyAccessedAPICategoryUserDefaults",
|
||||
"NSPrivacyAccessedAPITypeReasons" => ["CA92.1"],
|
||||
}
|
||||
boot_time_accessed_api = {
|
||||
"NSPrivacyAccessedAPIType" => "NSPrivacyAccessedAPICategorySystemBootTime",
|
||||
"NSPrivacyAccessedAPITypeReasons" => ["35F9.1"],
|
||||
}
|
||||
return [file_timestamp_accessed_api, user_defaults_accessed_api, boot_time_accessed_api]
|
||||
end
|
||||
|
||||
|
||||
def self.get_user_project_from(installer)
|
||||
user_project = installer.aggregate_targets
|
||||
.map{ |t| t.user_project }
|
||||
.first
|
||||
return user_project
|
||||
end
|
||||
|
||||
def self.add_privacy_manifest_if_needed(installer)
|
||||
user_project = get_user_project_from(installer)
|
||||
privacy_manifest = self.get_privacy_manifest_paths_from(user_project).first
|
||||
if privacy_manifest.nil?
|
||||
privacy_manifest = {
|
||||
"NSPrivacyCollectedDataTypes" => [],
|
||||
"NSPrivacyTracking" => false,
|
||||
"NSPrivacyAccessedAPITypes" => get_core_accessed_apis
|
||||
}
|
||||
path = File.join(user_project.path.parent, "PrivacyInfo.xcprivacy")
|
||||
Xcodeproj::Plist.write_to_path(privacy_manifest, path)
|
||||
Pod::UI.puts "Your app does not have a privacy manifest! A template has been generated containing Required Reasons API usage in the core React Native library. Please add the PrivacyInfo.xcprivacy file to your project and complete data use, tracking and any additional required reasons your app is using according to Apple's guidance: https://developer.apple.com/documentation/bundleresources/privacy_manifest_files. Then, you will need to manually add this file to your project in Xcode.".red
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -54,17 +54,49 @@ class ReactNativePodsUtils
|
||||
end
|
||||
|
||||
def self.exclude_i386_architecture_while_using_hermes(installer)
|
||||
projects = self.extract_projects(installer)
|
||||
is_using_hermes = self.has_pod(installer, 'hermes-engine')
|
||||
|
||||
# Hermes does not support `i386` architecture
|
||||
excluded_archs_default = self.has_pod(installer, 'hermes-engine') ? "i386" : ""
|
||||
if is_using_hermes
|
||||
key = "EXCLUDED_ARCHS[sdk=iphonesimulator*]"
|
||||
|
||||
projects.each do |project|
|
||||
project.build_configurations.each do |config|
|
||||
config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = excluded_archs_default
|
||||
projects = self.extract_projects(installer)
|
||||
|
||||
projects.each do |project|
|
||||
project.build_configurations.each do |config|
|
||||
current_setting = config.build_settings[key] || ""
|
||||
|
||||
excluded_archs_includes_I386 = current_setting.include?("i386")
|
||||
|
||||
if !excluded_archs_includes_I386
|
||||
# Hermes does not support `i386` architecture
|
||||
config.build_settings[key] = "#{current_setting} i386".strip
|
||||
end
|
||||
end
|
||||
|
||||
project.save()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.fix_flipper_for_xcode_15_3(installer)
|
||||
|
||||
installer.pods_project.targets.each do |target|
|
||||
if target.name == 'Flipper'
|
||||
file_path = 'Pods/Flipper/xplat/Flipper/FlipperTransportTypes.h'
|
||||
if !File.exist?(file_path)
|
||||
return
|
||||
end
|
||||
|
||||
contents = File.read(file_path)
|
||||
if contents.include?('#include <functional>')
|
||||
return
|
||||
end
|
||||
mod_content = contents.gsub("#pragma once", "#pragma once\n#include <functional>")
|
||||
File.chmod(0755, file_path)
|
||||
File.open(file_path, 'w') do |file|
|
||||
file.puts(mod_content)
|
||||
end
|
||||
end
|
||||
|
||||
project.save()
|
||||
end
|
||||
end
|
||||
|
||||
@@ -121,16 +153,31 @@ class ReactNativePodsUtils
|
||||
end
|
||||
end
|
||||
|
||||
def self.apply_xcode_15_patch(installer)
|
||||
installer.target_installation_results.pod_target_installation_results
|
||||
.each do |pod_name, target_installation_result|
|
||||
target_installation_result.native_target.build_configurations.each do |config|
|
||||
# unary_function and binary_function are no longer provided in C++17 and newer standard modes as part of Xcode 15. They can be re-enabled with setting _LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION
|
||||
# Ref: https://developer.apple.com/documentation/xcode-release-notes/xcode-15-release-notes#Deprecations
|
||||
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= '$(inherited) '
|
||||
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << '"_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION" '
|
||||
def self.apply_xcode_15_patch(installer, xcodebuild_manager: Xcodebuild)
|
||||
projects = self.extract_projects(installer)
|
||||
|
||||
gcc_preprocessor_definition_key = 'GCC_PREPROCESSOR_DEFINITIONS'
|
||||
other_ld_flags_key = 'OTHER_LDFLAGS'
|
||||
libcpp_cxx17_fix = '_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION'
|
||||
xcode15_compatibility_flags = '-Wl -ld_classic '
|
||||
|
||||
projects.each do |project|
|
||||
project.build_configurations.each do |config|
|
||||
# fix for unary_function and binary_function
|
||||
self.safe_init(config, gcc_preprocessor_definition_key)
|
||||
self.add_value_to_setting_if_missing(config, gcc_preprocessor_definition_key, libcpp_cxx17_fix)
|
||||
|
||||
# fix for weak linking
|
||||
self.safe_init(config, other_ld_flags_key)
|
||||
if self.is_using_xcode15_0(:xcodebuild_manager => xcodebuild_manager)
|
||||
self.add_value_to_setting_if_missing(config, other_ld_flags_key, xcode15_compatibility_flags)
|
||||
else
|
||||
self.remove_value_from_setting_if_present(config, other_ld_flags_key, xcode15_compatibility_flags)
|
||||
end
|
||||
end
|
||||
project.save()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def self.apply_flags_for_fabric(installer, fabric_enabled: false)
|
||||
@@ -232,6 +279,37 @@ class ReactNativePodsUtils
|
||||
end
|
||||
end
|
||||
|
||||
def self.updateIphoneOSDeploymentTarget(installer)
|
||||
pod_to_update = Set.new([
|
||||
"boost",
|
||||
"CocoaAsyncSocket",
|
||||
"Flipper",
|
||||
"Flipper-DoubleConversion",
|
||||
"Flipper-Fmt",
|
||||
"Flipper-Boost-iOSX",
|
||||
"Flipper-Folly",
|
||||
"Flipper-Glog",
|
||||
"Flipper-PeerTalk",
|
||||
"FlipperKit",
|
||||
"fmt",
|
||||
"libevent",
|
||||
"OpenSSL-Universal",
|
||||
"RCT-Folly",
|
||||
"SocketRocket",
|
||||
"YogaKit"
|
||||
])
|
||||
|
||||
installer.target_installation_results.pod_target_installation_results
|
||||
.each do |pod_name, target_installation_result|
|
||||
unless pod_to_update.include?(pod_name)
|
||||
next
|
||||
end
|
||||
target_installation_result.native_target.build_configurations.each do |config|
|
||||
config.build_settings["IPHONEOS_DEPLOYMENT_TARGET"] = Helpers::Constants.min_ios_version_supported
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# ========= #
|
||||
# Utilities #
|
||||
# ========= #
|
||||
@@ -243,6 +321,56 @@ class ReactNativePodsUtils
|
||||
.push(installer.pods_project)
|
||||
end
|
||||
|
||||
def self.safe_init(config, setting_name)
|
||||
old_config = config.build_settings[setting_name]
|
||||
if old_config == nil
|
||||
config.build_settings[setting_name] ||= '$(inherited) '
|
||||
end
|
||||
end
|
||||
|
||||
def self.add_value_to_setting_if_missing(config, setting_name, value)
|
||||
old_config = config.build_settings[setting_name]
|
||||
if old_config.is_a?(Array)
|
||||
old_config = old_config.join(" ")
|
||||
end
|
||||
|
||||
trimmed_value = value.strip()
|
||||
if !old_config.include?(trimmed_value)
|
||||
config.build_settings[setting_name] = "#{old_config.strip()} #{trimmed_value}".strip()
|
||||
end
|
||||
end
|
||||
|
||||
def self.remove_value_from_setting_if_present(config, setting_name, value)
|
||||
old_config = config.build_settings[setting_name]
|
||||
if old_config.is_a?(Array)
|
||||
old_config = old_config.join(" ")
|
||||
end
|
||||
|
||||
trimmed_value = value.strip()
|
||||
if old_config.include?(trimmed_value)
|
||||
new_config = old_config.gsub(trimmed_value, "")
|
||||
config.build_settings[setting_name] = new_config.strip()
|
||||
end
|
||||
end
|
||||
|
||||
def self.is_using_xcode15_0(xcodebuild_manager: Xcodebuild)
|
||||
xcodebuild_version = xcodebuild_manager.version
|
||||
|
||||
# The output of xcodebuild -version is something like
|
||||
# Xcode 15.0
|
||||
# or
|
||||
# Xcode 14.3.1
|
||||
# We want to capture the version digits
|
||||
regex = /(\d+)\.(\d+)(?:\.(\d+))?/
|
||||
if match_data = xcodebuild_version.match(regex)
|
||||
major = match_data[1].to_i
|
||||
minor = match_data[2].to_i
|
||||
return major == 15 && minor == 0
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
def self.add_compiler_flag_to_project(installer, flag, configuration: nil)
|
||||
projects = self.extract_projects(installer)
|
||||
|
||||
|
||||
+8
-2
@@ -11,6 +11,7 @@
|
||||
|
||||
const yargs = require('yargs');
|
||||
const fs = require('fs');
|
||||
const p = require('path');
|
||||
|
||||
const CONFIG_FILE_NAME = 'react-native.config.js';
|
||||
const PROJECT_FIELD = 'project';
|
||||
@@ -93,7 +94,11 @@ function extractComponentsNames(reactNativeConfig) {
|
||||
}
|
||||
|
||||
function generateRCTLegacyInteropComponents() {
|
||||
const configFilePath = `${appRoot}/${CONFIG_FILE_NAME}`;
|
||||
const cwd = process.cwd();
|
||||
const configFilePath = p.join(cwd, appRoot, CONFIG_FILE_NAME);
|
||||
console.log(
|
||||
`Looking for a react-native.config.js file at ${configFilePath}...`,
|
||||
);
|
||||
let reactNativeConfig = null;
|
||||
try {
|
||||
reactNativeConfig = require(configFilePath);
|
||||
@@ -107,7 +112,7 @@ function generateRCTLegacyInteropComponents() {
|
||||
console.log('Skip LegacyInterop generation');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`Components found: ${componentNames}`);
|
||||
let componentsArray = componentNames.map(name => `\t\t\t@"${name}",`);
|
||||
// Remove the last comma
|
||||
if (componentsArray.length > 0) {
|
||||
@@ -118,6 +123,7 @@ function generateRCTLegacyInteropComponents() {
|
||||
|
||||
const filePath = `${outputPath}/${OUTPUT_FILE_NAME}`;
|
||||
fs.writeFileSync(filePath, fileBody(componentsArray.join('\n')));
|
||||
console.log(`${filePath} updated!`);
|
||||
}
|
||||
|
||||
generateRCTLegacyInteropComponents();
|
||||
|
||||
@@ -15,6 +15,8 @@ require_relative './cocoapods/codegen_utils.rb'
|
||||
require_relative './cocoapods/utils.rb'
|
||||
require_relative './cocoapods/new_architecture.rb'
|
||||
require_relative './cocoapods/local_podspec_patch.rb'
|
||||
require_relative './cocoapods/helpers.rb'
|
||||
require_relative './cocoapods/privacy_manifest_utils.rb'
|
||||
|
||||
$CODEGEN_OUTPUT_DIR = 'build/generated/ios'
|
||||
$CODEGEN_COMPONENT_DIR = 'react/renderer/components'
|
||||
@@ -34,11 +36,12 @@ require Pod::Executable.execute_command('node', ['-p',
|
||||
{paths: [process.argv[1]]},
|
||||
)', __dir__]).strip
|
||||
|
||||
# This function returns the min iOS version supported by React Native
|
||||
|
||||
# This function returns the min supported OS versions supported by React Native
|
||||
# By using this function, you won't have to manually change your Podfile
|
||||
# when we change the minimum version supported by the framework.
|
||||
def min_ios_version_supported
|
||||
return '12.4'
|
||||
return Helpers::Constants.min_ios_version_supported
|
||||
end
|
||||
|
||||
# This function prepares the project for React Native, before processing
|
||||
@@ -72,7 +75,8 @@ def use_react_native! (
|
||||
flipper_configuration: FlipperConfiguration.disabled,
|
||||
app_path: '..',
|
||||
config_file_dir: '',
|
||||
ios_folder: 'ios'
|
||||
ios_folder: 'ios',
|
||||
privacy_file_aggregation_enabled: true
|
||||
)
|
||||
|
||||
# Set the app_path as env variable so the podspecs can access it.
|
||||
@@ -91,6 +95,7 @@ def use_react_native! (
|
||||
fabric_enabled = fabric_enabled || new_arch_enabled
|
||||
ENV['RCT_FABRIC_ENABLED'] = fabric_enabled ? "1" : "0"
|
||||
ENV['USE_HERMES'] = hermes_enabled ? "1" : "0"
|
||||
ENV['RCT_AGGREGATE_PRIVACY_FILES'] = privacy_file_aggregation_enabled ? "1" : "0"
|
||||
|
||||
prefix = path
|
||||
|
||||
@@ -139,7 +144,7 @@ def use_react_native! (
|
||||
pod 'Yoga', :path => "#{prefix}/ReactCommon/yoga", :modular_headers => true
|
||||
|
||||
pod 'DoubleConversion', :podspec => "#{prefix}/third-party-podspecs/DoubleConversion.podspec"
|
||||
pod 'glog', :podspec => "#{prefix}/third-party-podspecs/glog.podspec", :modular_headers => true
|
||||
pod 'glog', :podspec => "#{prefix}/third-party-podspecs/glog.podspec"
|
||||
pod 'boost', :podspec => "#{prefix}/third-party-podspecs/boost.podspec"
|
||||
pod 'RCT-Folly', :podspec => "#{prefix}/third-party-podspecs/RCT-Folly.podspec", :modular_headers => true
|
||||
|
||||
@@ -236,6 +241,8 @@ def react_native_post_install(
|
||||
if ReactNativePodsUtils.has_pod(installer, 'Flipper')
|
||||
flipper_post_install(installer)
|
||||
end
|
||||
|
||||
privacy_file_aggregation_enabled = ENV['RCT_AGGREGATE_PRIVACY_FILES'] == '1'
|
||||
|
||||
fabric_enabled = ReactNativePodsUtils.has_pod(installer, 'React-Fabric')
|
||||
|
||||
@@ -245,11 +252,20 @@ def react_native_post_install(
|
||||
ReactNativePodsUtils.set_node_modules_user_settings(installer, react_native_path)
|
||||
ReactNativePodsUtils.apply_flags_for_fabric(installer, fabric_enabled: fabric_enabled)
|
||||
ReactNativePodsUtils.apply_xcode_15_patch(installer)
|
||||
ReactNativePodsUtils.updateIphoneOSDeploymentTarget(installer)
|
||||
ReactNativePodsUtils.fix_flipper_for_xcode_15_3(installer)
|
||||
|
||||
if privacy_file_aggregation_enabled
|
||||
PrivacyManifestUtils.add_aggregated_privacy_manifest(installer)
|
||||
else
|
||||
PrivacyManifestUtils.add_privacy_manifest_if_needed(installer)
|
||||
end
|
||||
|
||||
NewArchitectureHelper.set_clang_cxx_language_standard_if_needed(installer)
|
||||
is_new_arch_enabled = ENV['RCT_NEW_ARCH_ENABLED'] == "1"
|
||||
NewArchitectureHelper.modify_flags_for_new_architecture(installer, is_new_arch_enabled)
|
||||
|
||||
|
||||
Pod::UI.puts "Pod install took #{Time.now.to_i - $START_TIME} [s] to run".green
|
||||
end
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
hermes-2023-03-20-RNv0.72.0-49794cfc7c81fb8f69fd60c3bbf85a7480cc5a77
|
||||
hermes-2024-04-29-RNv0.72.14-3815fec63d1a6667ca3195160d6e12fee6a0d8d5
|
||||
@@ -17,7 +17,7 @@ version = package['version']
|
||||
|
||||
# sdks/.hermesversion
|
||||
hermestag_file = File.join(react_native_path, "sdks", ".hermesversion")
|
||||
build_from_source = ENV['BUILD_FROM_SOURCE'] === 'true'
|
||||
build_from_source = ENV['RCT_BUILD_HERMES_FROM_SOURCE'] === 'true'
|
||||
|
||||
git = "https://github.com/facebook/hermes.git"
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ end
|
||||
# - To use a specific tarball, install the dependencies with:
|
||||
# `HERMES_ENGINE_TARBALL_PATH=<path_to_tarball> bundle exec pod install`
|
||||
# - To force a build from source, install the dependencies with:
|
||||
# `BUILD_FROM_SOURCE=true bundle exec pod install`
|
||||
# `RCT_BUILD_HERMES_FROM_SOURCE=true bundle exec pod install`
|
||||
# If none of the two are provided, Cocoapods will check whether there is a tarball for the current version
|
||||
# (either release or nightly). If not, it will fall back building from source (the latest commit on main).
|
||||
#
|
||||
|
||||
@@ -52,13 +52,9 @@ function build_host_hermesc {
|
||||
|
||||
# Utility function to configure an Apple framework
|
||||
function configure_apple_framework {
|
||||
local build_cli_tools enable_bitcode enable_debugger cmake_build_type
|
||||
local build_cli_tools enable_debugger cmake_build_type xcode_15_flags xcode_major_version
|
||||
|
||||
|
||||
if [[ $1 == iphoneos || $1 == catalyst ]]; then
|
||||
enable_bitcode="true"
|
||||
else
|
||||
enable_bitcode="false"
|
||||
fi
|
||||
if [[ $1 == macosx ]]; then
|
||||
build_cli_tools="true"
|
||||
else
|
||||
@@ -77,8 +73,15 @@ function configure_apple_framework {
|
||||
cmake_build_type="MinSizeRel"
|
||||
fi
|
||||
|
||||
xcode_15_flags=""
|
||||
xcode_major_version=$(xcodebuild -version | grep -oE '[0-9]*' | head -n 1)
|
||||
if [[ $xcode_major_version -ge 15 ]]; then
|
||||
xcode_15_flags="LINKER:-ld_classic"
|
||||
fi
|
||||
|
||||
pushd "$HERMES_PATH" > /dev/null || exit 1
|
||||
cmake -S . -B "build_$1" \
|
||||
-DHERMES_EXTRA_LINKER_FLAGS="$xcode_15_flags" \
|
||||
-DHERMES_APPLE_TARGET_PLATFORM:STRING="$1" \
|
||||
-DCMAKE_OSX_ARCHITECTURES:STRING="$2" \
|
||||
-DCMAKE_OSX_DEPLOYMENT_TARGET:STRING="$3" \
|
||||
@@ -87,7 +90,7 @@ function configure_apple_framework {
|
||||
-DHERMES_ENABLE_LIBFUZZER:BOOLEAN=false \
|
||||
-DHERMES_ENABLE_FUZZILLI:BOOLEAN=false \
|
||||
-DHERMES_ENABLE_TEST_SUITE:BOOLEAN=false \
|
||||
-DHERMES_ENABLE_BITCODE:BOOLEAN="$enable_bitcode" \
|
||||
-DHERMES_ENABLE_BITCODE:BOOLEAN=false \
|
||||
-DHERMES_BUILD_APPLE_FRAMEWORK:BOOLEAN=true \
|
||||
-DHERMES_BUILD_APPLE_DSYM:BOOLEAN=true \
|
||||
-DHERMES_ENABLE_TOOLS:BOOLEAN="$build_cli_tools" \
|
||||
|
||||
@@ -33,6 +33,13 @@ if [ -z "$deployment_target" ]; then
|
||||
deployment_target=${MACOSX_DEPLOYMENT_TARGET}
|
||||
fi
|
||||
|
||||
xcode_15_flags=""
|
||||
xcode_major_version=$(xcodebuild -version | grep -oE '[0-9]*' | head -n 1)
|
||||
if [[ $xcode_major_version -ge 15 ]]; then
|
||||
echo "########### Using LINKER:-ld_classic ###########"
|
||||
xcode_15_flags="LINKER:-ld_classic"
|
||||
fi
|
||||
|
||||
architectures=$( echo "$ARCHS" | tr " " ";" )
|
||||
|
||||
echo "Configure Apple framework"
|
||||
@@ -40,6 +47,7 @@ echo "Configure Apple framework"
|
||||
"$CMAKE_BINARY" \
|
||||
-S "${PODS_ROOT}/hermes-engine" \
|
||||
-B "${PODS_ROOT}/hermes-engine/build/${PLATFORM_NAME}" \
|
||||
-DHERMES_EXTRA_LINKER_FLAGS="$xcode_15_flags" \
|
||||
-DHERMES_APPLE_TARGET_PLATFORM:STRING="$PLATFORM_NAME" \
|
||||
-DCMAKE_OSX_ARCHITECTURES:STRING="$architectures" \
|
||||
-DCMAKE_OSX_DEPLOYMENT_TARGET:STRING="$deployment_target" \
|
||||
|
||||
@@ -3,4 +3,7 @@ source 'https://rubygems.org'
|
||||
# You may use http://rbenv.org/ or https://rvm.io/ to install and use this version
|
||||
ruby ">= 2.6.10"
|
||||
|
||||
gem 'cocoapods', '~> 1.12'
|
||||
# Cocoapods 1.15 introduced a bug which break the build. We will remove the upper
|
||||
# bound in the template on Cocoapods with next React Native release.
|
||||
gem 'cocoapods', '>= 1.13', '< 1.15'
|
||||
gem 'activesupport', '>= 6.1.7.3', '< 7.1.0'
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; };
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
||||
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
|
||||
6132EF182BDFF13200BBE14D /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 6132EF172BDFF13200BBE14D /* PrivacyInfo.xcprivacy */; };
|
||||
7699B88040F8A987B510C191 /* libPods-HelloWorld-HelloWorldTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 19F6CBCC0A4E27FBF8BF4A61 /* libPods-HelloWorld-HelloWorldTests.a */; };
|
||||
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
|
||||
/* End PBXBuildFile section */
|
||||
@@ -41,6 +42,7 @@
|
||||
5709B34CF0A7D63546082F79 /* Pods-HelloWorld.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HelloWorld.release.xcconfig"; path = "Target Support Files/Pods-HelloWorld/Pods-HelloWorld.release.xcconfig"; sourceTree = "<group>"; };
|
||||
5B7EB9410499542E8C5724F5 /* Pods-HelloWorld-HelloWorldTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HelloWorld-HelloWorldTests.debug.xcconfig"; path = "Target Support Files/Pods-HelloWorld-HelloWorldTests/Pods-HelloWorld-HelloWorldTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
5DCACB8F33CDC322A6C60F78 /* libPods-HelloWorld.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-HelloWorld.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
6132EF172BDFF13200BBE14D /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = PrivacyInfo.xcprivacy; path = HelloWorld/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
||||
81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = HelloWorld/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
89C6BE57DB24E9ADA2F236DE /* Pods-HelloWorld-HelloWorldTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HelloWorld-HelloWorldTests.release.xcconfig"; path = "Target Support Files/Pods-HelloWorld-HelloWorldTests/Pods-HelloWorld-HelloWorldTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
|
||||
@@ -116,6 +118,7 @@
|
||||
83CBB9F61A601CBA00E9B192 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6132EF172BDFF13200BBE14D /* PrivacyInfo.xcprivacy */,
|
||||
13B07FAE1A68108700A75B9A /* HelloWorld */,
|
||||
832341AE1AAA6A7D00B99B32 /* Libraries */,
|
||||
00E356EF1AD99517003FC87E /* HelloWorldTests */,
|
||||
@@ -242,6 +245,7 @@
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
6132EF182BDFF13200BBE14D /* PrivacyInfo.xcprivacy in Resources */,
|
||||
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */,
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
|
||||
);
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSPrivacyCollectedDataTypes</key>
|
||||
<array>
|
||||
</array>
|
||||
<key>NSPrivacyAccessedAPITypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
|
||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||
<array>
|
||||
<string>C617.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
|
||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||
<array>
|
||||
<string>CA92.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
|
||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||
<array>
|
||||
<string>35F9.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>NSPrivacyTracking</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -11,21 +11,21 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "18.2.0",
|
||||
"react-native": "0.72.2"
|
||||
"react-native": "0.72.17"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.20.0",
|
||||
"@babel/preset-env": "^7.20.0",
|
||||
"@babel/runtime": "^7.20.0",
|
||||
"@react-native/eslint-config": "^0.72.2",
|
||||
"@react-native/metro-config": "^0.72.9",
|
||||
"@react-native/metro-config": "^0.72.12",
|
||||
"@tsconfig/react-native": "^3.0.0",
|
||||
"@types/react": "^18.0.24",
|
||||
"@types/react-test-renderer": "^18.0.0",
|
||||
"babel-jest": "^29.2.1",
|
||||
"eslint": "^8.19.0",
|
||||
"jest": "^29.2.1",
|
||||
"metro-react-native-babel-preset": "0.76.7",
|
||||
"metro-react-native-babel-preset": "^0.76.9",
|
||||
"prettier": "^2.4.1",
|
||||
"react-test-renderer": "18.2.0",
|
||||
"typescript": "4.8.4"
|
||||
|
||||
@@ -10,7 +10,7 @@ Pod::Spec.new do |spec|
|
||||
spec.homepage = 'http://www.boost.org'
|
||||
spec.summary = 'Boost provides free peer-reviewed portable C++ source libraries.'
|
||||
spec.authors = 'Rene Rivera'
|
||||
spec.source = { :http => 'https://boostorg.jfrog.io/artifactory/main/release/1.76.0/source/boost_1_76_0.tar.bz2',
|
||||
spec.source = { :http => 'https://archives.boost.io/release/1.76.0/source/boost_1_76_0.tar.bz2',
|
||||
:sha256 => 'f0397ba6e982c4450f27bf32a2a83292aba035b827a5623a14636ea583318c41' }
|
||||
|
||||
# Pinning to the same version as React.podspec.
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
# Gemfile
|
||||
source 'https://rubygems.org'
|
||||
|
||||
gem 'cocoapods', '~> 1.12'
|
||||
# Cocoapods 1.15 introduced a bug which break the build. We will remove the upper
|
||||
# bound in the template on Cocoapods with next React Native release.
|
||||
gem 'cocoapods', '>= 1.13', '< 1.15'
|
||||
gem 'rexml'
|
||||
gem 'activesupport', '>= 6.1.7.3', '< 7.1.0'
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user