Compare commits

..
Author SHA1 Message Date
Christian Falch f217bce77a [ios][prebuilt] fixed using continue in loop
Instead of returning when creating the list of header files from our podspecs, we now call `continue`. This is a bug that causes all subsequent globs in the header file list to be omitted after the first omitted glob.
2025-07-08 16:38:43 +02:00
Christian Falch e2087457f8 [ios][prebuild] add support for USE_FRAMEWORKS
When using prebuilts the USE_FRAMEWORKS setting is not really relevant for the React Native code, since there will not be any source code to build frameworks for - and because we already have a framework for the code in React.XCFramework.

This commit adds a new command to the React Native podspecs like we did with the ReactNativeDependencies framework. The method is called `add_rncore_dependency` and it does nothing when building from source - but when linking with the React.XCFramework it explicitly adds linking with the framework.

In addition there are a few places in the ruby code where we check for the USE_FRAMEWORK value and changes some settings - where needed this commit will add a separate check to ensure we're building from source when making these changes.

Testing:
- Builds without USE_FRAMEWORKS as before with/without prebuilt
- Builds with USE_FRAMEWORKS=dynamic as before with source - and now also with prebuilt code.
- Same goes for the static variant.
2025-07-08 16:35:14 +02:00
155 changed files with 1604 additions and 3702 deletions
+1 -1
View File
@@ -4,7 +4,7 @@ inputs:
node-version:
description: 'The node.js version to use'
required: false
default: '22.14.0'
default: '22'
runs:
using: "composite"
steps:
@@ -48,14 +48,6 @@ runs:
- name: Print third-party folder
shell: bash
run: ls -lR /tmp/third-party
- name: Download React Native Prebuilds
uses: actions/download-artifact@v4
with:
name: ReactCore${{ inputs.flavor }}.xcframework.tar.gz
path: /tmp/ReactCore
- name: Print ReactCore folder
shell: bash
run: ls -lR /tmp/ReactCore
- name: Install iOS dependencies - Configuration ${{ inputs.flavor }};
shell: bash
run: |
@@ -81,7 +73,6 @@ runs:
TARBALL_FILENAME=$(node ../../packages/react-native/scripts/hermes/get-tarball-name.js --buildType "$BUILD_TYPE")
export HERMES_ENGINE_TARBALL_PATH="$HERMES_WS_DIR/hermes-runtime-darwin/$TARBALL_FILENAME"
export RCT_USE_LOCAL_RN_DEP="/tmp/third-party/ReactNativeDependencies${{ inputs.flavor }}.xcframework.tar.gz"
export RCT_TESTONLY_RNCORE_TARBALL_PATH="/tmp/ReactCore/ReactCore${{ inputs.flavor }}.xcframework.tar.gz"
yarn bootstrap ios "${args[@]}" | cat
+1 -10
View File
@@ -94,14 +94,6 @@ runs:
- name: Print third-party folder
shell: bash
run: ls -lR /tmp/third-party
- name: Download React Native Prebuilds
uses: actions/download-artifact@v4
with:
name: ReactCore${{ inputs.flavor }}.xcframework.tar.gz
path: /tmp/ReactCore
- name: Print ReactCore folder
shell: bash
run: ls -lR /tmp/ReactCore
- name: Setup xcode build cache
uses: ./.github/actions/setup-xcode-build-cache
with:
@@ -113,13 +105,12 @@ runs:
shell: bash
run: |
export HERMES_ENGINE_TARBALL_PATH=$HERMES_ENGINE_TARBALL_PATH
export RCT_USE_LOCAL_RN_DEP="/tmp/third-party/ReactNativeDependencies${{ inputs.flavor }}.xcframework.tar.gz"
export RCT_TESTONLY_RNCORE_TARBALL_PATH="/tmp/ReactCore/ReactCore${{ inputs.flavor }}.xcframework.tar.gz"
if [[ ${{ inputs.use-frameworks }} == "DynamicFrameworks" ]]; then
export USE_FRAMEWORKS=dynamic
fi
export RCT_USE_LOCAL_RN_DEP="/tmp/third-party/ReactNativeDependencies${{ inputs.flavor }}.xcframework.tar.gz"
cd packages/rn-tester
bundle install
-2
View File
@@ -2,8 +2,6 @@ name: yarn-install
runs:
using: composite
steps:
- name: Setup node.js
uses: ./.github/actions/setup-node
- name: Install dependencies
shell: bash
run: |
@@ -38,7 +38,7 @@ describe('#verifyArtifactsAreOnMaven', () => {
expect(mockSleep).toHaveBeenCalledTimes(1);
expect(mockFetch).toHaveBeenCalledWith(
'https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/0.78.1/react-native-artifacts-0.78.1.pom',
'https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/0.78.1',
);
});
@@ -55,7 +55,7 @@ describe('#verifyArtifactsAreOnMaven', () => {
expect(mockSleep).toHaveBeenCalledTimes(1);
expect(mockFetch).toHaveBeenCalledWith(
'https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/0.78.1/react-native-artifacts-0.78.1.pom',
'https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/0.78.1',
);
});
@@ -67,7 +67,7 @@ describe('#verifyArtifactsAreOnMaven', () => {
expect(mockSleep).toHaveBeenCalledTimes(0);
expect(mockFetch).toHaveBeenCalledWith(
'https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/0.78.1/react-native-artifacts-0.78.1.pom',
'https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/0.78.1',
);
});
@@ -81,7 +81,7 @@ describe('#verifyArtifactsAreOnMaven', () => {
expect(mockSleep).toHaveBeenCalledTimes(90);
expect(mockExit).toHaveBeenCalledWith(1);
expect(mockFetch).toHaveBeenCalledWith(
'https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/0.78.1/react-native-artifacts-0.78.1.pom',
'https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/0.78.1',
);
});
});
@@ -13,14 +13,13 @@ const SLEEP_S = 60; // 1 minute
const MAX_RETRIES = 90; // 90 attempts. Waiting between attempt: 1 min. Total time: 90 min.
const ARTIFACT_URL =
'https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/';
const ARTIFACT_NAME = 'react-native-artifacts-';
async function verifyArtifactsAreOnMaven(version, retries = MAX_RETRIES) {
if (version.startsWith('v')) {
version = version.substring(1);
}
const artifactUrl = `${ARTIFACT_URL}${version}/${ARTIFACT_NAME}${version}.pom`;
const artifactUrl = `${ARTIFACT_URL}${version}`;
for (let currentAttempt = 1; currentAttempt <= retries; currentAttempt++) {
const response = await fetch(artifactUrl);
-4
View File
@@ -18,10 +18,6 @@ jobs:
run: |
git config --local user.email "bot@reactnative.dev"
git config --local user.name "React Native Bot"
- name: Setup xcode
uses: ./.github/actions/setup-xcode
with:
xcode-version: '16.2.0'
- name: Extract branch name
run: |
TAG="${{ github.ref_name }}";
+5 -5
View File
@@ -23,7 +23,7 @@ jobs:
id: restore-ios-slice
uses: actions/cache/restore@v4
with:
key: v3-ios-core-${{ matrix.slice }}-${{ matrix.flavor }}-${{ hashFiles('packages/react-native/Package.swift', 'packages/react-native/scripts/ios-prebuild/setup.js', 'packages/react-native/React/**/*', 'packages/react-native/ReactCommon/**/*', 'packages/react-native/Libraries/**/*') }}
key: v3-ios-core-${{ matrix.slice }}-${{ matrix.flavor }}-${{ hashFiles('packages/react-native/Package.swift') }}-${{ hashFiles('packages/react-native/scripts/ios-prebuild/setup.js') }}
path: packages/react-native/
- name: Setup node.js
if: steps.restore-ios-slice.outputs.cache-hit != 'true'
@@ -83,7 +83,7 @@ jobs:
# Move the XCFramework in the destination directory
mv /tmp/third-party/packages/react-native/third-party/ReactNativeDependencies.xcframework packages/react-native/third-party/ReactNativeDependencies.xcframework
VERSION=$(jq -r '.version' packages/react-native/package.json)
VERSION=$(jq -r '.version' package.json)
echo "$VERSION-${{matrix.flavor}}" > "packages/react-native/third-party/version.txt"
cat "packages/react-native/third-party/version.txt"
# Check destination directory
@@ -117,7 +117,7 @@ jobs:
uses: actions/cache/save@v4
if: ${{ github.ref == 'refs/heads/main' }} # To avoid that the cache explode
with:
key: v3-ios-core-${{ matrix.slice }}-${{ matrix.flavor }}-${{ hashFiles('packages/react-native/Package.swift', 'packages/react-native/scripts/ios-prebuild/setup.js', 'packages/react-native/React/**/*', 'packages/react-native/ReactCommon/**/*', 'packages/react-native/Libraries/**/*') }}
key: v3-ios-core-${{ matrix.slice }}-${{ matrix.flavor }}-${{ hashFiles('packages/react-native/Package.swift') }}-${{ hashFiles('packages/react-native/scripts/ios-prebuild/setup.js') }}
path: |
packages/react-native/.build/output/spm/${{ matrix.flavor }}/Build/Products
packages/react-native/.build/headers
@@ -140,7 +140,7 @@ jobs:
uses: actions/cache/restore@v4
with:
path: packages/react-native/.build/output/xcframeworks
key: v2-ios-core-xcframework-${{ matrix.flavor }}-${{ hashFiles('packages/react-native/Package.swift', 'packages/react-native/scripts/ios-prebuild/setup.js', 'packages/react-native/React/**/*', 'packages/react-native/ReactCommon/**/*', 'packages/react-native/Libraries/**/*') }}
key: v2-ios-core-xcframework-${{ matrix.flavor }}-${{ hashFiles('packages/react-native/Package.swift') }}-${{ hashFiles('packages/react-native/scripts/ios-prebuild/setup.js') }}
- name: Setup node.js
if: steps.restore-ios-xcframework.outputs.cache-hit != 'true'
uses: ./.github/actions/setup-node
@@ -209,4 +209,4 @@ jobs:
path: |
packages/react-native/.build/output/xcframeworks/ReactCore${{matrix.flavor}}.xcframework.tar.gz
packages/react-native/.build/output/xcframeworks/ReactCore${{matrix.flavor}}.framework.dSYM.tar.gz
key: v2-ios-core-xcframework-${{ matrix.flavor }}-${{ hashFiles('packages/react-native/Package.swift', 'packages/react-native/scripts/ios-prebuild/setup.js', 'packages/react-native/React/**/*', 'packages/react-native/ReactCommon/**/*', 'packages/react-native/Libraries/**/*') }}
key: v2-ios-core-xcframework-${{ matrix.flavor }}-${{ hashFiles('packages/react-native/Package.swift') }}-${{ hashFiles('packages/react-native/scripts/ios-prebuild/setup.js') }}
+26 -16
View File
@@ -128,7 +128,7 @@ jobs:
test_ios_rntester_ruby_3_2_0:
runs-on: macos-14
needs:
[build_apple_slices_hermes, prepare_hermes_workspace, build_hermes_macos, prebuild_apple_dependencies, prebuild_react_native_core]
[build_apple_slices_hermes, prepare_hermes_workspace, build_hermes_macos, prebuild_apple_dependencies]
env:
HERMES_WS_DIR: /tmp/hermes
HERMES_TARBALL_ARTIFACTS_DIR: /tmp/hermes/hermes-runtime-darwin
@@ -141,12 +141,31 @@ jobs:
ruby-version: "3.2.0"
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
flavor: Debug
test_ios_rntester_dynamic_frameworks:
runs-on: macos-14
needs:
[build_apple_slices_hermes, prepare_hermes_workspace, build_hermes_macos, prebuild_apple_dependencies]
env:
HERMES_WS_DIR: /tmp/hermes
HERMES_TARBALL_ARTIFACTS_DIR: /tmp/hermes/hermes-runtime-darwin
continue-on-error: true
strategy:
fail-fast: false
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Run it
uses: ./.github/actions/test-ios-rntester
with:
use-frameworks: DynamicFrameworks
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
test_ios_rntester:
runs-on: macos-14-large
needs:
[build_apple_slices_hermes, prepare_hermes_workspace, build_hermes_macos, prebuild_apple_dependencies, prebuild_react_native_core]
[build_apple_slices_hermes, prepare_hermes_workspace, build_hermes_macos, prebuild_apple_dependencies]
env:
HERMES_WS_DIR: /tmp/hermes
HERMES_TARBALL_ARTIFACTS_DIR: /tmp/hermes/hermes-runtime-darwin
@@ -155,14 +174,14 @@ jobs:
fail-fast: false
matrix:
flavor: [Debug, Release]
frameworks: [StaticLibraries, DynamicFrameworks]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Run it
uses: ./.github/actions/test-ios-rntester
with:
use-frameworks: ${{ matrix.frameworks }}
run-unit-tests: "false"
use-frameworks: StaticLibraries
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
flavor: ${{ matrix.flavor }}
@@ -245,14 +264,6 @@ jobs:
- name: Print third-party folder
shell: bash
run: ls -lR /tmp/third-party
- name: Download React Native Prebuilds
uses: actions/download-artifact@v4
with:
name: ReactCore${{ matrix.flavor }}.xcframework.tar.gz
path: /tmp/ReactCore
- name: Print ReactCore folder
shell: bash
run: ls -lR /tmp/ReactCore
- name: Prepare artifacts
run: |
REACT_NATIVE_PKG=$(find /tmp/react-native-tmp -type f -name "*.tgz")
@@ -275,7 +286,6 @@ jobs:
NEW_ARCH_ENABLED=1
export RCT_USE_LOCAL_RN_DEP=/tmp/third-party/ReactNativeDependencies${{ matrix.flavor }}.xcframework.tar.gz
export RCT_TESTONLY_RNCORE_TARBALL_PATH="/tmp/ReactCore/ReactCore${{ matrix.flavor }}.xcframework.tar.gz"
HERMES_ENGINE_TARBALL_PATH=$HERMES_PATH RCT_NEW_ARCH_ENABLED=$NEW_ARCH_ENABLED bundle exec pod install
xcodebuild \
@@ -538,7 +548,7 @@ jobs:
test_ios_helloworld_with_ruby_3_2_0:
runs-on: macos-14
needs: [prepare_hermes_workspace, build_hermes_macos, prebuild_apple_dependencies, prebuild_react_native_core] # prepare_hermes_workspace must be there because we need its reference to retrieve a couple of outputs
needs: [prepare_hermes_workspace, build_hermes_macos, prebuild_apple_dependencies] # prepare_hermes_workspace must be there because we need its reference to retrieve a couple of outputs
env:
PROJECT_NAME: iOSTemplateProject
HERMES_WS_DIR: /tmp/hermes
@@ -555,7 +565,7 @@ jobs:
test_ios_helloworld:
runs-on: macos-14
needs: [prepare_hermes_workspace, build_hermes_macos, prebuild_apple_dependencies, prebuild_react_native_core] # prepare_hermes_workspace must be there because we need its reference to retrieve a couple of outputs
needs: [prepare_hermes_workspace, build_hermes_macos, prebuild_apple_dependencies] # prepare_hermes_workspace must be there because we need its reference to retrieve a couple of outputs
strategy:
matrix:
flavor: [Debug, Release]
-25
View File
@@ -319,31 +319,6 @@ ChuiHW))
- **JSC:** Clean up RCTBridgeDelegate to remove shouldBridgeUseCustomJSC method ([c8f1506f13](https://github.com/facebook/react-native/commit/c8f1506f13310ffafe370273805684e696d72d50) by [@zhongwuzw](https://github.com/zhongwuzw))
- **Layout:** Remove no longer needed UISceneDelegate ([a033cf9d5e](https://github.com/facebook/react-native/commit/a033cf9d5e8ffbda8b6f86cf3ce152b4ccb73187) by [@okwasniewski](https://github.com/okwasniewski))
## v0.78.3
### Added
#### Android specific
- **Gradle:** RNGP - Add support for `exclusiveEnterpriseRepository` to specify an internal Maven mirror. ([6cb8dc37c7](https://github.com/facebook/react-native/commit/6cb8dc37c74995cba3f9f0a845919f305de53c3d) by [@cortinico](https://github.com/cortinico))
### Fixed
- **DevTools**: Temporarily disable eager evaluation and live expressions in the console tab ([07717b5275](https://github.com/facebook/react-native/commit/07717b5275d80cde7b2b4edbe032ab629127fbf0) by [@huntie](https://github.com/huntie))
- **InteropLayer:** Fixed adding child views to a native view using the interop layer ([d53a60dd23](https://github.com/facebook/react-native/commit/d53a60dd23c5df8afca058a867c50df8b61f62e2) by [@chrfalch](https://github.com/chrfalch))
- **Runtime:** Align timer IDs and timer function argument error handling with web standards. ([480a4642e5](https://github.com/facebook/react-native/commit/480a4642e5a644becf1c477d3d239f9b57efff3a) by [@kitten](https://github.com/kitten))
#### Android specific
- **StyleSheet:** Wrong `borderBottomEndRadius` on RTL ([68d6ada448](https://github.com/facebook/react-native/commit/68d6ada44893701b6006a6b1753131c7e880a30a) by [@riteshshukla04](https://github.com/riteshshukla04))
#### iOS specific
- **Codegen:** Skip codegen for selectively disabled libraries in react-native.config.js ([be8595b18a](https://github.com/facebook/react-native/commit/be8595b18a46635bf679d8e7473f2960c33530fa) by [@ismarbesic](https://github.com/ismarbesic))
- **Layout:** Layout direction changes are now honored on bundle reload ([36f29beac4](https://github.com/facebook/react-native/commit/36f29beac47259768612bf56e5d9acfa4b94ab1a) by [@chrsmys](https://github.com/chrsmys))
- **Runtime:** Re-enable enableFixForViewCommandRace feature flag ([ae59702f8e](https://github.com/facebook/react-native/commit/ae59702f8ee89e7bddec971e0a041744cb91e65c) by [@okwasniewski](https://github.com/okwasniewski))
- **Switch:** Fixed switches correctly reverting to controlled state ([aa8c072870](https://github.com/facebook/react-native/commit/aa8c072870f6f9740e567a0f455c0e500ff1400c) by [@javache](https://github.com/javache))
## v0.78.2
### Changed
-192
View File
@@ -1,193 +1,5 @@
# Changelog
## v0.81.0-rc.0
### Breaking
- **APIs:** All `react-native/Libraries/BugReporting` APIs have been removed ([9d4d8dcb02](https://github.com/facebook/react-native/commit/9d4d8dcb0264273cc1522ed6e9de47cdb05606f4) by [@huntie](https://github.com/huntie))
- **APIs:** Add public JS API breaking change detection under `yarn diff-api-snapshot` script. ([6b40f35032](https://github.com/facebook/react-native/commit/6b40f35032462de8a9bad0e9f186916562475a40) by [@coado](https://github.com/coado))
- **APIs:** Community CLI users: user-defined `resolver.resolveRequest` and `serializer.getModulesRunBeforeMainModule` Metro config now takes precedence over CLI defaults ([fe2bcbf4ba](https://github.com/facebook/react-native/commit/fe2bcbf4ba7ce983fac0cd09727c165517b6337f) by [@robhogan](https://github.com/robhogan))
- **Error Handling:** Improve messaging and add error stack trace for uncaught throws. ([5ba0e1f97a](https://github.com/facebook/react-native/commit/5ba0e1f97ad40f84d83efaa9cfdbaf9ad22a18e8) by [@vzaidman](https://github.com/vzaidman))
- **Flow:** The `react-native` package no longer ships with the `flow` directory ([38acb4c074](https://github.com/facebook/react-native/commit/38acb4c0746e48ebb10729360788e26454736d1b) by [@huntie](https://github.com/huntie))
- **Node:** Minimum Node version is now bumped to Node.js 22.14.0 ([df39eadc03](https://github.com/facebook/react-native/commit/df39eadc03edcd23fab47712d24818d2d0c75d16) by [@huntie](https://github.com/huntie))
- **View:** `View` no longer sets any default accessibility props, which should not result in visible changes in behaviour but may affect snapshot tests. ([039a333df5](https://github.com/facebook/react-native/commit/039a333df57e20133af3ec77e995ec8fe4dc7f5c) by [@javache](https://github.com/javache))
- **View:** Upgrade `View` component to React 19. ([eedd60b9e6](https://github.com/facebook/react-native/commit/eedd60b9e6b595801d05c2fa223124fb8a895c3c) by [@EvanBacon](https://github.com/EvanBacon))
#### Android specific
- **APIs:** Cleanup and internalize `FpsDebugFrameCallback` ([cf6569bc18](https://github.com/facebook/react-native/commit/cf6569bc18082253fa84feecdfaa7a28413bc993) by [@cortinico](https://github.com/cortinico))
- **CMake:** Correctly propagate `RN_SERIALIZABLE_STATE` to 3rd party `CMake` targets. Users with custom `CMake` and C++ code should update to use `target_compile_reactnative_options` inside their `CMakeLists.txt` files.([c059ae1b77](https://github.com/facebook/react-native/commit/c059ae1b77b073e6990dc2a5d81979de679c2b01) by [@cortinico](https://github.com/cortinico))
- **FabricUIManager:** Remove `FabricUIManager.measure` overload which accepts attachment positions ([2ba86caf18](https://github.com/facebook/react-native/commit/2ba86caf18d86f6902f987ec9a0aa94bf67c1b4e) by [@NickGerleman](https://github.com/NickGerleman))
- **Kotlin:** Migrate `ViewManagerInterfaces` to kotlin. Some types in code generated ViewManagerInterfaces might differ. e.g. this will start enforcing nullability in parameters of viewManagerInterface methods (e.g. String commands parameters are not nullable, view params are not nullable in any method, etc) ([76ff1aa5c6](https://github.com/facebook/react-native/commit/76ff1aa5c6d30935ec33708d3a13ac7e5a82f551) by [@mdvacca](https://github.com/mdvacca))
- **Kotlin:** Migrate `com.facebook.react.ReactDelegate` to Kotlin. Some users implementing this class in Kotlin could have breakages. ([50ea5b4380](https://github.com/facebook/react-native/commit/50ea5b43806a9047bace81267c97d5dd73e0e74d) by [@mateoguzmana](https://github.com/mateoguzmana))
- **Kotlin:** Convert to Kotlin and internalize `MountingManager` ([f33fdca876](https://github.com/facebook/react-native/commit/f33fdca87679d5cc628a2e9dccada728cbb0335b) by [@cortinico](https://github.com/cortinico))
- **textAlignVertical:** Move `textAlignVertical` to paragraph attributes instead of text attributes ([55fd8b26f8](https://github.com/facebook/react-native/commit/55fd8b26f8791848dd886bd7fb5110b401038234) by [@joevilches](https://github.com/joevilches))
- **TextLayoutManager:** Make Java Side `TextLayoutManager` Internal ([e82a677c79](https://github.com/facebook/react-native/commit/e82a677c7966209b05fe55209fcb26c067427393) by [@NickGerleman](https://github.com/NickGerleman))
#### iOS specific
- **RCTDisplayLink:** Migrate `RCTDisplayLink`'s API from `RCTModuleData` ([70eeb9f541](https://github.com/facebook/react-native/commit/70eeb9f54194cc807017bec8c71080972c5c4e65) by [@RSNara](https://github.com/RSNara))
- **SynchronouslyUpdateViewOnUIThread:** `SynchronouslyUpdateViewOnUIThread` now accepts `folly::dynamic` instead of `NSDictionary`. Use https://github.com/facebook/react-native/blob/main/packages/react-native/ReactCommon/react/utils/platform/ios/react/utils/FollyConvert.h#L14 for conversion. ([82279bd981](https://github.com/facebook/react-native/commit/82279bd9811c406d21496d03a1572b98946c50b6) by [@sammy-SC](https://github.com/sammy-SC))
- **Xcode:** Bump min Xcode to 16.1 ([c27a8804a6](https://github.com/facebook/react-native/commit/c27a8804a6fdaea2d4bef4a4c689bfe2c343daaa) by [@NickGerleman](https://github.com/NickGerleman))
### Added
- **APIs:** Expose `unstable_TextAncestorContext` API ([962a7dda44](https://github.com/facebook/react-native/commit/962a7dda440863e7888fd2cc01c065c8762857e6) by [@huntie](https://github.com/huntie))
- **APIs:** Expose additional `*AnimationConfig` types on the `Animated` namespace ([11a1ad7a98](https://github.com/facebook/react-native/commit/11a1ad7a98a71cd1189550a8ae5666e5a2ed8d57) by [@huntie](https://github.com/huntie))
- **APIs:** `InterpolationConfig` is now exposed on the `Animated` namespace ([b01a5f91fe](https://github.com/facebook/react-native/commit/b01a5f91fedc19495e8a9d6ce079feb5898e7b87) by [@huntie](https://github.com/huntie))
- **APIs:** Expose `ScrollViewImperativeMethods` and `ScrollViewScrollToOptions` types to public API ([f184b591cf](https://github.com/facebook/react-native/commit/f184b591cfb49ed372efb0bdd55a145230112f45) by Antonio Pires)
- **APIs:** Add `--validate` flag to `build-types` script for JS API snapshot validation. ([f529fd6ba5](https://github.com/facebook/react-native/commit/f529fd6ba590101a3dfa710a92befb81994ed2dd) by [@coado](https://github.com/coado))
- **Bridging:** Added support for bridging `Class` methods return types ([e403b510d0](https://github.com/facebook/react-native/commit/e403b510d0de74ac7e62defeb1e80eff84b956e2) by [@hoxyq](https://github.com/hoxyq))
- **Error Handling:** Improve error messages when enum members are missing ([12ced22f70](https://github.com/facebook/react-native/commit/12ced22f70438064bf815c2413cbd12a80dbf0a7) by Yannick Loriot)
- **Fantom:** Add `Fantom.getFabricUpdateProps` for reading fabric update props scheduled via `UIManager::updateShadowTree` ([cc442eb8c8](https://github.com/facebook/react-native/commit/cc442eb8c85d516701f840046d73683a7cd51424) by [@zeyap](https://github.com/zeyap))
- **Flow:** Add support for Flow opaque types in codegen for native modules ([a15fc102e6](https://github.com/facebook/react-native/commit/a15fc102e63eb3b37852ca45fe4c65e894ecef7d) by [@rubennorte](https://github.com/rubennorte))
- **HMR:** Process HMR `registerBundle` calls from the same origin only ([a9007ea586](https://github.com/facebook/react-native/commit/a9007ea586f6e87db47c6305be3232d760abfd57) by [@jbroma](https://github.com/jbroma))
- **IntersectionObserver:** `IntersectionObserver` support for `root` with fixes for viewport offsets ([c5b6716311](https://github.com/facebook/react-native/commit/c5b67163117e13c99a9c57816f0ff36efc80ccf5) by [@lunaleaps](https://github.com/lunaleaps))
- **ReactNativeFeatureFlags:** Allow Custom ReactNativeFeatureFlags for Shell 2.0 ([bbc1e121c7](https://github.com/facebook/react-native/commit/bbc1e121c71d14803d29a931f642bf8ea6ee2023) by Maddie Lord)
- **ScrollView:** Added more Pending Decleration for `ScrollView` ([a6908ad1a5](https://github.com/facebook/react-native/commit/a6908ad1a5d998505b2bb6ba3e39910fee17329a) by [@riteshshukla04](https://github.com/riteshshukla04))
- **ShadowNode:** Added `cloneMultiple` to `ShadowNode` class. ([1161fb4fcd](https://github.com/facebook/react-native/commit/1161fb4fcd6a0cac3a691de1f37cc7f9d6a861a5) by [@bartlomiejbloniarz](https://github.com/bartlomiejbloniarz))
- **Typescript:** Add `pressRetentionOffset` prop to be recognised by typescript in `Text.d.ts` ([d94f4d8c9d](https://github.com/facebook/react-native/commit/d94f4d8c9deef78c0345a7fd3de74424f864c080) by [@iamAbhi-916](https://github.com/iamAbhi-916))
- **URLSearchParams:** Added size property to `URLSearchParams` implementation ([9b1a8ffac4](https://github.com/facebook/react-native/commit/9b1a8ffac4368b9304939359917c7cfd0a9501bf) by [@louix](https://github.com/louix))
#### Android specific
- **BaseViewManager:** Adds support for `onFocus` / `onBlur` event dispatching logic to all native views that implement `BaseViewManager` ([e960a28af7](https://github.com/facebook/react-native/commit/e960a28af7f4541dcf67d3c7148b2d32a39e1b04) by [@Abbondanzo](https://github.com/Abbondanzo))
- **Edge To Edge:** Add Android edge-to-edge opt-in support ([09ef774ff6](https://github.com/facebook/react-native/commit/09ef774ff6dac10a00a8b35670f9b3941d810dfb) by [@zoontek](https://github.com/zoontek))
- **RNGP:** `RNGP`- Add support for `exclusiveEnterpriseRepository` to specify an internal Maven mirror. ([6cb8dc37c7](https://github.com/facebook/react-native/commit/6cb8dc37c74995cba3f9f0a845919f305de53c3d) by [@cortinico](https://github.com/cortinico))
- **RNTester:** Added explicit build tool version to `RNTester` `build.gradle` to avoid automatic installation of Android SDK Build Tools. ([35dba09724](https://github.com/facebook/react-native/commit/35dba097243ff2d21466f860ec9831e1ff2a97ac) by [@mojavad](https://github.com/mojavad))
- **ScrollView:** Allow `fadingEdgeLength` to be set independently on the start and end of the `ScrollView` ([a21a4b87c3](https://github.com/facebook/react-native/commit/a21a4b87c337f3f2d998a30841430f587c066580) by Mark Verlingieri)
- **View:** Support for `onFocus` and `onBlur` function calls in `View` components ([af0a76cf5f](https://github.com/facebook/react-native/commit/af0a76cf5fdb8107294dff2c9aa0dbc36c7d5443) by [@Abbondanzo](https://github.com/Abbondanzo))
#### iOS specific
- **borderWidth:** Add support for different `borderWidth`s ([70962ef3ed](https://github.com/facebook/react-native/commit/70962ef3ed06a76a96cb2e72c374dc028628c829) by [@a-klotz-p8](https://github.com/a-klotz-p8))
- **Modal:** Allow to interactively swipe down `Modal`s. ([28986a7599](https://github.com/facebook/react-native/commit/28986a7599952a77b8b8e433f72ca837afde310e) by [@okwasniewski](https://github.com/okwasniewski))
- **Package.swift:** Added missing search path to `Package.swift` ([592b09781b](https://github.com/facebook/react-native/commit/592b09781bb94fe6dc00ba49c7a86649980fed5d) by [@chrfalch](https://github.com/chrfalch))
- **Prebuild:** Add more logging around `computeNightlyTarballURL` in ios pre-build ([1a6887bd70](https://github.com/facebook/react-native/commit/1a6887bd70cdefb8fbc421467de841ece74d5c6b) by [@cortinico](https://github.com/cortinico))
- **Prebuild:** Added backwards compatible use of prebuild through cocoapods ([d8e00f0bb1](https://github.com/facebook/react-native/commit/d8e00f0bb1940fc9cc7e5cbb68b26c2d05824486) by [@chrfalch](https://github.com/chrfalch))
- **Prebuild:** Ship the `React-Core-prebuilt.podspec` in `package.json` ([46b562b9b3](https://github.com/facebook/react-native/commit/46b562b9b3bf4c0b8c5af25ab84a43509979c4a7) by [@cipolleschi](https://github.com/cipolleschi))
- **Prebuild:** Added support for using prebuilt `RNCore` with Cocoapods ([90654e4ba2](https://github.com/facebook/react-native/commit/90654e4ba2f3cc2f6b0d8f08769ce58b4e5d1b51) by [@chrfalch](https://github.com/chrfalch))
- **Prebuild:** Add `React-Core-prebuild.podspec` to integrate React native core prebuilds using Cocoapods ([1a86ee17fb](https://github.com/facebook/react-native/commit/1a86ee17fb80cfa1b8bcff30f4f3d5cdb193900d) by [@chrfalch](https://github.com/chrfalch))
- **Prebuild:** Added building `XCFframework` from the prebuild script ([55534f518a](https://github.com/facebook/react-native/commit/55534f518aab53bcdc3fe12d987ab7ef6e620c77) by [@chrfalch](https://github.com/chrfalch))
- **Prebuild:** Added building swift package from the prebuild script ([3c01b1b6f0](https://github.com/facebook/react-native/commit/3c01b1b6f04d285c97bb182131135903b0c1cdd5) by [@chrfalch](https://github.com/chrfalch))
- **Prebuild:** Added downloading of hermes artifacts when pre-building for iOS. ([41d2b5de0a](https://github.com/facebook/react-native/commit/41d2b5de0af21c72227ef030dcddf208e2eb221a) by [@chrfalch](https://github.com/chrfalch))
- **runtime:** Added `HERMES_ENABLE_DEBUGGER` to debug configuration for the `reactRuntime` target. ([560ac23001](https://github.com/facebook/react-native/commit/560ac23001b02f19d4c6ca4ea493c17060cfaf5f) by [@chrfalch](https://github.com/chrfalch))
### Changed
- **Animated:** Animated now always flattens `props.style`, which fixes an error that results from `props.style` objects in which `AnimatedNode` instances are shadowed (i.e. flattened to not exist in the resulting `props.style` object). ([da520848c9](https://github.com/facebook/react-native/commit/da520848c931f356d013623c412af11dce7ff114) by [@yungsters](https://github.com/yungsters))
- **Animated:** Creates a feature flag that changes `Animated` to no longer produce invalid `props.style` if every `AnimatedNode` instance is shadowed via style flattening. ([5c8c5388fc](https://github.com/facebook/react-native/commit/5c8c5388fc53ef2430b0bb6bbbc628479819e23d) by [@yungsters](https://github.com/yungsters))
- **Animated:** Enabled a feature flag that optimizes `Animated` to reduce memory usage. ([2a13d20085](https://github.com/facebook/react-native/commit/2a13d200850e4f161a29b252a0ccedc158e53937) by [@yungsters](https://github.com/yungsters))
- **Error handling:** Errors will no longer have the "js engine" suffix. ([a293925280](https://github.com/facebook/react-native/commit/a2939252803d5cd4b68340da08820174c30a53e6) by [@yungsters](https://github.com/yungsters))
- **Fibers:** Reduces memory usage, by improving memory management of parent alternate fibers. (Previously, a parent fiber might retain memory associated with shadow nodes from a previous commit.) ([0411c43b3a](https://github.com/facebook/react-native/commit/0411c43b3a239384c778baad22c7b4c501008449) by [@yungsters](https://github.com/yungsters))
- **infoLog:** Removed `infoLog` from `react-native` package ([8a0cfec815](https://github.com/facebook/react-native/commit/8a0cfec81584e966c9e6ea0f5e438022e0129bcd) by [@coado](https://github.com/coado))
- **IntersectionObserver:** Fixed `IntersectionObserver#observe` to avoid retaining memory for unmounted child nodes of observed views. ([d945c5863a](https://github.com/facebook/react-native/commit/d945c5863a5ed7b755e577bc25d681bfcc1c401b) by [@yungsters](https://github.com/yungsters))
- **Jest:** Improved default mocking for Jest unit tests. ([1fd9508ecc](https://github.com/facebook/react-native/commit/1fd9508ecc499df89b086e0c46035f43f6f78ad9) by [@yungsters](https://github.com/yungsters))
- **LegacyArchitecture:** Raise loglevel for assertion of `LegacyArchitecture` classes ([38a4b62211](https://github.com/facebook/react-native/commit/38a4b6221164d36eb4ac95c9f3bc7f7e7235e383) by [@mdvacca](https://github.com/mdvacca))
- **LegacyArchitecture:** Raise logLevel of `LegacyArchitecture` classes when minimizing of legacy architecture is enabled ([0d1cde7f36](https://github.com/facebook/react-native/commit/0d1cde7f36e9de72c997fc812bba023694c2a369) by [@mdvacca](https://github.com/mdvacca))
- **Metro:** Bump Metro to `^0.82.5` ([083644647e](https://github.com/facebook/react-native/commit/083644647eff502f484b3ba24f9d361d5df56546) by [@robhogan](https://github.com/robhogan))
- **React DevTools:** Bumped React DevTools to `6.1.5` ([c302902b1d](https://github.com/facebook/react-native/commit/c302902b1db7e8f8ac5b61472c095dc0755d6d1c) by [@hoxyq](https://github.com/hoxyq))
- **RuntimeExecutor:** `RuntimeExecutor`: Remove noexcept from sync ui thread utils ([7ef278af50](https://github.com/facebook/react-native/commit/7ef278af505deba6b8a47876c6824f9a7fefa427) by [@RSNara](https://github.com/RSNara))
- **Typescript:** Bump `types/react` to `19.1` ([3ae9328571](https://github.com/facebook/react-native/commit/3ae932857174e9c39cd5d9c53922f849aa1401b1) by [@gabrieldonadel](https://github.com/gabrieldonadel))
#### Android specific
- **APIs:** Deprecate `DefaultNewArchitectureEntryPoint.load(Boolean, Boolean, Boolean)` ([efdf73983c](https://github.com/facebook/react-native/commit/efdf73983cef1f371511b6e1efa5e01835ebcabb) by [@cortinico](https://github.com/cortinico))
- **APIs:** Make `com.facebook.react.views.common.ContextUtils` internal ([d1ef8f1fa3](https://github.com/facebook/react-native/commit/d1ef8f1fa36cbfc34d05c409abf693e4e1cac3de) by [@cortinico](https://github.com/cortinico))
- **deps:** Bump `AGP` to `8.11.0` ([04858ecbab](https://github.com/facebook/react-native/commit/04858ecbab808ddca80e20e76f1359619bb5e865) by [@cortinico](https://github.com/cortinico))
- **deps:** Bump `Gradle` to `8.14.2` ([e20bb56f3b](https://github.com/facebook/react-native/commit/e20bb56f3b4db0d3e69154b95b952b1fe8e29959) by [@cortinico](https://github.com/cortinico))
- **JS FPS:** Hide JS FPS on performance overlay as not accurate ([feec8d0148](https://github.com/facebook/react-native/commit/feec8d014877b2177f1c7dded7eb9664f53ee471) by [@cortinico](https://github.com/cortinico))
- Updated targetSdk to 36 in Android. ([477d8df312](https://github.com/facebook/react-native/commit/477d8df3126b325b8cc9b410f1eaeb56b727d4d9) by [@kikoso](https://github.com/kikoso))
- **Kotlin:** Convert `UIManagerModuleConstantsHelper` to Kotlin ([45fd7feb9f](https://github.com/facebook/react-native/commit/45fd7feb9f083e5c8afc916732aed9795d344e09) by [@cortinico](https://github.com/cortinico))
- **Kotlin:** Migrate `ThemedReactContext` to Kotlin ([78c9671c24](https://github.com/facebook/react-native/commit/78c9671c241a86bedb17862e549842b7e36d77ea) by [@cortinico](https://github.com/cortinico))
- **Kotlin:** Convert `ReactViewGroup` to Kotlin ([48395d346b](https://github.com/facebook/react-native/commit/48395d346bc89f63d38889e58508304df0088e4f) by [@cortinico](https://github.com/cortinico))
- **Kotlin:** Migrate `com.facebook.react.LazyReactPackage` to Kotlin. ([b4ae5c1de1](https://github.com/facebook/react-native/commit/b4ae5c1de1003c343d43c3be1b59ee2b800b9258) by [@Xintre](https://github.com/Xintre))
- **Kotlin:** Apply Collections Kotlin DSL helpers in `ReactAndroid` package ([b2ffd34a39](https://github.com/facebook/react-native/commit/b2ffd34a392de2bddba5ee13248796ccc2db6039) by [@l2hyunwoo](https://github.com/l2hyunwoo))
#### iOS specific
- **Accessibility:** Only generate recursive accessibility label for accessible elements ([7e2f17ffe2](https://github.com/facebook/react-native/commit/7e2f17ffe229e09288deba9061221835300ec153) by [@janicduplessis](https://github.com/janicduplessis))
- **GC:** Hermes GC is now triggered in response to iOS memory pressure warning. ([12b2b56102](https://github.com/facebook/react-native/commit/12b2b5610263cb145d1ade8eaf06d8a6e015b10e) by [@yungsters](https://github.com/yungsters))
- **Gradients:** Optimised Radial Gradients. ([f238b74658](https://github.com/facebook/react-native/commit/f238b74658fd155366d4909872ab06781403f31d) by [@intergalacticspacehighway](https://github.com/intergalacticspacehighway))
- **Gradients:** Optimised Linear Gradients. ([2f3b104224](https://github.com/facebook/react-native/commit/2f3b1042249411e84f9a1d5bb1191461cd2dc5ee) by [@intergalacticspacehighway](https://github.com/intergalacticspacehighway))
- **Prebuild:** Simplified logging in prebuild scripts ([1477cc0dbd](https://github.com/facebook/react-native/commit/1477cc0dbdee4b50fee4b1b98346812868148aa5) by [@chrfalch](https://github.com/chrfalch))
- **Prebuild:** Fail fast when pod install if using prebuild and frameworks are not present in the disk. ([60c01b4715](https://github.com/facebook/react-native/commit/60c01b4715053bccbeca2673ff1be1fca60bce9b) by [@chrfalch](https://github.com/chrfalch))
- **Prebuild:** Update `ReactCodegen` to support Core prebuilds ([152cb538f6](https://github.com/facebook/react-native/commit/152cb538f69cd07422526802defe3f3617302098) by [@chrfalch](https://github.com/chrfalch))
### Deprecated
- **hasTVPreferredFocus:** Deprecate `hasTVPreferredFocus` ([cfb6c968dd](https://github.com/facebook/react-native/commit/cfb6c968ddce56138553a9d2e0cc8dfc666eb943) by [@Abbondanzo](https://github.com/Abbondanzo))
- **SafeAreaView:** Deprecate `SafeAreaView` due to its iOS-only support and incompatibility with Android 15 edge-to-edge behavior; recommend using `react-native-safe-area-context` instead. ([73133a31d5](https://github.com/facebook/react-native/commit/73133a31d5a47e71edd4e6b798184df8045e2234) by [@kikoso](https://github.com/kikoso))
- **ShadowNode:** `ShadowNode::Shared` is now deprecated. Use `std::shared_ptr<const ShadowNode>` instead. ([0e175ce5b6](https://github.com/facebook/react-native/commit/0e175ce5b6c80a21237f5cd0f20c9876fa975935) by [@sammy-SC](https://github.com/sammy-SC))
- **ShadowNode:** Deprecate type aliases `ShadowNode::Unshared` and `ShadowNode::Weak` in favour of `std::shared_ptr<ShadowNode>` and `std::weak_ptr<ShadowNode>` ([12fb101e30](https://github.com/facebook/react-native/commit/12fb101e306778b6e5399b23f822cc0874a5c386) by [@sammy-SC](https://github.com/sammy-SC))
#### iOS specific
- **RCTFollyConvert:** `RCTFollyConvert.h` is deprecated please use `/ReactCommon/react/utils/platform/ios/react/utils/FollyConvert.h` instead ([685a60e6b4](https://github.com/facebook/react-native/commit/685a60e6b44018531abf47f98fd38d9c75f6aca6) by [@sammy-SC](https://github.com/sammy-SC))
### Removed
- **Yoga:** Remove `YogaLayoutableShadowNode::cleanLayout()` and Fix `ParagraphShadowNode` Font Size Invalidation Logic ([7979c7ce06](https://github.com/facebook/react-native/commit/7979c7ce0664bf019e17781e95a74baf95ec89f1) by [@NickGerleman](https://github.com/NickGerleman))
#### Android specific
- **APIs:** Internalize `NetworkingModule`'s `UriHandler`, `RequestBodyHandler`, and `ResponseHandler` APIs ([987e3f8c00](https://github.com/facebook/react-native/commit/987e3f8c0031affe89218675061eca3a4620e0cd) by [@huntie](https://github.com/huntie))
- **DeveloperSettings:** Remove deprecated `isStartSamplingProfilerOnInit` from `DeveloperSettings` ([ccb9edc717](https://github.com/facebook/react-native/commit/ccb9edc7179ec1b568038408118971c2ee4c1b27) by [@cortinico](https://github.com/cortinico))
- **JSC:** Remove 1st party JSC support ([8174d02811](https://github.com/facebook/react-native/commit/8174d028116f00b6e89968d368b719ec8b7f6ff6) by [@cortinico](https://github.com/cortinico))
- **JSEngineResolutionAlgorithm:** Remove and cleanup `JSEngineResolutionAlgorithm` ([0954c1db45](https://github.com/facebook/react-native/commit/0954c1db45511d1a640deb8d921d26457bb3777c) by [@cortinico](https://github.com/cortinico))
#### iOS specific
- **JSC:** Remove code from jsc folder from React Native ([331fab0683](https://github.com/facebook/react-native/commit/331fab068355a3ba78776fbdf7e75ff4af3b740f) by [@cipolleschi](https://github.com/cipolleschi))
- **JSC:** Remove the option to use JSC from core ([a6ea626255](https://github.com/facebook/react-native/commit/a6ea6262555e7a25e27934f33099e95cb45c8077) by [@cipolleschi](https://github.com/cipolleschi))
- **Turbo Modules** Disable Turbo Modules fix for #51103 (dictionary stripped out when value is null) until more testing can be done. ([ca5f4d1721](https://github.com/facebook/react-native/commit/ca5f4d1721878ccd81ddcb9267f30160c6d17dd4) by [@javache](https://github.com/javache))
### Fixed
- **APIs:** Renamed argument names in the `onContentSizeChange` callback's type definition ([0386b9bd51](https://github.com/facebook/react-native/commit/0386b9bd5144b785af51c96ea6bada5c55127e98) by [@pchalupa](https://github.com/pchalupa))
- **BindingsInstallerHolder:** Fixed deprecation message for `BindingsInstallerHolder` ([4a8fda83e3](https://github.com/facebook/react-native/commit/4a8fda83e3d0f8aa0e5ac0c427c30fd9170ad375) by [@tomekzaw](https://github.com/tomekzaw))
- **C++:** Add `default:` case to avoid warnings/errors for targets that compile with `-Wswitch-enum` and `-Wswitch-default` enabled ([22b8b53c77](https://github.com/facebook/react-native/commit/22b8b53c77cb2fe87aa54be92d1758a603b7dd35) by [@NSProgrammer](https://github.com/NSProgrammer))
- **C++:** Add `default:` case to avoid warnings/errors for targets that compile with `-Wswitch-enum` and `-Wswitch-default` enabled ([9079b53c6f](https://github.com/facebook/react-native/commit/9079b53c6fa4ec9494f22390a89d1d42b77108a8) by [@NSProgrammer](https://github.com/NSProgrammer))
- **C++:** Fix clang tidy for react-native ([3e49d17f58](https://github.com/facebook/react-native/commit/3e49d17f58b9b7cc051925f43b709b020745312c) by [@RSNara](https://github.com/RSNara))
- **Color APIs:** Fix the serialization of the alpha channel in the `rgba()` color string format. ([1cc12ce7fd](https://github.com/facebook/react-native/commit/1cc12ce7fd5c8c766872906b4175122558d369a0) by [@piaskowyk](https://github.com/piaskowyk))
- **Color APIs:** Fix incorrect flattening / non-rendering of views with `backgroundColor` set to `rgba(255, 255, 255, 127/256)` ([b1e8729f4d](https://github.com/facebook/react-native/commit/b1e8729f4dfcb065978887b94a9e0ca65cdcfa77) by [@rubennorte](https://github.com/rubennorte))
- **Fantom:** Support viewport offsets for Fantom root and fix `getBoundingClientRect` to respect viewport offsets ([b5c62f52d1](https://github.com/facebook/react-native/commit/b5c62f52d185d6427425e25e6f18d0d86acaebf0) by [@lunaleaps](https://github.com/lunaleaps))
- **IntersectionObserver:** Fix potential leak inside `IntersectionObserver` ([a55f430daa](https://github.com/facebook/react-native/commit/a55f430daa4c9168272482125998da849840f9dd) by [@RSNara](https://github.com/RSNara))
- **LogBox:** Remove LogBox patch, de-duplicating errors ([e0797d0e03](https://github.com/facebook/react-native/commit/e0797d0e03bde6cd3321ff76556c5e2f0454ec63) by [@rickhanlonii](https://github.com/rickhanlonii))
- **ScrollView:** Expose `ScrollView.getNativeScrollRef` on the type definition to allow accessing the underlying `HostInstance`. ([4b91b63094](https://github.com/facebook/react-native/commit/4b91b630945b3d0f82656791d089451066aad538) by [@zbauman3](https://github.com/zbauman3))
- **Typescript:** Add `ImageSource` type to TypeScript ([42ca46b95c](https://github.com/facebook/react-native/commit/42ca46b95cf9938de00b76dc61948a4ae7116e2b) by [@okwasniewski](https://github.com/okwasniewski))
- **Typescript:** Devtools TS Types ([8f189fce03](https://github.com/facebook/react-native/commit/8f189fce03db367abdceca6ad57ae28b613fdd7d) by [@krystofwoldrich](https://github.com/krystofwoldrich))
- **Yoga:** Fix possible invalid measurements with width or height is zero pixels ([5cc4d0a086](https://github.com/facebook/react-native/commit/5cc4d0a086d450e0f9d8ab6194013348f9de1f58) by [@NickGerleman](https://github.com/NickGerleman))
#### Android specific
- **BaseViewManager:** Remove focus change listener when dropping/recycling view instances ([94cbf206d6](https://github.com/facebook/react-native/commit/94cbf206d607477257c65039d97565a79e94c7dd) by [@Abbondanzo](https://github.com/Abbondanzo))
- **BoringLayout:** Include fallback line spacing in `BoringLayout` ([2fe6c1a947](https://github.com/facebook/react-native/commit/2fe6c1a94758223a5342fdfa90163971eb588e6a) by [@NickGerleman](https://github.com/NickGerleman))
- **Bridgeless:** Adding `shouldForwardToReactInstance` check in `ReactDelegate` for Bridgeless ([0f7bf66bba](https://github.com/facebook/react-native/commit/0f7bf66bba8498c89384e96ad9219cdad0107b0c) by [@arushikesarwani94](https://github.com/arushikesarwani94))
- **Codegen:** Fix combining schema in Codegen process to exclude platforms correctly ([6104ccdc6e](https://github.com/facebook/react-native/commit/6104ccdc6ef89c2d4da25e60dcc55d73038e023f) by [@arushikesarwani94](https://github.com/arushikesarwani94))
- **Edge To Edge:** Fix `Dimensions` `window` values on Android < 15 when edge-to-edge is enabled ([85d10ed904](https://github.com/facebook/react-native/commit/85d10ed90401a13de1f74aeddd773736195da285) by [@zoontek](https://github.com/zoontek))
- **FBReactNativeSpec:** Extract out `FBReactNativeSpec`'s core components including Unimplemented from auto-generated registry ([b417b0c2d5](https://github.com/facebook/react-native/commit/b417b0c2d56dc37f824c0e77e98d1014d21cd8f8) by [@arushikesarwani94](https://github.com/arushikesarwani94))
- **Gradle:** Fix Gradle v8.0 builds by using .set() for Property ([777397667c](https://github.com/facebook/react-native/commit/777397667c2625aab3fc907b9ef4bd564963d8bb) by [@meghancampbel9](https://github.com/meghancampbel9))
- **ImageFetcher:** Change `free` to `delete` to call destructor of `ImageFetcher` and release `contextContainer`. ([90da666691](https://github.com/facebook/react-native/commit/90da666691745ab9bf3930dc3347d8e51683099f) by [@WoLewicki](https://github.com/WoLewicki))
- **Modal:** Fix `Modal` first frame being rendered on top-left corner ([b950fa2afb](https://github.com/facebook/react-native/commit/b950fa2afb20e2213ff6c733cb1c2465b90406ef) by [@cortinico](https://github.com/cortinico))
- **onTextLayout:** Fix `onTextLayout` metrics not incorporating `ReactTextViewManagerCallback` ([a6a2884d63](https://github.com/facebook/react-native/commit/a6a2884d63717a42ac2bafd2054991ce8b32a2e9) by [@NickGerleman](https://github.com/NickGerleman))
- **Text:** Fix more text rounding bugs ([1fe3ff86c3](https://github.com/facebook/react-native/commit/1fe3ff86c364fad023ad1e426f26608699314339) by [@NickGerleman](https://github.com/NickGerleman))
- **Text:** Fix `TextLayoutManager` `MeasureMode` Regression ([99119a2104](https://github.com/facebook/react-native/commit/99119a210487af18983145fd374ff7ebc88931f3) by [@NickGerleman](https://github.com/NickGerleman))
- **TextInput:** Fix bug where focus would jump to top text input upon clearing a separate text input. ([79c47987b7](https://github.com/facebook/react-native/commit/79c47987b74ab044574fc542fd4b13a9f11aa491) by [@joevilches](https://github.com/joevilches))
#### iOS specific
- **Gradient**: Gradient interpolation for transparent colors ([097d482446](https://github.com/facebook/react-native/commit/097d482446b7a03ca0f8c7e0254f4d770e05c79c) by [@intergalacticspacehighway](https://github.com/intergalacticspacehighway))
- **Prebuild:** Fixed wrong path in prebuild hermes check ([be11f2ee77](https://github.com/facebook/react-native/commit/be11f2ee77fd793efe0a1aa225897a1924163925) by [@chrfalch](https://github.com/chrfalch))
- **Prebuild:** Fixed resolving build type when downloading hermes artifacts ([9371e20192](https://github.com/facebook/react-native/commit/9371e201927fd105e797bf06e43943dd21e04381) by [@chrfalch](https://github.com/chrfalch))
- **Package.swift:** Add missing `React-RCTSettings` to `Package.swift` ([e40c1d265a](https://github.com/facebook/react-native/commit/e40c1d265a2045730dcf751eed4ebf32e099f0c7) by [@chrfalch](https://github.com/chrfalch))
- **Package.swift:** Fixed defines in `Package.swift` ([e2f6ce4ddf](https://github.com/facebook/react-native/commit/e2f6ce4ddfbea5814fc5d8632df14daeae3636d1) by [@chrfalch](https://github.com/chrfalch))
- **RCTImage:** Allow for consuming `RCTImage` in Swift codebase by enabling "Defines Module" option ([1d80586730](https://github.com/facebook/react-native/commit/1d8058673085580f402ec3a320fce810db7ad2ef) by [@kkafar](https://github.com/kkafar))
- **RCTImageComponentView:** Fix `RCTImageComponentView` image loading after source props change with no layout invalidation ([cd5d74518b](https://github.com/facebook/react-native/commit/cd5d74518becb3355519373211d2f54ff7dbd208) by Nick Lefever)
- **RCTScreenSize:** Make `RCTScreenSize` take horizontal orientation into account ([50ce8c77a7](https://github.com/facebook/react-native/commit/50ce8c77a74f2f2574030db04dc88c6092e68ba8) by [@okwasniewski](https://github.com/okwasniewski))
- **TextInput:** Fixed blank space at the bottom of multiline `TextInput` on iOS ([2da4a6059a](https://github.com/facebook/react-native/commit/2da4a6059a82430fa7c1c078f0dcd38f0d3fe3cb) by [@tomekzaw](https://github.com/tomekzaw))
- **Turbo Modules:** Turbo Modules- Fixes dictionary stripped out when value is `null` ([4a4fd1cb8b](https://github.com/facebook/react-native/commit/4a4fd1cb8bb06eee185a3b2463caec4d2b7e9235) by [@zhongwuzw](https://github.com/zhongwuzw))
## v0.80.1
### Added
@@ -546,10 +358,6 @@ See [CHANGELOG-0.7x](./CHANGELOG-0.7x#v0791)
See [CHANGELOG-0.7x](./CHANGELOG-0.7x#v0790)
## v0.78.3
See [CHANGELOG-0.7x](./CHANGELOG-0.7x#v0783)
## v0.78.2
See [CHANGELOG-0.7x](./CHANGELOG-0.7x#v0782)
+1 -1
View File
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
+6 -6
View File
@@ -28,8 +28,8 @@
"set-version": "node ./scripts/releases/set-version.js",
"test-android": "./gradlew :packages:react-native:ReactAndroid:test",
"test-ci": "jest --maxWorkers=2 --ci --reporters=\"default\" --reporters=\"jest-junit\"",
"test-release-local-clean": "node ./scripts/release-testing/test-release-local-clean.js",
"test-release-local": "node ./scripts/release-testing/test-release-local.js",
"test-e2e-local-clean": "node ./scripts/release-testing/test-e2e-local-clean.js",
"test-e2e-local": "node ./scripts/release-testing/test-e2e-local.js",
"test-ios": "./scripts/objc-test.sh test",
"test-typescript": "tsc -p packages/react-native/types/tsconfig.json",
"test-generated-typescript": "tsc -p packages/react-native/types_generated/tsconfig.test.json",
@@ -58,7 +58,7 @@
"@react-native/metro-config": "0.81.0-main",
"@tsconfig/node22": "22.0.2",
"@types/react": "^19.1.0",
"@typescript-eslint/parser": "^8.36.0",
"@typescript-eslint/parser": "^7.1.1",
"ansi-styles": "^4.2.1",
"babel-plugin-minify-dead-code-elimination": "^0.5.2",
"babel-plugin-syntax-hermes-parser": "0.29.1",
@@ -93,9 +93,9 @@
"jest-snapshot": "^29.7.0",
"markdownlint-cli2": "^0.17.2",
"markdownlint-rule-relative-links": "^3.0.0",
"memfs": "^4.7.7",
"metro-babel-register": "^0.83.0",
"metro-transform-plugins": "^0.83.0",
"metro-babel-register": "^0.82.5",
"metro-memory-fs": "^0.82.5",
"metro-transform-plugins": "^0.82.5",
"micromatch": "^4.0.4",
"node-fetch": "^2.2.0",
"nullthrows": "^1.1.1",
+4 -4
View File
@@ -25,13 +25,13 @@
"@react-native/dev-middleware": "0.81.0-main",
"debug": "^4.4.0",
"invariant": "^2.2.4",
"metro": "^0.83.0",
"metro-config": "^0.83.0",
"metro-core": "^0.83.0",
"metro": "^0.82.5",
"metro-config": "^0.82.5",
"metro-core": "^0.82.5",
"semver": "^7.1.3"
},
"devDependencies": {
"metro-resolver": "^0.83.0"
"metro-resolver": "^0.82.5"
},
"peerDependencies": {
"@react-native-community/cli": "*",
@@ -147,7 +147,7 @@ async function runServer(
// $FlowIgnore[cannot-write] Assigning to readonly property
metroConfig.reporter = reporter;
await Metro.runServer(metroConfig, {
const serverInstance = await Metro.runServer(metroConfig, {
host: args.host,
secure: args.https,
secureCert: args.cert,
@@ -161,6 +161,18 @@ async function runServer(
reportEvent = eventsSocketEndpoint.reportEvent;
// In Node 8, the default keep-alive for an HTTP connection is 5 seconds. In
// early versions of Node 8, this was implemented in a buggy way which caused
// some HTTP responses (like those containing large JS bundles) to be
// terminated early.
//
// As a workaround, arbitrarily increase the keep-alive from 5 to 30 seconds,
// which should be enough to send even the largest of JS bundles.
//
// For more info: https://github.com/nodejs/node/issues/13391
//
serverInstance.keepAliveTimeout = 30000;
await version.logIfUpdateAvailable(cliConfig, terminalReporter);
}
+3 -2
View File
@@ -76,8 +76,9 @@ function getNodePackagePath(packageName: string): string {
}
function metro(...args: $ReadOnlyArray<string>): ExecaPromise {
log(`🚇 metro ${args.join(' ')} `);
return execa('npx', ['--offline', 'metro', ...args]);
const metroPath = getNodePackagePath(path.join('metro', 'src', 'cli.js'));
log(`🚇 ${metroPath} ${args.join(' ')} `);
return execa('node', [metroPath, ...args]);
}
export const tasks = {
@@ -23,8 +23,8 @@
"@babel/core": "^7.25.2",
"@babel/eslint-parser": "^7.25.1",
"@react-native/eslint-plugin": "0.81.0-main",
"@typescript-eslint/eslint-plugin": "^8.36.0",
"@typescript-eslint/parser": "^8.36.0",
"@typescript-eslint/eslint-plugin": "^7.1.1",
"@typescript-eslint/parser": "^7.1.1",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-ft-flow": "^2.0.1",
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
+2 -2
View File
@@ -28,7 +28,7 @@
"dependencies": {
"@react-native/js-polyfills": "0.81.0-main",
"@react-native/metro-babel-transformer": "0.81.0-main",
"metro-config": "^0.83.0",
"metro-runtime": "^0.83.0"
"metro-config": "^0.82.5",
"metro-runtime": "^0.82.5"
}
}
+12 -17
View File
@@ -13,7 +13,10 @@ import {ThemedText, useTheme} from './Theme';
import * as React from 'react';
import {
Image,
Platform,
SafeAreaView,
ScrollView,
StatusBar,
StyleSheet,
Text,
TouchableHighlight,
@@ -26,32 +29,24 @@ import {version as ReactNativeVersion} from 'react-native/Libraries/Core/ReactNa
export type NewAppScreenProps = $ReadOnly<{
templateFileName?: string,
safeAreaInsets?: $ReadOnly<{
top: number,
bottom: number,
left: number,
right: number,
}>,
}>;
const statusBarHeightOffset = Platform.select({
android: StatusBar.currentHeight || 0,
default: 0,
});
export default function NewAppScreen({
templateFileName = 'App.tsx',
safeAreaInsets = {top: 0, bottom: 0, left: 0, right: 0},
}: NewAppScreenProps): React.Node {
const {colors} = useTheme();
const isDarkMode = useColorScheme() === 'dark';
const isLargeScreen = useWindowDimensions().width > 600;
return (
<View
style={{
backgroundColor: colors.background,
paddingTop: safeAreaInsets.top,
paddingLeft: safeAreaInsets.left,
paddingRight: safeAreaInsets.right,
}}>
<ScrollView style={{paddingBottom: safeAreaInsets.bottom}}>
<View style={styles.container}>
<SafeAreaView style={{backgroundColor: colors.background}}>
<ScrollView>
<View style={[styles.container, {paddingTop: statusBarHeightOffset}]}>
<View style={styles.header}>
<Image
style={styles.logo}
@@ -104,7 +99,7 @@ export default function NewAppScreen({
</View>
</View>
</ScrollView>
</View>
</SafeAreaView>
);
}
-8
View File
@@ -11,14 +11,6 @@ import type * as React from 'react';
export type NewAppScreenProps = Readonly<{
templateFileName?: string | undefined;
safeAreaInsets?:
| Readonly<{
top: number;
bottom: number;
left: number;
right: number;
}>
| undefined;
}>;
export function NewAppScreen(props: NewAppScreenProps): React.ReactNode;
@@ -65,15 +65,15 @@ const TestTemplate = ({
propValue: string,
}) => `
TEST(${componentName}_${testName}, etc) {
auto propParser = RawPropsParser();
RawPropsParser propParser{};
propParser.prepare<${componentName}>();
auto const &sourceProps = ${componentName}();
auto const &rawProps = RawProps(folly::dynamic::object("${propName}", ${propValue}));
${componentName} sourceProps{};
RawProps rawProps(folly::dynamic::object("${propName}", ${propValue}));
ContextContainer contextContainer{};
PropsParserContext parserContext{-1, contextContainer};
rawProps.parse(propParser, parserContext);
rawProps.parse(propParser);
${componentName}(parserContext, sourceProps, rawProps);
}
`;
@@ -537,160 +537,3 @@ test('animate layout props', () => {
<rn-view height="100.000000" />,
);
});
test('AnimatedValue.interpolate', () => {
let _valueX;
let _interpolatedValueX;
const viewRef = createRef<HostInstance>();
function MyApp({outputRangeX}: $ReadOnly<{outputRangeX: number}>) {
const valueX = useAnimatedValue(0.5, {useNativeDriver: true});
_valueX = valueX;
const offset = outputRangeX - 1;
const interpolatedValueX = valueX.interpolate({
inputRange: [0, 1],
outputRange: [offset, 100],
});
_interpolatedValueX = interpolatedValueX;
return (
<Animated.View
ref={viewRef}
style={[
{
width: 100,
height: 100,
},
{transform: [{translateX: valueX}, {translateY: interpolatedValueX}]},
]}
/>
);
}
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<MyApp outputRangeX={1} />);
});
const viewElement = ensureInstance(viewRef.current, ReactNativeElement);
expect(_valueX?.__getValue()).toBe(0.5);
expect(_interpolatedValueX?.__getValue()).toBe(50);
expect(
JSON.stringify(
Fantom.unstable_getDirectManipulationProps(viewElement).transform,
),
).toBe('[{"translateX":0.5},{"translateY":50}]');
expect(viewElement.getBoundingClientRect().x).toBe(0.5);
expect(viewElement.getBoundingClientRect().y).toBe(50);
Fantom.runTask(() => {
root.render(<MyApp outputRangeX={51} />);
});
expect(_valueX?.__getValue()).toBe(0.5);
expect(_interpolatedValueX?.__getValue()).toBe(75);
expect(
JSON.stringify(
Fantom.unstable_getDirectManipulationProps(viewElement).transform,
),
).toBe('[{"translateX":0.5},{"translateY":75}]');
expect(viewElement.getBoundingClientRect().x).toBe(0.5);
expect(viewElement.getBoundingClientRect().y).toBe(75);
});
test('Animated.sequence', () => {
let _translateY;
let _isSequenceFinished = false;
const elementRef = createRef<HostInstance>();
function MyApp() {
const translateY = useAnimatedValue(0, {useNativeDriver: true});
_translateY = translateY;
return (
<View>
<Animated.View
ref={elementRef}
style={[
{
position: 'absolute',
width: 100,
height: 100,
},
{
transform: [
{
translateY: translateY.interpolate({
inputRange: [0, 1],
outputRange: [0, -16],
}),
},
],
},
]}
/>
</View>
);
}
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<MyApp />);
});
const element = ensureInstance(elementRef.current, ReactNativeElement);
expect(element.getBoundingClientRect().y).toBe(0);
Fantom.runTask(() => {
Animated.sequence([
Animated.timing(_translateY, {
toValue: 1,
duration: 500,
useNativeDriver: true,
}),
Animated.timing(_translateY, {
toValue: 0,
duration: 0,
useNativeDriver: true,
}),
]).start(({finished}) => {
if (finished) {
_isSequenceFinished = true;
}
});
});
Fantom.unstable_produceFramesForDuration(500);
expect(
// $FlowFixMe[incompatible-use]
Fantom.unstable_getDirectManipulationProps(element).transform[0].translateY,
).toBeCloseTo(-16, 0.001);
if (!ReactNativeFeatureFlags.cxxNativeAnimatedRemoveJsSync()) {
Fantom.runWorkLoop(); // React update to sync end state of 1st timing animation in sequence
}
expect(_isSequenceFinished).toBe(false);
expect(element.getBoundingClientRect().y).toBe(-16);
Fantom.runWorkLoop(); // React render
expect(
// $FlowFixMe[incompatible-use]
Fantom.unstable_getDirectManipulationProps(element).transform[0].translateY,
).toBeCloseTo(0, 0.001);
if (!ReactNativeFeatureFlags.cxxNativeAnimatedRemoveJsSync()) {
Fantom.runWorkLoop(); // React update to sync end state of 2nd timing animation in sequence
}
expect(element.getBoundingClientRect().y).toBe(0);
if (ReactNativeFeatureFlags.cxxNativeAnimatedRemoveJsSync()) {
expect(_isSequenceFinished).toBe(false);
Fantom.runWorkLoop();
}
expect(_isSequenceFinished).toBe(true);
});
@@ -673,7 +673,7 @@ type ScrollViewBaseProps = $ReadOnly<{
}>;
export type ScrollViewProps = $ReadOnly<{
...ViewProps,
...Omit<ViewProps, 'experimental_accessibilityOrder'>,
...ScrollViewPropsIOS,
...ScrollViewPropsAndroid,
...ScrollViewBaseProps,
@@ -1031,7 +1031,7 @@ type TextInputBaseProps = $ReadOnly<{
}>;
export type TextInputProps = $ReadOnly<{
...Omit<ViewProps, 'style'>,
...Omit<ViewProps, 'style' | 'experimental_accessibilityOrder'>,
...TextInputIOSProps,
...TextInputAndroidProps,
...TextInputBaseProps,
@@ -242,8 +242,6 @@ function reactConsoleErrorHandler(...args) {
if (__DEV__) {
// If we're not reporting to the console in reportException,
// we need to report it as a console.error here.
/* $FlowFixMe[constant-condition] Error discovered during Constant
* Condition roll out. See https://fburl.com/workplace/1v97vimq. */
if (!reportToConsole) {
require('../LogBox/LogBox').default.addConsoleLog('error', ...args);
}
@@ -73,8 +73,6 @@ const InteractionManagerImpl = {
* Notify manager that an interaction has started.
*/
createInteractionHandle(): Handle {
/* $FlowFixMe[constant-condition] Error discovered during Constant
* Condition roll out. See https://fburl.com/workplace/1v97vimq. */
DEBUG && console.log('InteractionManager: create interaction handle');
_scheduleUpdate();
const handle = ++_inc;
@@ -86,8 +84,6 @@ const InteractionManagerImpl = {
* Notify manager that an interaction has completed.
*/
clearInteractionHandle(handle: Handle) {
/* $FlowFixMe[constant-condition] Error discovered during Constant
* Condition roll out. See https://fburl.com/workplace/1v97vimq. */
DEBUG && console.log('InteractionManager: clear interaction handle');
invariant(!!handle, 'InteractionManager: Must provide a handle to clear.');
_scheduleUpdate();
@@ -99,13 +99,9 @@ class TaskQueue {
const task = queue.shift();
try {
if (typeof task === 'object' && task.gen) {
/* $FlowFixMe[constant-condition] Error discovered during Constant
* Condition roll out. See https://fburl.com/workplace/1v97vimq. */
DEBUG && console.log('TaskQueue: genPromise for task ' + task.name);
this._genPromise(task);
} else if (typeof task === 'object' && task.run) {
/* $FlowFixMe[constant-condition] Error discovered during Constant
* Condition roll out. See https://fburl.com/workplace/1v97vimq. */
DEBUG && console.log('TaskQueue: run task ' + task.name);
task.run();
} else {
@@ -114,8 +110,6 @@ class TaskQueue {
'Expected Function, SimpleTask, or PromiseTask, but got:\n' +
JSON.stringify(task, null, 2),
);
/* $FlowFixMe[constant-condition] Error discovered during Constant
* Condition roll out. See https://fburl.com/workplace/1v97vimq. */
DEBUG && console.log('TaskQueue: run anonymous task');
task();
}
@@ -145,8 +139,6 @@ class TaskQueue {
this._queueStack.length > 1
) {
this._queueStack.pop();
/* $FlowFixMe[constant-condition] Error discovered during Constant
* Condition roll out. See https://fburl.com/workplace/1v97vimq. */
DEBUG &&
console.log('TaskQueue: popped queue: ', {
stackIdx,
@@ -166,17 +158,11 @@ class TaskQueue {
this._queueStack.push({tasks: [], popable: false});
const stackIdx = this._queueStack.length - 1;
const stackItem = this._queueStack[stackIdx];
/* $FlowFixMe[constant-condition] Error discovered during Constant
* Condition roll out. See https://fburl.com/workplace/1v97vimq. */
DEBUG && console.log('TaskQueue: push new queue: ', {stackIdx});
/* $FlowFixMe[constant-condition] Error discovered during Constant
* Condition roll out. See https://fburl.com/workplace/1v97vimq. */
DEBUG && console.log('TaskQueue: exec gen task ' + task.name);
task
.gen()
.then(() => {
/* $FlowFixMe[constant-condition] Error discovered during Constant
* Condition roll out. See https://fburl.com/workplace/1v97vimq. */
DEBUG &&
console.log('TaskQueue: onThen for gen task ' + task.name, {
stackIdx,
@@ -802,7 +802,7 @@ describe('LogBox', () => {
expect(logBox.getNotificationUI()).toEqual({
count: '!',
message:
'Invalid prop `invalid` supplied to `React.Fragment`. React.Fragment can only have `key`, `ref`, and `children` props.',
'Invalid prop `invalid` supplied to `React.Fragment`. React.Fragment can only have `key` and `children` props.',
});
// Open LogBox.
@@ -817,7 +817,7 @@ describe('LogBox', () => {
// This seems like a bug, should be "Render Error".
title: 'Console Error',
message:
'Invalid prop `invalid` supplied to `React.Fragment`. React.Fragment can only have `key`, `ref`, and `children` props.',
'Invalid prop `invalid` supplied to `React.Fragment`. React.Fragment can only have `key` and `children` props.',
componentStackFrames: ['<TestComponent />'],
isDismissable: true,
});
@@ -51,7 +51,9 @@ RCT_EXPORT_MODULE();
{
// _surfacePresenter set in setSurfacePresenter:
_nodesManager = [[RCTNativeAnimatedNodesManager alloc] initWithBridge:nil surfacePresenter:_surfacePresenter];
[_surfacePresenter addObserver:self];
if (!facebook::react::ReactNativeFeatureFlags::animatedShouldSignalBatch()) {
[_surfacePresenter addObserver:self];
}
[[self.moduleRegistry moduleForName:"EventDispatcher"] addDispatchObserver:self];
}
@@ -60,7 +62,9 @@ RCT_EXPORT_MODULE();
[super invalidate];
[_nodesManager stopAnimationLoop];
[[self.moduleRegistry moduleForName:"EventDispatcher"] removeDispatchObserver:self];
[_surfacePresenter removeObserver:self];
if (!facebook::react::ReactNativeFeatureFlags::animatedShouldSignalBatch()) {
[_surfacePresenter removeObserver:self];
}
}
/*
@@ -76,7 +80,11 @@ RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(startOperationBatch) {}
RCT_EXPORT_METHOD(finishOperationBatch) {}
RCT_EXPORT_METHOD(finishOperationBatch)
{
// This method is only called from JS when animatedShouldSignalBatch is enabled.
[self flushOperationQueues];
}
RCT_EXPORT_METHOD(createAnimatedNode : (double)tag config : (NSDictionary<NSString *, id> *)config)
{
@@ -251,27 +259,39 @@ RCT_EXPORT_METHOD(queueAndExecuteBatchedOperations : (NSArray *)operationsAndArg
- (void)queueFlushedOperationBlock:(AnimatedOperation)operation
{
dispatch_async(RCTGetUIManagerQueue(), ^{
if (facebook::react::ReactNativeFeatureFlags::animatedShouldSignalBatch()) {
[self addOperationBlock:operation];
// In Bridge, flushing of native animations is done from RCTCxxBridge batchDidComplete().
// Since RCTCxxBridge doesn't exist in Bridgeless, and components are not remounted in Fabric for native
// animations, flush here for changes in Animated.Value for Animated.event.
[self flushOperationQueues];
});
} else {
dispatch_async(RCTGetUIManagerQueue(), ^{
[self addOperationBlock:operation];
// In Bridge, flushing of native animations is done from RCTCxxBridge batchDidComplete().
// Since RCTCxxBridge doesn't exist in Bridgeless, and components are not remounted in Fabric for native
// animations, flush here for changes in Animated.Value for Animated.event.
[self flushOperationQueues];
});
}
}
- (void)queueOperationBlock:(AnimatedOperation)operation
{
dispatch_async(RCTGetUIManagerQueue(), ^{
if (facebook::react::ReactNativeFeatureFlags::animatedShouldSignalBatch()) {
[self addOperationBlock:operation];
});
} else {
dispatch_async(RCTGetUIManagerQueue(), ^{
[self addOperationBlock:operation];
});
}
}
- (void)queuePreOperationBlock:(AnimatedOperation)operation
{
dispatch_async(RCTGetUIManagerQueue(), ^{
if (facebook::react::ReactNativeFeatureFlags::animatedShouldSignalBatch()) {
[self addPreOperationBlock:operation];
});
} else {
dispatch_async(RCTGetUIManagerQueue(), ^{
[self addPreOperationBlock:operation];
});
}
}
- (void)addOperationBlock:(AnimatedOperation)operation
+5 -22
View File
@@ -34,9 +34,6 @@ const RCTNetworking = require('./RCTNetworking').default;
const base64 = require('base64-js');
const invariant = require('invariant');
const PERFORMANCE_TRACK_NAME = 'Network (JS-initiated only)';
const PERFORMANCE_TRACK_GROUP = 'Chrome DevTools Temp Compat';
declare var performance: Performance;
const DEBUG_NETWORK_SEND_DELAY: false = false; // Set to a number of milliseconds when debugging
@@ -388,9 +385,6 @@ class XMLHttpRequest extends EventTarget {
if (requestId !== this._requestId) {
return;
}
const start = XMLHttpRequest._profiling ? performance.now() : undefined;
if (!this._response) {
this._response = responseText;
} else {
@@ -398,13 +392,8 @@ class XMLHttpRequest extends EventTarget {
}
if (XMLHttpRequest._profiling) {
console.timeStamp(
'Incremental Data: ' + this._getMeasureURL(),
// $FlowFixMe[extra-arg] Add correct typing for `console.timeStamp`
start,
undefined,
PERFORMANCE_TRACK_NAME,
PERFORMANCE_TRACK_GROUP,
performance.mark(
'Track:XMLHttpRequest:Incremental Data: ' + this._getMeasureURL(),
);
}
XMLHttpRequest._interceptor &&
@@ -453,14 +442,10 @@ class XMLHttpRequest extends EventTarget {
this.setReadyState(this.DONE);
if (XMLHttpRequest._profiling && this._startTime != null) {
const start = this._startTime;
console.timeStamp(
this._getMeasureURL(),
// $FlowFixMe[extra-arg] Add correct typing for `console.timeStamp`
performance.measure('Track:XMLHttpRequest:' + this._getMeasureURL(), {
start,
undefined,
PERFORMANCE_TRACK_NAME,
PERFORMANCE_TRACK_GROUP,
);
end: performance.now(),
});
}
if (error) {
XMLHttpRequest._interceptor &&
@@ -661,8 +646,6 @@ class XMLHttpRequest extends EventTarget {
this.withCredentials,
);
};
/* $FlowFixMe[constant-condition] Error discovered during Constant
* Condition roll out. See https://fburl.com/workplace/1v97vimq. */
if (DEBUG_NETWORK_SEND_DELAY) {
setTimeout(doSend, DEBUG_NETWORK_SEND_DELAY);
} else {
@@ -18,7 +18,6 @@ end
header_search_paths = [
"\"${PODS_ROOT}/Headers/Public/ReactCodegen/react/renderer/components\"",
"\"${PODS_ROOT}/Headers/Public/React-RCTFBReactNativeSpec/FBReactNativeSpec\"",
]
Pod::Spec.new do |s|
@@ -46,9 +45,7 @@ Pod::Spec.new do |s|
s.dependency "React-Core/RCTPushNotificationHeaders"
s.dependency "React-jsi"
add_dependency(s, "React-RCTFBReactNativeSpec", :additional_framework_paths => ['FBReactNativeSpec'])
add_dependency(s, "React-RCTFBReactNativeSpec")
add_dependency(s, "ReactCommon", :subspec => "turbomodule/core", :additional_framework_paths => ["react/nativemodule/core"])
add_dependency(s, "React-NativeModulesApple")
add_rncore_dependency(s)
end
@@ -35,8 +35,6 @@ class PerformanceLogger implements IPerformanceLogger {
endExtras?: Extras,
) {
if (this._closed) {
/* $FlowFixMe[constant-condition] Error discovered during Constant
* Condition roll out. See https://fburl.com/workplace/1v97vimq. */
if (PRINT_TO_CONSOLE && __DEV__) {
console.log(
'PerformanceLogger: addTimespan - has closed ignoring: ',
@@ -46,8 +44,6 @@ class PerformanceLogger implements IPerformanceLogger {
return;
}
if (this._timespans[key]) {
/* $FlowFixMe[constant-condition] Error discovered during Constant
* Condition roll out. See https://fburl.com/workplace/1v97vimq. */
if (PRINT_TO_CONSOLE && __DEV__) {
console.log(
'PerformanceLogger: Attempting to add a timespan that already exists ',
@@ -83,8 +79,6 @@ class PerformanceLogger implements IPerformanceLogger {
this._timespans = {};
this._extras = {};
this._points = {};
/* $FlowFixMe[constant-condition] Error discovered during Constant
* Condition roll out. See https://fburl.com/workplace/1v97vimq. */
if (PRINT_TO_CONSOLE) {
console.log('PerformanceLogger.js', 'clear');
}
@@ -98,8 +92,6 @@ class PerformanceLogger implements IPerformanceLogger {
}
this._extras = {};
this._points = {};
/* $FlowFixMe[constant-condition] Error discovered during Constant
* Condition roll out. See https://fburl.com/workplace/1v97vimq. */
if (PRINT_TO_CONSOLE) {
console.log('PerformanceLogger.js', 'clearCompleted');
}
@@ -138,8 +130,6 @@ class PerformanceLogger implements IPerformanceLogger {
}
logEverything() {
/* $FlowFixMe[constant-condition] Error discovered during Constant
* Condition roll out. See https://fburl.com/workplace/1v97vimq. */
if (PRINT_TO_CONSOLE) {
// log timespans
for (const key in this._timespans) {
@@ -166,8 +156,6 @@ class PerformanceLogger implements IPerformanceLogger {
extras?: Extras,
) {
if (this._closed) {
/* $FlowFixMe[constant-condition] Error discovered during Constant
* Condition roll out. See https://fburl.com/workplace/1v97vimq. */
if (PRINT_TO_CONSOLE && __DEV__) {
console.log(
'PerformanceLogger: markPoint - has closed ignoring: ',
@@ -177,8 +165,6 @@ class PerformanceLogger implements IPerformanceLogger {
return;
}
if (this._points[key] != null) {
/* $FlowFixMe[constant-condition] Error discovered during Constant
* Condition roll out. See https://fburl.com/workplace/1v97vimq. */
if (PRINT_TO_CONSOLE && __DEV__) {
console.log(
'PerformanceLogger: Attempting to mark a point that has been already logged ',
@@ -201,8 +187,6 @@ class PerformanceLogger implements IPerformanceLogger {
setExtra(key: string, value: ExtraValue) {
if (this._closed) {
/* $FlowFixMe[constant-condition] Error discovered during Constant
* Condition roll out. See https://fburl.com/workplace/1v97vimq. */
if (PRINT_TO_CONSOLE && __DEV__) {
console.log('PerformanceLogger: setExtra - has closed ignoring: ', key);
}
@@ -210,8 +194,6 @@ class PerformanceLogger implements IPerformanceLogger {
}
if (this._extras.hasOwnProperty(key)) {
/* $FlowFixMe[constant-condition] Error discovered during Constant
* Condition roll out. See https://fburl.com/workplace/1v97vimq. */
if (PRINT_TO_CONSOLE && __DEV__) {
console.log(
'PerformanceLogger: Attempting to set an extra that already exists ',
@@ -229,8 +211,6 @@ class PerformanceLogger implements IPerformanceLogger {
extras?: Extras,
) {
if (this._closed) {
/* $FlowFixMe[constant-condition] Error discovered during Constant
* Condition roll out. See https://fburl.com/workplace/1v97vimq. */
if (PRINT_TO_CONSOLE && __DEV__) {
console.log(
'PerformanceLogger: startTimespan - has closed ignoring: ',
@@ -241,8 +221,6 @@ class PerformanceLogger implements IPerformanceLogger {
}
if (this._timespans[key]) {
/* $FlowFixMe[constant-condition] Error discovered during Constant
* Condition roll out. See https://fburl.com/workplace/1v97vimq. */
if (PRINT_TO_CONSOLE && __DEV__) {
console.log(
'PerformanceLogger: Attempting to start a timespan that already exists ',
@@ -256,8 +234,6 @@ class PerformanceLogger implements IPerformanceLogger {
startTime: timestamp,
startExtras: extras,
};
/* $FlowFixMe[constant-condition] Error discovered during Constant
* Condition roll out. See https://fburl.com/workplace/1v97vimq. */
if (PRINT_TO_CONSOLE) {
console.log('PerformanceLogger.js', 'start: ' + key);
}
@@ -269,8 +245,6 @@ class PerformanceLogger implements IPerformanceLogger {
extras?: Extras,
) {
if (this._closed) {
/* $FlowFixMe[constant-condition] Error discovered during Constant
* Condition roll out. See https://fburl.com/workplace/1v97vimq. */
if (PRINT_TO_CONSOLE && __DEV__) {
console.log(
'PerformanceLogger: stopTimespan - has closed ignoring: ',
@@ -282,8 +256,6 @@ class PerformanceLogger implements IPerformanceLogger {
const timespan = this._timespans[key];
if (!timespan || timespan.startTime == null) {
/* $FlowFixMe[constant-condition] Error discovered during Constant
* Condition roll out. See https://fburl.com/workplace/1v97vimq. */
if (PRINT_TO_CONSOLE && __DEV__) {
console.log(
'PerformanceLogger: Attempting to end a timespan that has not started ',
@@ -293,8 +265,6 @@ class PerformanceLogger implements IPerformanceLogger {
return;
}
if (timespan.endTime != null) {
/* $FlowFixMe[constant-condition] Error discovered during Constant
* Condition roll out. See https://fburl.com/workplace/1v97vimq. */
if (PRINT_TO_CONSOLE && __DEV__) {
console.log(
'PerformanceLogger: Attempting to end a timespan that has already ended ',
@@ -307,8 +277,6 @@ class PerformanceLogger implements IPerformanceLogger {
timespan.endExtras = extras;
timespan.endTime = timestamp;
timespan.totalTime = timespan.endTime - (timespan.startTime || 0);
/* $FlowFixMe[constant-condition] Error discovered during Constant
* Condition roll out. See https://fburl.com/workplace/1v97vimq. */
if (PRINT_TO_CONSOLE) {
console.log('PerformanceLogger.js', 'end: ' + key);
}
+2 -3
View File
@@ -166,7 +166,7 @@ let reactJsInspector = RNTarget(
name: .reactJsInspector,
path: "ReactCommon/jsinspector-modern",
excludedPaths: ["tracing", "network", "tests"],
dependencies: [.reactNativeDependencies, .reactFeatureFlags, .jsi, .reactJsInspectorTracing, .reactJsInspectorNetwork, .reactRuntimeExecutor, .reactPerfLogger],
dependencies: [.reactNativeDependencies, .reactFeatureFlags, .jsi, .reactJsInspectorTracing, .reactJsInspectorNetwork, .reactRuntimeExecutor],
defines: [
CXXSetting.define("REACT_NATIVE_DEBUGGER_ENABLED", to: "1", .when(configuration: BuildConfiguration.debug)),
CXXSetting.define("REACT_NATIVE_DEBUGGER_ENABLED_DEVONLY", to: "1", .when(configuration: BuildConfiguration.debug)),
@@ -398,7 +398,6 @@ let reactFabric = RNTarget(
"components/textinput/platform/ios/",
"components/unimplementedview",
"components/virtualview",
"components/virtualviewexperimental",
"components/root/tests",
],
dependencies: [.reactNativeDependencies, .reactJsiExecutor, .rctTypesafety, .reactTurboModuleCore, .jsi, .logger, .reactDebug, .reactFeatureFlags, .reactUtils, .reactRuntimeScheduler, .reactCxxReact, .reactRendererDebug, .reactGraphics, .yoga],
@@ -434,7 +433,7 @@ let reactFabricComponents = RNTarget(
"conponents/rncore", // this was the old folder where RN Core Components were generated. If you ran codegen in the past, you might have some files in it that might make the build fail.
],
dependencies: [.reactNativeDependencies, .reactCore, .reactJsiExecutor, .reactTurboModuleCore, .jsi, .logger, .reactDebug, .reactFeatureFlags, .reactUtils, .reactRuntimeScheduler, .reactCxxReact, .yoga, .reactRendererDebug, .reactGraphics, .reactFabric, .reactTurboModuleBridging],
sources: ["components/inputaccessory", "components/modal", "components/safeareaview", "components/text", "components/text/platform/cxx", "components/textinput", "components/textinput/platform/ios/", "components/unimplementedview", "components/virtualview", "components/virtualviewexperimental", "textlayoutmanager", "textlayoutmanager/platform/ios"]
sources: ["components/inputaccessory", "components/modal", "components/safeareaview", "components/text", "components/text/platform/cxx", "components/textinput", "components/textinput/platform/ios/", "components/unimplementedview", "components/virtualview", "textlayoutmanager", "textlayoutmanager/platform/ios"]
)
/// React-FabricImage.podspec
@@ -62,7 +62,8 @@ Pod::Spec.new do |s|
CONFIG="Debug"
fi
"$NODE_BINARY" "$REACT_NATIVE_PATH/scripts/replace-rncore-version.js" -c "$CONFIG" -r "#{version}" -p "$PODS_ROOT"
# TODO(T228219721): Add this for React Native Core as well
##### "$NODE_BINARY" "$REACT_NATIVE_PATH/third-party-podspecs/replace_dependencies_version.js" -c "$CONFIG" -r "#{version}" -p "$PODS_ROOT"
EOS
}
@@ -72,7 +73,7 @@ Pod::Spec.new do |s|
# always run the script without warning
script_phase[:always_out_of_date] = "1"
end
s.script_phase = script_phase
end
end
@@ -47,6 +47,7 @@ RCT_EXTERN void RCTExecuteOnMainQueue(dispatch_block_t block);
// Legacy function to execute the specified block on the main queue synchronously.
// Please do not use this unless you know what you're doing.
RCT_EXTERN void RCTUnsafeExecuteOnMainQueueSync(dispatch_block_t block);
RCT_EXTERN void RCTUnsafeExecuteOnMainQueueSyncWithError(dispatch_block_t block, NSString *context);
// Get screen metrics in a thread-safe way
RCT_EXTERN CGFloat RCTScreenScale(void);
@@ -304,6 +304,13 @@ void RCTExecuteOnMainQueue(dispatch_block_t block)
// Please do not use this method
// unless you know what you are doing.
void RCTUnsafeExecuteOnMainQueueSync(dispatch_block_t block)
{
RCTUnsafeExecuteOnMainQueueSyncWithError(block, @"Sync dispatches to the main queue can deadlock React Native.");
}
// Please do not use this method
// unless you know what you are doing.
void RCTUnsafeExecuteOnMainQueueSyncWithError(dispatch_block_t block, NSString *context)
{
if (RCTIsMainQueue()) {
block();
@@ -315,6 +322,10 @@ void RCTUnsafeExecuteOnMainQueueSync(dispatch_block_t block)
return;
}
if (ReactNativeFeatureFlags::disableMainQueueSyncDispatchIOS()) {
RCTLogError(@"RCTUnsafeExecuteOnMainQueueSync: %@", context);
}
dispatch_sync(dispatch_get_main_queue(), ^{
block();
});
@@ -343,6 +354,10 @@ static void RCTUnsafeExecuteOnMainQueueOnceSync(dispatch_once_t *onceToken, disp
return;
}
if (ReactNativeFeatureFlags::disableMainQueueSyncDispatchIOS()) {
RCTLogError(@"RCTUnsafeExecuteOnMainQueueOnceSync: Sync dispatches to the main queue can deadlock React Native.");
}
dispatch_sync(dispatch_get_main_queue(), executeOnce);
}
@@ -39,7 +39,7 @@ static NSString *const RCTPerfMonitorCellIdentifier = @"RCTPerfMonitorCellIdenti
static const CGFloat RCTPerfMonitorBarHeight = 50;
static const CGFloat RCTPerfMonitorExpandHeight = 250;
using RCTJSCSetOptionType = BOOL (*)(const char *);
typedef BOOL (*RCTJSCSetOptionType)(const char *);
NSArray<NSString *> *LabelsForRCTPerformanceLoggerTags();
@@ -1,24 +0,0 @@
/*
* 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.
*/
#import <UIKit/UIKit.h>
#import <React/RCTViewComponentView.h>
NS_ASSUME_NONNULL_BEGIN
@interface RCTVirtualViewExperimentalComponentView : RCTViewComponentView
+ (instancetype)new NS_UNAVAILABLE;
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithCoder:(NSCoder *)coder NS_UNAVAILABLE;
- (instancetype)initWithFrame:(CGRect)frame NS_DESIGNATED_INITIALIZER;
@end
NS_ASSUME_NONNULL_END
@@ -1,384 +0,0 @@
/*
* 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.
*/
#import "RCTVirtualViewExperimentalComponentView.h"
#import <React/RCTAssert.h>
#import <React/RCTConversions.h>
#import <React/RCTScrollViewComponentView.h>
#import <React/RCTScrollableProtocol.h>
#import <React/UIView+React.h>
#import <jsi/jsi.h>
#import <react/featureflags/ReactNativeFeatureFlags.h>
#import <react/renderer/components/FBReactNativeSpec/ComponentDescriptors.h>
#import <react/renderer/components/FBReactNativeSpec/EventEmitters.h>
#import <react/renderer/components/FBReactNativeSpec/Props.h>
#import <react/renderer/components/virtualviewexperimental/VirtualViewExperimentalComponentDescriptor.h>
#import <react/renderer/components/virtualviewexperimental/VirtualViewExperimentalShadowNode.h>
#import "RCTFabricComponentsPlugins.h"
using namespace facebook;
using namespace facebook::react;
typedef NS_ENUM(NSInteger, RCTVirtualViewMode) {
RCTVirtualViewModeVisible = 0,
RCTVirtualViewModePrerender = 1,
RCTVirtualViewModeHidden = 2,
};
typedef NS_ENUM(NSInteger, RCTVirtualViewRenderState) {
RCTVirtualViewRenderStateUnknown = 0,
RCTVirtualViewRenderStateRendered = 1,
RCTVirtualViewRenderStateNone = 2,
};
/**
* Checks whether one CGRect overlaps with another CGRect.
*
* This is different from CGRectIntersectsRect because a CGRect representing
* a line or a point is considered to overlap with another CGRect if the line
* or point is within the rect bounds. However, two CGRects are not considered
* to overlap if they only share a boundary.
*/
static BOOL CGRectOverlaps(CGRect rect1, CGRect rect2)
{
CGFloat minY1 = CGRectGetMinY(rect1);
CGFloat maxY1 = CGRectGetMaxY(rect1);
CGFloat minY2 = CGRectGetMinY(rect2);
CGFloat maxY2 = CGRectGetMaxY(rect2);
if (minY1 >= maxY2 || minY2 >= maxY1) {
// No overlap on the y-axis.
return NO;
}
CGFloat minX1 = CGRectGetMinX(rect1);
CGFloat maxX1 = CGRectGetMaxX(rect1);
CGFloat minX2 = CGRectGetMinX(rect2);
CGFloat maxX2 = CGRectGetMaxX(rect2);
if (minX1 >= maxX2 || minX2 >= maxX1) {
// No overlap on the x-axis.
return NO;
}
return YES;
}
@interface RCTVirtualViewExperimentalComponentView () <UIScrollViewDelegate>
@end
@implementation RCTVirtualViewExperimentalComponentView {
RCTScrollViewComponentView *_lastParentScrollViewComponentView;
std::optional<enum RCTVirtualViewMode> _mode;
enum RCTVirtualViewRenderState _renderState;
std::optional<CGRect> _targetRect;
}
- (instancetype)initWithFrame:(CGRect)frame
{
if ((self = [super initWithFrame:frame]) != nil) {
_props = VirtualViewExperimentalShadowNode::defaultSharedProps();
_renderState = RCTVirtualViewRenderStateUnknown;
}
return self;
}
- (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &)oldProps
{
const auto &newViewProps = static_cast<const VirtualViewExperimentalProps &>(*props);
if (!_mode.has_value()) {
_mode = newViewProps.initialHidden ? RCTVirtualViewModeHidden : RCTVirtualViewModeVisible;
if (ReactNativeFeatureFlags::hideOffscreenVirtualViewsOnIOS()) {
self.hidden = newViewProps.initialHidden && !sIsAccessibilityUsed;
}
}
// If disabled, `_renderState` will always be `RCTVirtualViewRenderStateUnknown`.
if (ReactNativeFeatureFlags::enableVirtualViewRenderState()) {
switch (newViewProps.renderState) {
case 1:
_renderState = RCTVirtualViewRenderStateRendered;
break;
case 2:
_renderState = RCTVirtualViewRenderStateNone;
break;
default:
_renderState = RCTVirtualViewRenderStateUnknown;
break;
}
}
[super updateProps:props oldProps:oldProps];
}
- (RCTScrollViewComponentView *)getParentScrollViewComponentView
{
UIView *view = self.superview;
while (view != nil) {
if ([view isKindOfClass:[RCTScrollViewComponentView class]]) {
return (RCTScrollViewComponentView *)view;
}
view = view.superview;
}
return nil;
}
/**
* Static flag that tracks whether accessibility services are being used.
* When accessibility is detected, virtual views will remain visible even when
* they would normally be hidden when off-screen, ensuring that accessibility
* features will work correctly.
*/
static BOOL sIsAccessibilityUsed = NO;
- (void)_unhideIfNeeded
{
if (!sIsAccessibilityUsed) {
// accessibility is detected for the first time. Make views visible.
sIsAccessibilityUsed = YES;
}
if (self.hidden) {
self.hidden = NO;
}
}
- (NSInteger)accessibilityElementCount
{
// From empirical testing, method `accessibilityElementCount` is called lazily only
// when accessibility is used.
[self _unhideIfNeeded];
return [super accessibilityElementCount];
}
- (NSArray<id<UIFocusItem>> *)focusItemsInRect:(CGRect)rect
{
// From empirical testing, method `focusItemsInRect:` is called lazily only
// when keyboard navigation is used.
[self _unhideIfNeeded];
return [super focusItemsInRect:rect];
}
- (void)prepareForRecycle
{
[super prepareForRecycle];
// No need to remove the scroll listener here since the view is always removed from window before being recycled and
// we do that in didMoveToWindow, which gets called when the view is removed from window.
RCTAssert(
_lastParentScrollViewComponentView == nil,
@"_lastParentScrollViewComponentView should already have been cleared in didMoveToWindow.");
self.hidden = NO;
_mode.reset();
_targetRect.reset();
}
// Handles case when sibling changes size.
// TODO(T202601695): This doesn't yet handle the case of elements in the ScrollView outside a VirtualColumn changing
// size.
- (void)updateLayoutMetrics:(const LayoutMetrics &)layoutMetrics
oldLayoutMetrics:(const LayoutMetrics &)oldLayoutMetrics
{
[super updateLayoutMetrics:layoutMetrics oldLayoutMetrics:_layoutMetrics];
[self dispatchOnModeChangeIfNeeded:YES];
}
- (void)didMoveToWindow
{
[super didMoveToWindow];
if (_lastParentScrollViewComponentView != nil) {
[_lastParentScrollViewComponentView removeScrollListener:self];
_lastParentScrollViewComponentView = nil;
}
if (RCTScrollViewComponentView *parentScrollViewComponentView = [self getParentScrollViewComponentView]) {
if (self.window != nil) {
// TODO(T202601695): We also want the ScrollView to emit layout changes from didLayoutSubviews so that any event
// that may affect visibily of this view notifies the listeners.
[parentScrollViewComponentView addScrollListener:self];
_lastParentScrollViewComponentView = parentScrollViewComponentView;
// We want to dispatch the event immediately when the view is added to the window before any scrolling occurs.
[self dispatchOnModeChangeIfNeeded:NO];
}
}
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
[self dispatchOnModeChangeIfNeeded:NO];
}
- (void)dispatchOnModeChangeIfNeeded:(BOOL)checkForTargetRectChange
{
if (_lastParentScrollViewComponentView == nullptr) {
return;
}
UIScrollView *scrollView = _lastParentScrollViewComponentView.scrollView;
CGRect targetRect = [self convertRect:self.bounds toView:scrollView];
// While scrolling, the `targetRect` does not change, so we don't check for changed `targetRect` in that case.
if (checkForTargetRectChange) {
if (_targetRect.has_value() && CGRectEqualToRect(targetRect, _targetRect.value())) {
return;
}
_targetRect = targetRect;
}
enum RCTVirtualViewMode newMode;
CGRect thresholdRect = CGRectMake(
scrollView.contentOffset.x,
scrollView.contentOffset.y,
scrollView.frame.size.width,
scrollView.frame.size.height);
if (CGRectOverlaps(targetRect, thresholdRect)) {
newMode = RCTVirtualViewModeVisible;
} else {
auto prerender = false;
const CGFloat prerenderRatio = ReactNativeFeatureFlags::virtualViewPrerenderRatio();
if (prerenderRatio > 0) {
thresholdRect = CGRectInset(
thresholdRect, -thresholdRect.size.width * prerenderRatio, -thresholdRect.size.height * prerenderRatio);
prerender = CGRectOverlaps(targetRect, thresholdRect);
}
if (prerender) {
newMode = RCTVirtualViewModePrerender;
} else {
newMode = RCTVirtualViewModeHidden;
thresholdRect = CGRectZero;
}
}
if (_mode.has_value() && newMode == _mode.value()) {
return;
}
// NOTE: Make sure to keep these props in sync with dispatchSyncModeChange below where we have to explicitly copy all
// props.
VirtualViewEventEmitter::OnModeChange event = {
.mode = (int)newMode,
.targetRect =
{.x = targetRect.origin.x,
.y = targetRect.origin.y,
.width = targetRect.size.width,
.height = targetRect.size.height},
.thresholdRect =
{.x = thresholdRect.origin.x,
.y = thresholdRect.origin.y,
.width = thresholdRect.size.width,
.height = thresholdRect.size.height},
};
const std::optional<enum RCTVirtualViewMode> oldMode = _mode;
_mode = newMode;
switch (newMode) {
case RCTVirtualViewModeVisible:
if (_renderState == RCTVirtualViewRenderStateUnknown) {
// Feature flag is disabled, so use the former logic.
[self dispatchSyncModeChange:event];
} else {
// If the previous mode was prerender and the result of dispatching that event was committed, we do not need to
// dispatch an event for visible.
const auto wasPrerenderCommitted = oldMode.has_value() && oldMode == RCTVirtualViewModePrerender &&
_renderState == RCTVirtualViewRenderStateRendered;
if (!wasPrerenderCommitted) {
[self dispatchSyncModeChange:event];
}
}
break;
case RCTVirtualViewModePrerender:
if (!oldMode.has_value() || oldMode != RCTVirtualViewModeVisible) {
[self dispatchAsyncModeChange:event];
}
break;
case RCTVirtualViewModeHidden:
[self dispatchAsyncModeChange:event];
break;
}
if (ReactNativeFeatureFlags::hideOffscreenVirtualViewsOnIOS()) {
switch (newMode) {
case RCTVirtualViewModeVisible:
self.hidden = NO;
break;
case RCTVirtualViewModePrerender:
self.hidden = !sIsAccessibilityUsed;
break;
case RCTVirtualViewModeHidden:
self.hidden = YES;
break;
}
}
}
- (void)dispatchAsyncModeChange:(VirtualViewEventEmitter::OnModeChange &)event
{
if (!_eventEmitter) {
return;
}
std::shared_ptr<const VirtualViewEventEmitter> emitter =
std::static_pointer_cast<const VirtualViewEventEmitter>(_eventEmitter);
emitter->onModeChange(event);
}
- (void)dispatchSyncModeChange:(VirtualViewEventEmitter::OnModeChange &)event
{
if (!_eventEmitter) {
return;
}
std::shared_ptr<const VirtualViewEventEmitter> emitter =
std::static_pointer_cast<const VirtualViewEventEmitter>(_eventEmitter);
// TODO: Move this into a custom event emitter. We had to duplicate the codegen code here from onModeChange in order
// to dispatch synchronously and discrete.
emitter->experimental_flushSync([&emitter, &event]() {
emitter->dispatchEvent(
"modeChange",
[event](jsi::Runtime &runtime) {
auto payload = jsi::Object(runtime);
payload.setProperty(runtime, "mode", event.mode);
{
auto targetRect = jsi::Object(runtime);
targetRect.setProperty(runtime, "x", event.targetRect.x);
targetRect.setProperty(runtime, "y", event.targetRect.y);
targetRect.setProperty(runtime, "width", event.targetRect.width);
targetRect.setProperty(runtime, "height", event.targetRect.height);
payload.setProperty(runtime, "targetRect", targetRect);
}
{
auto thresholdRect = jsi::Object(runtime);
thresholdRect.setProperty(runtime, "x", event.thresholdRect.x);
thresholdRect.setProperty(runtime, "y", event.thresholdRect.y);
thresholdRect.setProperty(runtime, "width", event.thresholdRect.width);
thresholdRect.setProperty(runtime, "height", event.thresholdRect.height);
payload.setProperty(runtime, "thresholdRect", thresholdRect);
}
return payload;
},
RawEvent::Category::Discrete);
});
}
+ (ComponentDescriptorProvider)componentDescriptorProvider
{
return concreteComponentDescriptorProvider<VirtualViewExperimentalComponentDescriptor>();
}
@end
Class<RCTComponentViewProtocol> VirtualViewExperimentalCls(void)
{
return RCTVirtualViewExperimentalComponentView.class;
}
@@ -7,4 +7,4 @@
#import <Foundation/Foundation.h>
using ReactTag = NSInteger;
typedef NSInteger ReactTag;
@@ -13,7 +13,7 @@ NS_ASSUME_NONNULL_BEGIN
@class RCTFabricSurface;
using RCTSurfaceEnumeratorBlock = void (^)(NSEnumerator<RCTFabricSurface *> *_Nonnull __strong);
typedef void (^RCTSurfaceEnumeratorBlock)(NSEnumerator<RCTFabricSurface *> *enumerator);
/**
* Registry of Surfaces.
@@ -3286,7 +3286,6 @@ public abstract class com/facebook/react/uimanager/BaseViewManager : com/faceboo
public fun setAccessibilityLabel (Landroid/view/View;Ljava/lang/String;)V
public fun setAccessibilityLabelledBy (Landroid/view/View;Lcom/facebook/react/bridge/Dynamic;)V
public fun setAccessibilityLiveRegion (Landroid/view/View;Ljava/lang/String;)V
public fun setAccessibilityOrder (Landroid/view/View;Lcom/facebook/react/bridge/ReadableArray;)V
public fun setAccessibilityRole (Landroid/view/View;Ljava/lang/String;)V
public fun setAccessibilityValue (Landroid/view/View;Lcom/facebook/react/bridge/ReadableMap;)V
public fun setBackgroundColor (Landroid/view/View;I)V
@@ -3777,6 +3776,14 @@ public final class com/facebook/react/uimanager/ReactAccessibilityDelegate$Role
public static fun values ()[Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$Role;
}
public final class com/facebook/react/uimanager/ReactAxOrderHelper {
public static final field INSTANCE Lcom/facebook/react/uimanager/ReactAxOrderHelper;
public final fun buildAxOrderList (Landroid/view/View;Ljava/util/List;[Landroid/view/View;)V
public static final fun cleanUpAxOrder (Landroid/view/ViewGroup;)V
public final fun disableFocusForSubtree (Landroid/view/ViewGroup;Ljava/util/List;)V
public static final fun restoreFocusability (Landroid/view/ViewGroup;)V
}
public abstract interface class com/facebook/react/uimanager/ReactClippingProhibitedView {
}
@@ -5252,16 +5259,6 @@ public abstract interface class com/facebook/react/viewmanagers/UnimplementedNat
public abstract fun setName (Landroid/view/View;Ljava/lang/String;)V
}
public class com/facebook/react/viewmanagers/VirtualViewExperimentalManagerDelegate : com/facebook/react/uimanager/BaseViewManagerDelegate {
public fun <init> (Lcom/facebook/react/uimanager/BaseViewManager;)V
public fun setProperty (Landroid/view/View;Ljava/lang/String;Ljava/lang/Object;)V
}
public abstract interface class com/facebook/react/viewmanagers/VirtualViewExperimentalManagerInterface : com/facebook/react/uimanager/ViewManagerWithGeneratedInterface {
public abstract fun setInitialHidden (Landroid/view/View;Z)V
public abstract fun setRenderState (Landroid/view/View;I)V
}
public class com/facebook/react/viewmanagers/VirtualViewManagerDelegate : com/facebook/react/uimanager/BaseViewManagerDelegate {
public fun <init> (Lcom/facebook/react/uimanager/BaseViewManager;)V
public fun setProperty (Landroid/view/View;Ljava/lang/String;Ljava/lang/Object;)V
@@ -5706,7 +5703,7 @@ public class com/facebook/react/views/scroll/ReactHorizontalScrollViewManager :
public final class com/facebook/react/views/scroll/ReactHorizontalScrollViewManager$Companion {
}
public class com/facebook/react/views/scroll/ReactScrollView : android/widget/ScrollView, android/view/View$OnLayoutChangeListener, android/view/ViewGroup$OnHierarchyChangeListener, com/facebook/react/uimanager/ReactClippingViewGroup, com/facebook/react/uimanager/ReactOverflowViewWithInset, com/facebook/react/views/scroll/ReactAccessibleScrollView, com/facebook/react/views/scroll/ReactScrollViewHelper$HasFlingAnimator, com/facebook/react/views/scroll/ReactScrollViewHelper$HasScrollEventThrottle, com/facebook/react/views/scroll/ReactScrollViewHelper$HasScrollState, com/facebook/react/views/scroll/ReactScrollViewHelper$HasSmoothScroll, com/facebook/react/views/scroll/ReactScrollViewHelper$HasStateWrapper, com/facebook/react/views/scroll/VirtualViewContainer {
public class com/facebook/react/views/scroll/ReactScrollView : android/widget/ScrollView, android/view/View$OnLayoutChangeListener, android/view/ViewGroup$OnHierarchyChangeListener, com/facebook/react/uimanager/ReactClippingViewGroup, com/facebook/react/uimanager/ReactOverflowViewWithInset, com/facebook/react/views/scroll/ReactAccessibleScrollView, com/facebook/react/views/scroll/ReactScrollViewHelper$HasFlingAnimator, com/facebook/react/views/scroll/ReactScrollViewHelper$HasScrollEventThrottle, com/facebook/react/views/scroll/ReactScrollViewHelper$HasScrollState, com/facebook/react/views/scroll/ReactScrollViewHelper$HasSmoothScroll, com/facebook/react/views/scroll/ReactScrollViewHelper$HasStateWrapper {
public fun <init> (Landroid/content/Context;)V
public fun <init> (Landroid/content/Context;Lcom/facebook/react/views/scroll/FpsListener;)V
public fun abortAnimation ()V
@@ -5734,7 +5731,6 @@ public class com/facebook/react/views/scroll/ReactScrollView : android/widget/Sc
public fun getScrollEventThrottle ()I
public fun getStateWrapper ()Lcom/facebook/react/uimanager/StateWrapper;
protected fun getTopFadingEdgeStrength ()F
public fun getVirtualViewContainerState ()Lcom/facebook/react/views/scroll/VirtualViewContainerState;
protected fun handleInterceptedTouchEvent (Landroid/view/MotionEvent;)V
public fun isPartiallyScrolledInView (Landroid/view/View;)Z
protected fun onAttachedToWindow ()V
@@ -6002,12 +5998,6 @@ public final class com/facebook/react/views/scroll/ScrollEventType$Companion {
public final fun getJSEventName (Lcom/facebook/react/views/scroll/ScrollEventType;)Ljava/lang/String;
}
public abstract interface class com/facebook/react/views/scroll/VirtualView {
public abstract fun getContainerRelativeRect ()Landroid/graphics/Rect;
public abstract fun getVirtualViewID ()Ljava/lang/String;
public abstract fun onModeChange (Lcom/facebook/react/views/virtual/VirtualViewMode;Landroid/graphics/Rect;)V
}
public final class com/facebook/react/views/swiperefresh/ReactSwipeRefreshLayout : androidx/swiperefreshlayout/widget/SwipeRefreshLayout {
public fun <init> (Lcom/facebook/react/bridge/ReactContext;)V
public fun canChildScrollUp ()Z
@@ -6564,6 +6554,8 @@ public final class com/facebook/react/views/view/ReactDrawableHelper {
public class com/facebook/react/views/view/ReactViewGroup : android/view/ViewGroup, com/facebook/react/touch/ReactHitSlopView, com/facebook/react/touch/ReactInterceptingViewGroup, com/facebook/react/uimanager/ReactClippingViewGroup, com/facebook/react/uimanager/ReactOverflowViewWithInset, com/facebook/react/uimanager/ReactPointerEventsView, com/facebook/react/uimanager/ReactZIndexedViewGroup {
public fun <init> (Landroid/content/Context;)V
public fun addChildrenForAccessibility (Ljava/util/ArrayList;)V
public final fun cleanUpAxOrderListener ()V
protected fun dispatchDraw (Landroid/graphics/Canvas;)V
public fun dispatchGenericMotionEvent (Landroid/view/MotionEvent;)Z
public fun dispatchProvideStructure (Landroid/view/ViewStructure;)V
@@ -6571,6 +6563,7 @@ public class com/facebook/react/views/view/ReactViewGroup : android/view/ViewGro
public fun draw (Landroid/graphics/Canvas;)V
protected fun drawChild (Landroid/graphics/Canvas;Landroid/view/View;J)Z
public fun endViewTransition (Landroid/view/View;)V
public final fun getAxOrderList ()Ljava/util/List;
protected fun getChildDrawingOrder (II)I
public fun getClippingRect (Landroid/graphics/Rect;)V
public fun getHitSlopRect ()Landroid/graphics/Rect;
@@ -6590,6 +6583,7 @@ public class com/facebook/react/views/view/ReactViewGroup : android/view/ViewGro
public fun onViewAdded (Landroid/view/View;)V
public fun onViewRemoved (Landroid/view/View;)V
public fun requestLayout ()V
public final fun setAxOrderList (Ljava/util/List;)V
public final fun setBackfaceVisibility (Ljava/lang/String;)V
public final fun setBackfaceVisibilityDependantOpacity ()V
public fun setBackgroundColor (I)V
@@ -6626,12 +6620,15 @@ public class com/facebook/react/views/view/ReactViewManager : com/facebook/react
public fun nextFocusLeft (Lcom/facebook/react/views/view/ReactViewGroup;I)V
public fun nextFocusRight (Lcom/facebook/react/views/view/ReactViewGroup;I)V
public fun nextFocusUp (Lcom/facebook/react/views/view/ReactViewGroup;I)V
public synthetic fun onDropViewInstance (Landroid/view/View;)V
public fun onDropViewInstance (Lcom/facebook/react/views/view/ReactViewGroup;)V
public synthetic fun prepareToRecycleView (Lcom/facebook/react/uimanager/ThemedReactContext;Landroid/view/View;)Landroid/view/View;
protected fun prepareToRecycleView (Lcom/facebook/react/uimanager/ThemedReactContext;Lcom/facebook/react/views/view/ReactViewGroup;)Lcom/facebook/react/views/view/ReactViewGroup;
public synthetic fun receiveCommand (Landroid/view/View;ILcom/facebook/react/bridge/ReadableArray;)V
public synthetic fun receiveCommand (Landroid/view/View;Ljava/lang/String;Lcom/facebook/react/bridge/ReadableArray;)V
public fun receiveCommand (Lcom/facebook/react/views/view/ReactViewGroup;ILcom/facebook/react/bridge/ReadableArray;)V
public fun receiveCommand (Lcom/facebook/react/views/view/ReactViewGroup;Ljava/lang/String;Lcom/facebook/react/bridge/ReadableArray;)V
public fun setAccessibilityOrder (Lcom/facebook/react/views/view/ReactViewGroup;Lcom/facebook/react/bridge/ReadableArray;)V
public fun setAccessible (Lcom/facebook/react/views/view/ReactViewGroup;Z)V
public fun setBackfaceVisibility (Lcom/facebook/react/views/view/ReactViewGroup;Ljava/lang/String;)V
public fun setBackgroundImage (Lcom/facebook/react/views/view/ReactViewGroup;Lcom/facebook/react/bridge/ReadableArray;)V
@@ -6664,79 +6661,3 @@ public final class com/facebook/react/views/view/WindowUtilKt {
public static final fun setEdgeToEdgeFeatureFlagOn ()V
}
public final class com/facebook/react/views/virtual/VirtualViewMode : java/lang/Enum {
public static final field Hidden Lcom/facebook/react/views/virtual/VirtualViewMode;
public static final field Prerender Lcom/facebook/react/views/virtual/VirtualViewMode;
public static final field Visible Lcom/facebook/react/views/virtual/VirtualViewMode;
public static fun getEntries ()Lkotlin/enums/EnumEntries;
public final fun getValue ()I
public static fun valueOf (Ljava/lang/String;)Lcom/facebook/react/views/virtual/VirtualViewMode;
public static fun values ()[Lcom/facebook/react/views/virtual/VirtualViewMode;
}
public final class com/facebook/react/views/virtual/view/ReactVirtualView : com/facebook/react/views/view/ReactViewGroup, android/view/View$OnLayoutChangeListener, com/facebook/react/views/scroll/ReactScrollViewHelper$LayoutChangeListener, com/facebook/react/views/scroll/ReactScrollViewHelper$ScrollListener {
public fun <init> (Landroid/content/Context;)V
public fun onLayout (Landroid/view/ViewGroup;)V
public fun onLayoutChange (Landroid/view/View;IIIIIIII)V
public fun onLayoutChange (Landroid/view/ViewGroup;)V
public fun onScroll (Landroid/view/ViewGroup;Lcom/facebook/react/views/scroll/ScrollEventType;FF)V
public synthetic fun recycleView$xplat_js_react_native_github_packages_react_native_ReactAndroid_src_main_java_com_facebook_react_views_view_viewAndroid ()V
}
public final class com/facebook/react/views/virtual/view/ReactVirtualViewManager : com/facebook/react/uimanager/ViewGroupManager, com/facebook/react/viewmanagers/VirtualViewManagerInterface {
public static final field Companion Lcom/facebook/react/views/virtual/view/ReactVirtualViewManager$Companion;
public static final field REACT_CLASS Ljava/lang/String;
public fun <init> ()V
public synthetic fun addEventEmitters (Lcom/facebook/react/uimanager/ThemedReactContext;Landroid/view/View;)V
public synthetic fun createViewInstance (Lcom/facebook/react/uimanager/ThemedReactContext;)Landroid/view/View;
public fun getName ()Ljava/lang/String;
public synthetic fun prepareToRecycleView (Lcom/facebook/react/uimanager/ThemedReactContext;Landroid/view/View;)Landroid/view/View;
public synthetic fun setInitialHidden (Landroid/view/View;Z)V
public fun setInitialHidden (Lcom/facebook/react/views/virtual/view/ReactVirtualView;Z)V
public synthetic fun setNativeId (Landroid/view/View;Ljava/lang/String;)V
public fun setNativeId (Lcom/facebook/react/views/virtual/view/ReactVirtualView;Ljava/lang/String;)V
public synthetic fun setRenderState (Landroid/view/View;I)V
public fun setRenderState (Lcom/facebook/react/views/virtual/view/ReactVirtualView;I)V
}
public final class com/facebook/react/views/virtual/view/ReactVirtualViewManager$Companion {
}
public final class com/facebook/react/views/virtual/view/VirtualViewEventEmitter : com/facebook/react/views/virtual/VirtualViewModeChangeEmitter {
public fun <init> (IILcom/facebook/react/uimanager/events/EventDispatcher;)V
public fun emitModeChange (Lcom/facebook/react/views/virtual/VirtualViewMode;Landroid/graphics/Rect;Landroid/graphics/Rect;Z)V
}
public final class com/facebook/react/views/virtual/viewexperimental/ReactVirtualViewExperimental : com/facebook/react/views/view/ReactViewGroup, android/view/View$OnLayoutChangeListener, com/facebook/react/views/scroll/VirtualView {
public fun <init> (Landroid/content/Context;)V
public fun getContainerRelativeRect ()Landroid/graphics/Rect;
public fun getVirtualViewID ()Ljava/lang/String;
public fun onLayoutChange (Landroid/view/View;IIIIIIII)V
public fun onModeChange (Lcom/facebook/react/views/virtual/VirtualViewMode;Landroid/graphics/Rect;)V
public synthetic fun recycleView$xplat_js_react_native_github_packages_react_native_ReactAndroid_src_main_java_com_facebook_react_views_view_viewAndroid ()V
}
public final class com/facebook/react/views/virtual/viewexperimental/ReactVirtualViewExperimentalManager : com/facebook/react/uimanager/ViewGroupManager, com/facebook/react/viewmanagers/VirtualViewExperimentalManagerInterface {
public static final field Companion Lcom/facebook/react/views/virtual/viewexperimental/ReactVirtualViewExperimentalManager$Companion;
public static final field REACT_CLASS Ljava/lang/String;
public fun <init> ()V
public synthetic fun addEventEmitters (Lcom/facebook/react/uimanager/ThemedReactContext;Landroid/view/View;)V
public synthetic fun createViewInstance (Lcom/facebook/react/uimanager/ThemedReactContext;)Landroid/view/View;
public fun getName ()Ljava/lang/String;
public synthetic fun prepareToRecycleView (Lcom/facebook/react/uimanager/ThemedReactContext;Landroid/view/View;)Landroid/view/View;
public synthetic fun setInitialHidden (Landroid/view/View;Z)V
public fun setInitialHidden (Lcom/facebook/react/views/virtual/viewexperimental/ReactVirtualViewExperimental;Z)V
public synthetic fun setNativeId (Landroid/view/View;Ljava/lang/String;)V
public fun setNativeId (Lcom/facebook/react/views/virtual/viewexperimental/ReactVirtualViewExperimental;Ljava/lang/String;)V
public synthetic fun setRenderState (Landroid/view/View;I)V
public fun setRenderState (Lcom/facebook/react/views/virtual/viewexperimental/ReactVirtualViewExperimental;I)V
}
public final class com/facebook/react/views/virtual/viewexperimental/ReactVirtualViewExperimentalManager$Companion {
}
public final class com/facebook/react/views/virtual/viewexperimental/VirtualViewEventEmitter : com/facebook/react/views/virtual/VirtualViewModeChangeEmitter {
public fun <init> (IILcom/facebook/react/uimanager/events/EventDispatcher;)V
public fun emitModeChange (Lcom/facebook/react/views/virtual/VirtualViewMode;Landroid/graphics/Rect;Landroid/graphics/Rect;Z)V
}
@@ -112,8 +112,6 @@ val preparePrefab by
Pair(
"../ReactCommon/react/renderer/animations/",
"react/renderer/animations/"),
// react_renderer_bridging
Pair("../ReactCommon/react/renderer/bridging/", "react/renderer/bridging/"),
// react_renderer_componentregistry
Pair(
"../ReactCommon/react/renderer/componentregistry/",
@@ -117,7 +117,6 @@ public class ReactActivityDelegate {
* going away in the New Architecture. You should access {@link ReactHost} instead."
* @noinspection deprecation
*/
@Deprecated
public ReactInstanceManager getReactInstanceManager() {
return Objects.requireNonNull(mReactDelegate).getReactInstanceManager();
}
@@ -83,9 +83,6 @@ internal class ReactAndroidHWInputDeviceHelper(private val reactRootView: ReactR
KeyEvent.KEYCODE_DPAD_DOWN to "down",
KeyEvent.KEYCODE_DPAD_LEFT to "left",
KeyEvent.KEYCODE_INFO to "info",
KeyEvent.KEYCODE_MENU to "menu",
KeyEvent.KEYCODE_CHANNEL_UP to "channelUp",
KeyEvent.KEYCODE_CHANNEL_DOWN to "channelDown",
)
KeyEvent.KEYCODE_MENU to "menu")
}
}
@@ -7,11 +7,21 @@
package com.facebook.react.bridge
import com.facebook.react.common.annotations.internal.LegacyArchitecture
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger
import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
public object JSONArguments {
init {
LegacyArchitectureLogger.assertLegacyArchitecture(
"JSONArguments", LegacyArchitectureLogLevel.ERROR)
}
/**
* Parse JSONObject to ReadableMap
*
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<f45b66a7bbafef525b79c657522d062e>>
* @generated SignedSource<<a4a7c66f4603fc6a56018aba12c942ee>>
*/
/**
@@ -36,6 +36,12 @@ public object ReactNativeFeatureFlags {
@JvmStatic
public fun commonTestFlag(): Boolean = accessor.commonTestFlag()
/**
* Enables start- and finishOperationBatch on any platform.
*/
@JvmStatic
public fun animatedShouldSignalBatch(): Boolean = accessor.animatedShouldSignalBatch()
/**
* Use a C++ implementation of Native Animated instead of the platform implementation.
*/
@@ -48,6 +54,12 @@ public object ReactNativeFeatureFlags {
@JvmStatic
public fun cxxNativeAnimatedRemoveJsSync(): Boolean = accessor.cxxNativeAnimatedRemoveJsSync()
/**
* Disable sync dispatch on the main queue on iOS
*/
@JvmStatic
public fun disableMainQueueSyncDispatchIOS(): Boolean = accessor.disableMainQueueSyncDispatchIOS()
/**
* Prevent FabricMountingManager from reordering mountItems, which may lead to invalid state on the UI thread
*/
@@ -108,12 +120,6 @@ public object ReactNativeFeatureFlags {
@JvmStatic
public fun enableDoubleMeasurementFixAndroid(): Boolean = accessor.enableDoubleMeasurementFixAndroid()
/**
* This infra allows native modules to initialize on the main thread, during React Native init.
*/
@JvmStatic
public fun enableEagerMainQueueModulesOnIOS(): Boolean = accessor.enableEagerMainQueueModulesOnIOS()
/**
* Feature flag to configure eager attachment of the root view/initialisation of the JS code.
*/
@@ -180,6 +186,12 @@ public object ReactNativeFeatureFlags {
@JvmStatic
public fun enableMainQueueCoordinatorOnIOS(): Boolean = accessor.enableMainQueueCoordinatorOnIOS()
/**
* Makes modules requiring main queue setup initialize on the main thread, during React Native init.
*/
@JvmStatic
public fun enableMainQueueModulesOnIOS(): Boolean = accessor.enableMainQueueModulesOnIOS()
/**
* Enable NSNull conversion when handling module arguments on iOS
*/
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<455793458c7d1f7c3efb33a3ae2c017c>>
* @generated SignedSource<<9b6d83d6ea0acbc13bce19d869699079>>
*/
/**
@@ -21,8 +21,10 @@ package com.facebook.react.internal.featureflags
internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccessor {
private var commonTestFlagCache: Boolean? = null
private var animatedShouldSignalBatchCache: Boolean? = null
private var cxxNativeAnimatedEnabledCache: Boolean? = null
private var cxxNativeAnimatedRemoveJsSyncCache: Boolean? = null
private var disableMainQueueSyncDispatchIOSCache: Boolean? = null
private var disableMountItemReorderingAndroidCache: Boolean? = null
private var disableTextLayoutManagerCacheAndroidCache: Boolean? = null
private var enableAccessibilityOrderCache: Boolean? = null
@@ -33,7 +35,6 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
private var enableCustomFocusSearchOnClippedElementsAndroidCache: Boolean? = null
private var enableDestroyShadowTreeRevisionAsyncCache: Boolean? = null
private var enableDoubleMeasurementFixAndroidCache: Boolean? = null
private var enableEagerMainQueueModulesOnIOSCache: Boolean? = null
private var enableEagerRootViewAttachmentCache: Boolean? = null
private var enableFabricLogsCache: Boolean? = null
private var enableFabricRendererCache: Boolean? = null
@@ -45,6 +46,7 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
private var enableLayoutAnimationsOnAndroidCache: Boolean? = null
private var enableLayoutAnimationsOnIOSCache: Boolean? = null
private var enableMainQueueCoordinatorOnIOSCache: Boolean? = null
private var enableMainQueueModulesOnIOSCache: Boolean? = null
private var enableModuleArgumentNSNullConversionIOSCache: Boolean? = null
private var enableNativeCSSParsingCache: Boolean? = null
private var enableNetworkEventReportingCache: Boolean? = null
@@ -86,6 +88,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
return cached
}
override fun animatedShouldSignalBatch(): Boolean {
var cached = animatedShouldSignalBatchCache
if (cached == null) {
cached = ReactNativeFeatureFlagsCxxInterop.animatedShouldSignalBatch()
animatedShouldSignalBatchCache = cached
}
return cached
}
override fun cxxNativeAnimatedEnabled(): Boolean {
var cached = cxxNativeAnimatedEnabledCache
if (cached == null) {
@@ -104,6 +115,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
return cached
}
override fun disableMainQueueSyncDispatchIOS(): Boolean {
var cached = disableMainQueueSyncDispatchIOSCache
if (cached == null) {
cached = ReactNativeFeatureFlagsCxxInterop.disableMainQueueSyncDispatchIOS()
disableMainQueueSyncDispatchIOSCache = cached
}
return cached
}
override fun disableMountItemReorderingAndroid(): Boolean {
var cached = disableMountItemReorderingAndroidCache
if (cached == null) {
@@ -194,15 +214,6 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
return cached
}
override fun enableEagerMainQueueModulesOnIOS(): Boolean {
var cached = enableEagerMainQueueModulesOnIOSCache
if (cached == null) {
cached = ReactNativeFeatureFlagsCxxInterop.enableEagerMainQueueModulesOnIOS()
enableEagerMainQueueModulesOnIOSCache = cached
}
return cached
}
override fun enableEagerRootViewAttachment(): Boolean {
var cached = enableEagerRootViewAttachmentCache
if (cached == null) {
@@ -302,6 +313,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
return cached
}
override fun enableMainQueueModulesOnIOS(): Boolean {
var cached = enableMainQueueModulesOnIOSCache
if (cached == null) {
cached = ReactNativeFeatureFlagsCxxInterop.enableMainQueueModulesOnIOS()
enableMainQueueModulesOnIOSCache = cached
}
return cached
}
override fun enableModuleArgumentNSNullConversionIOS(): Boolean {
var cached = enableModuleArgumentNSNullConversionIOSCache
if (cached == null) {
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<9588b972841baa23bd3bb3b7326b4710>>
* @generated SignedSource<<75760457dea789ab0951d3a22be3341c>>
*/
/**
@@ -30,10 +30,14 @@ public object ReactNativeFeatureFlagsCxxInterop {
@DoNotStrip @JvmStatic public external fun commonTestFlag(): Boolean
@DoNotStrip @JvmStatic public external fun animatedShouldSignalBatch(): Boolean
@DoNotStrip @JvmStatic public external fun cxxNativeAnimatedEnabled(): Boolean
@DoNotStrip @JvmStatic public external fun cxxNativeAnimatedRemoveJsSync(): Boolean
@DoNotStrip @JvmStatic public external fun disableMainQueueSyncDispatchIOS(): Boolean
@DoNotStrip @JvmStatic public external fun disableMountItemReorderingAndroid(): Boolean
@DoNotStrip @JvmStatic public external fun disableTextLayoutManagerCacheAndroid(): Boolean
@@ -54,8 +58,6 @@ public object ReactNativeFeatureFlagsCxxInterop {
@DoNotStrip @JvmStatic public external fun enableDoubleMeasurementFixAndroid(): Boolean
@DoNotStrip @JvmStatic public external fun enableEagerMainQueueModulesOnIOS(): Boolean
@DoNotStrip @JvmStatic public external fun enableEagerRootViewAttachment(): Boolean
@DoNotStrip @JvmStatic public external fun enableFabricLogs(): Boolean
@@ -78,6 +80,8 @@ public object ReactNativeFeatureFlagsCxxInterop {
@DoNotStrip @JvmStatic public external fun enableMainQueueCoordinatorOnIOS(): Boolean
@DoNotStrip @JvmStatic public external fun enableMainQueueModulesOnIOS(): Boolean
@DoNotStrip @JvmStatic public external fun enableModuleArgumentNSNullConversionIOS(): Boolean
@DoNotStrip @JvmStatic public external fun enableNativeCSSParsing(): Boolean
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<7b6a844d99839c72647d6685d72f6896>>
* @generated SignedSource<<48fa8921cc2947a713974c9926e1d806>>
*/
/**
@@ -25,10 +25,14 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
override fun commonTestFlag(): Boolean = false
override fun animatedShouldSignalBatch(): Boolean = false
override fun cxxNativeAnimatedEnabled(): Boolean = false
override fun cxxNativeAnimatedRemoveJsSync(): Boolean = false
override fun disableMainQueueSyncDispatchIOS(): Boolean = false
override fun disableMountItemReorderingAndroid(): Boolean = false
override fun disableTextLayoutManagerCacheAndroid(): Boolean = false
@@ -49,8 +53,6 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
override fun enableDoubleMeasurementFixAndroid(): Boolean = false
override fun enableEagerMainQueueModulesOnIOS(): Boolean = false
override fun enableEagerRootViewAttachment(): Boolean = false
override fun enableFabricLogs(): Boolean = false
@@ -73,6 +75,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
override fun enableMainQueueCoordinatorOnIOS(): Boolean = false
override fun enableMainQueueModulesOnIOS(): Boolean = false
override fun enableModuleArgumentNSNullConversionIOS(): Boolean = false
override fun enableNativeCSSParsing(): Boolean = false
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<d6024891cd1852741976e94cd6d637c6>>
* @generated SignedSource<<356261385b837def94ac5a4ca7ffd05d>>
*/
/**
@@ -25,8 +25,10 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
private val accessedFeatureFlags = mutableSetOf<String>()
private var commonTestFlagCache: Boolean? = null
private var animatedShouldSignalBatchCache: Boolean? = null
private var cxxNativeAnimatedEnabledCache: Boolean? = null
private var cxxNativeAnimatedRemoveJsSyncCache: Boolean? = null
private var disableMainQueueSyncDispatchIOSCache: Boolean? = null
private var disableMountItemReorderingAndroidCache: Boolean? = null
private var disableTextLayoutManagerCacheAndroidCache: Boolean? = null
private var enableAccessibilityOrderCache: Boolean? = null
@@ -37,7 +39,6 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
private var enableCustomFocusSearchOnClippedElementsAndroidCache: Boolean? = null
private var enableDestroyShadowTreeRevisionAsyncCache: Boolean? = null
private var enableDoubleMeasurementFixAndroidCache: Boolean? = null
private var enableEagerMainQueueModulesOnIOSCache: Boolean? = null
private var enableEagerRootViewAttachmentCache: Boolean? = null
private var enableFabricLogsCache: Boolean? = null
private var enableFabricRendererCache: Boolean? = null
@@ -49,6 +50,7 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
private var enableLayoutAnimationsOnAndroidCache: Boolean? = null
private var enableLayoutAnimationsOnIOSCache: Boolean? = null
private var enableMainQueueCoordinatorOnIOSCache: Boolean? = null
private var enableMainQueueModulesOnIOSCache: Boolean? = null
private var enableModuleArgumentNSNullConversionIOSCache: Boolean? = null
private var enableNativeCSSParsingCache: Boolean? = null
private var enableNetworkEventReportingCache: Boolean? = null
@@ -91,6 +93,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
return cached
}
override fun animatedShouldSignalBatch(): Boolean {
var cached = animatedShouldSignalBatchCache
if (cached == null) {
cached = currentProvider.animatedShouldSignalBatch()
accessedFeatureFlags.add("animatedShouldSignalBatch")
animatedShouldSignalBatchCache = cached
}
return cached
}
override fun cxxNativeAnimatedEnabled(): Boolean {
var cached = cxxNativeAnimatedEnabledCache
if (cached == null) {
@@ -111,6 +123,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
return cached
}
override fun disableMainQueueSyncDispatchIOS(): Boolean {
var cached = disableMainQueueSyncDispatchIOSCache
if (cached == null) {
cached = currentProvider.disableMainQueueSyncDispatchIOS()
accessedFeatureFlags.add("disableMainQueueSyncDispatchIOS")
disableMainQueueSyncDispatchIOSCache = cached
}
return cached
}
override fun disableMountItemReorderingAndroid(): Boolean {
var cached = disableMountItemReorderingAndroidCache
if (cached == null) {
@@ -211,16 +233,6 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
return cached
}
override fun enableEagerMainQueueModulesOnIOS(): Boolean {
var cached = enableEagerMainQueueModulesOnIOSCache
if (cached == null) {
cached = currentProvider.enableEagerMainQueueModulesOnIOS()
accessedFeatureFlags.add("enableEagerMainQueueModulesOnIOS")
enableEagerMainQueueModulesOnIOSCache = cached
}
return cached
}
override fun enableEagerRootViewAttachment(): Boolean {
var cached = enableEagerRootViewAttachmentCache
if (cached == null) {
@@ -331,6 +343,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
return cached
}
override fun enableMainQueueModulesOnIOS(): Boolean {
var cached = enableMainQueueModulesOnIOSCache
if (cached == null) {
cached = currentProvider.enableMainQueueModulesOnIOS()
accessedFeatureFlags.add("enableMainQueueModulesOnIOS")
enableMainQueueModulesOnIOSCache = cached
}
return cached
}
override fun enableModuleArgumentNSNullConversionIOS(): Boolean {
var cached = enableModuleArgumentNSNullConversionIOSCache
if (cached == null) {
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<391d35ccb9b7004fd8d9643df9a08ab5>>
* @generated SignedSource<<8abf9bfb81265ae0c840457eb6c199bd>>
*/
/**
@@ -25,10 +25,14 @@ import com.facebook.proguard.annotations.DoNotStrip
public interface ReactNativeFeatureFlagsProvider {
@DoNotStrip public fun commonTestFlag(): Boolean
@DoNotStrip public fun animatedShouldSignalBatch(): Boolean
@DoNotStrip public fun cxxNativeAnimatedEnabled(): Boolean
@DoNotStrip public fun cxxNativeAnimatedRemoveJsSync(): Boolean
@DoNotStrip public fun disableMainQueueSyncDispatchIOS(): Boolean
@DoNotStrip public fun disableMountItemReorderingAndroid(): Boolean
@DoNotStrip public fun disableTextLayoutManagerCacheAndroid(): Boolean
@@ -49,8 +53,6 @@ public interface ReactNativeFeatureFlagsProvider {
@DoNotStrip public fun enableDoubleMeasurementFixAndroid(): Boolean
@DoNotStrip public fun enableEagerMainQueueModulesOnIOS(): Boolean
@DoNotStrip public fun enableEagerRootViewAttachment(): Boolean
@DoNotStrip public fun enableFabricLogs(): Boolean
@@ -73,6 +75,8 @@ public interface ReactNativeFeatureFlagsProvider {
@DoNotStrip public fun enableMainQueueCoordinatorOnIOS(): Boolean
@DoNotStrip public fun enableMainQueueModulesOnIOS(): Boolean
@DoNotStrip public fun enableModuleArgumentNSNullConversionIOS(): Boolean
@DoNotStrip public fun enableNativeCSSParsing(): Boolean
@@ -30,7 +30,6 @@ import com.facebook.react.bridge.ReadableMapKeySetIterator;
import com.facebook.react.bridge.ReadableType;
import com.facebook.react.common.MapBuilder;
import com.facebook.react.common.ReactConstants;
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags;
import com.facebook.react.uimanager.ReactAccessibilityDelegate.AccessibilityRole;
import com.facebook.react.uimanager.ReactAccessibilityDelegate.Role;
import com.facebook.react.uimanager.annotations.ReactProp;
@@ -312,61 +311,9 @@ public abstract class BaseViewManager<T extends View, C extends LayoutShadowNode
public void setNativeId(@NonNull T view, @Nullable String nativeId) {
view.setTag(R.id.view_tag_native_id, nativeId);
/*
* If we change the nativeId we need to notify the relevant accessibility parent to update the
* focusing order.
*/
if (view.getTag(R.id.accessibility_order_parent) != null) {
ViewGroup accessibilityParent = (ViewGroup) view.getTag(R.id.accessibility_order_parent);
accessibilityParent.setTag(R.id.accessibility_order_dirty, true);
accessibilityParent.notifySubtreeAccessibilityStateChanged(
accessibilityParent, accessibilityParent, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
}
ReactFindViewUtil.notifyViewRendered(view);
}
@ReactProp(name = ViewProps.ACCESSIBILITY_ORDER)
public void setAccessibilityOrder(@NonNull T view, @Nullable ReadableArray nativeIds) {
if (!ReactNativeFeatureFlags.enableAccessibilityOrder()) {
return;
}
view.setTag(R.id.accessibility_order, nativeIds);
view.setTag(R.id.accessibility_order_dirty, true);
if (view instanceof ViewGroup) {
((ViewGroup) view)
.setOnHierarchyChangeListener(
new ViewGroup.OnHierarchyChangeListener() {
@Override
public void onChildViewAdded(View parent, View child) {
view.setTag(R.id.accessibility_order_dirty, true);
// We also want to listen to changes on the hierarchy of nested ViewGroups
if (child instanceof ViewGroup) {
ViewGroup childGroup = (ViewGroup) child;
childGroup.setOnHierarchyChangeListener(this);
for (int i = 0; i < childGroup.getChildCount(); i++) {
onChildViewAdded(childGroup, childGroup.getChildAt(i));
}
}
}
@Override
public void onChildViewRemoved(View parent, View child) {
view.setTag(R.id.accessibility_order_dirty, true);
}
});
((ViewGroup) view)
.notifySubtreeAccessibilityStateChanged(
view, view, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
}
}
@ReactProp(name = ViewProps.ACCESSIBILITY_LABELLED_BY)
public void setAccessibilityLabelledBy(@NonNull T view, @Nullable Dynamic nativeId) {
if (nativeId.isNull()) {
@@ -91,10 +91,7 @@ public abstract class BaseViewManagerDelegate<
val dynamicFromObject: Dynamic = DynamicFromObject(value)
mViewManager.setAccessibilityLabelledBy(view, dynamicFromObject)
}
ViewProps.ACCESSIBILITY_ORDER ->
mViewManager.setAccessibilityOrder(view, value as ReadableArray?)
ViewProps.OPACITY -> mViewManager.setOpacity(view, (value as Double?)?.toFloat() ?: 1.0f)
ViewProps.OUTLINE_COLOR -> mViewManager.setOutlineColor(view, value as Int?)
ViewProps.OUTLINE_OFFSET ->
@@ -0,0 +1,103 @@
/*
* 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.uimanager
import android.view.View
import android.view.ViewGroup
import com.facebook.react.R
public object ReactAxOrderHelper {
@JvmStatic
public fun cleanUpAxOrder(host: ViewGroup) {
fun traverse(view: View) {
val originalFocusability = view.getTag(R.id.original_focusability) as Boolean?
if (originalFocusability != null) {
view.isFocusable = originalFocusability
}
val axOrderParent = view.getTag(R.id.accessibility_order_parent) as View?
if (axOrderParent != null) {
view.setTag(R.id.accessibility_order_parent, null)
}
if (view is ViewGroup) {
for (i in 0..<view.childCount) {
traverse(view.getChildAt(i))
}
}
}
for (i in 0..<host.childCount) {
traverse(host.getChildAt(i))
}
}
@JvmStatic
public fun restoreFocusability(host: ViewGroup) {
fun traverse(view: View) {
val originalFocusability = view.getTag(R.id.original_focusability) as Boolean?
if (originalFocusability != null) {
view.isFocusable = originalFocusability
}
if (view is ViewGroup) {
for (i in 0..<view.childCount) {
traverse(view.getChildAt(i))
}
}
}
for (i in 0..<host.childCount) {
traverse(host.getChildAt(i))
}
}
public fun disableFocusForSubtree(view: ViewGroup, axOrderList: MutableList<*>) {
fun traverse(view: View) {
if (!axOrderList.contains(view.getTag(R.id.view_tag_native_id))) {
if (view.getTag(R.id.original_focusability) == null) {
view.setTag(R.id.original_focusability, view.isFocusable)
}
view.isFocusable = false
}
if (view is ViewGroup) {
for (i in 0..<view.childCount) {
traverse(view.getChildAt(i))
}
}
}
for (i in 0..<view.childCount) {
traverse(view.getChildAt(i))
}
}
public fun buildAxOrderList(
view: View,
axOrderList: MutableList<*>,
result: Array<View?>,
) {
val nativeId = view.getTag(R.id.view_tag_native_id)
view.setTag(R.id.accessibility_order_parent, this)
if (axOrderList.contains(nativeId)) {
val idx = axOrderList.indexOf(nativeId)
if (idx != -1) {
result[idx] = view
}
}
if (view is ViewGroup) {
for (i in 0..<view.childCount) {
buildAxOrderList(view.getChildAt(i), axOrderList, result)
}
}
}
}
@@ -86,8 +86,7 @@ public class ReactScrollView extends ScrollView
HasStateWrapper,
HasFlingAnimator,
HasScrollEventThrottle,
HasSmoothScroll,
VirtualViewContainer {
HasSmoothScroll {
private static @Nullable Field sScrollerField;
private static boolean sTriedToGetScrollerField = false;
@@ -100,7 +99,6 @@ public class ReactScrollView extends ScrollView
private final Rect mTempRect = new Rect();
private final Rect mOverflowInset = new Rect();
private @Nullable VirtualViewContainerState mVirtualViewContainerState;
private boolean mActivelyScrolling;
private @Nullable Rect mClippingRect;
private Overflow mOverflow = Overflow.SCROLL;
@@ -152,15 +150,6 @@ public class ReactScrollView extends ScrollView
ViewCompat.setAccessibilityDelegate(this, new ReactScrollViewAccessibilityDelegate());
}
@Override
public VirtualViewContainerState getVirtualViewContainerState() {
if (mVirtualViewContainerState == null) {
mVirtualViewContainerState = new VirtualViewContainerState(this);
}
return mVirtualViewContainerState;
}
@Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
@@ -1,136 +0,0 @@
/*
* 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.views.scroll
import android.graphics.Rect
import android.view.ViewGroup
import com.facebook.common.logging.FLog
import com.facebook.react.common.build.ReactBuildConfig
import com.facebook.react.views.virtual.VirtualViewMode
import java.util.*
internal interface VirtualViewContainer {
public val virtualViewContainerState: VirtualViewContainerState
}
public interface VirtualView {
public val virtualViewID: String
public val containerRelativeRect: Rect
public fun onModeChange(newMode: VirtualViewMode, thresholdRect: Rect): Unit
}
/**
* Checks whether one Rect overlaps with another Rect.
*
* This is different from [Rect.intersects] because a Rect representing a line or a point is
* considered to overlap with another Rect if the line or point is within the rect bounds. However,
* two Rects are not considered to overlap if they only share a boundary.
*/
private fun rectsOverlap(rect1: Rect, rect2: Rect): Boolean {
if (rect1.top >= rect2.bottom || rect2.top >= rect1.bottom) {
// No overlap on the y-axis.
return false
}
if (rect1.left >= rect2.right || rect2.left >= rect1.right) {
// No overlap on the x-axis.
return false
}
return true
}
internal class VirtualViewContainerState(private val scrollView: ViewGroup) :
ReactScrollViewHelper.ScrollListener {
private val prerenderRatio: Int = 1
private val virtualViews: MutableSet<VirtualView> = mutableSetOf()
private val emptyRect: Rect = Rect()
private val visibleRect: Rect = Rect()
private val prerenderRect: Rect = Rect()
init {
ReactScrollViewHelper.addScrollListener(this)
}
public fun add(virtualView: VirtualView) {
assert(virtualViews.add(virtualView)) {
"Attempting to add duplicate VirtualView: ${virtualView.virtualViewID}"
}
updateModes(virtualView)
}
public fun remove(virtualView: VirtualView) {
assert(virtualViews.remove(virtualView)) {
"Attempting to remove non-existent VirtualView: ${virtualView.virtualViewID}"
}
}
// ReactScrollViewHelper.ScrollListener.onLayout
// Emitted from ScrollView's onLayout
override fun onLayout(scrollView: ViewGroup?) {
// ReactScrollViewHelper is global
if (this.scrollView == scrollView) {
debugLog("ReactScrollViewHelper.onLayout")
updateModes()
}
}
// ReactScrollViewHelper.ScrollListener.onScroll
// Emitted from ScrollView's onLayout
override fun onScroll(
scrollView: ViewGroup?,
scrollEventType: ScrollEventType?,
xVelocity: Float,
yVelocity: Float
) {
// ReactScrollViewHelper is global
if (this.scrollView == scrollView) {
debugLog("ReactScrollViewHelper.onScroll")
updateModes()
}
}
public fun update(virtualView: VirtualView) {
updateModes(virtualView)
}
private fun updateModes(virtualView: VirtualView? = null) {
scrollView.getDrawingRect(visibleRect)
prerenderRect.set(visibleRect)
prerenderRect.inset(
(-prerenderRect.width() * prerenderRatio).toInt(),
(-prerenderRect.height() * prerenderRatio).toInt())
val virtualViewsIt = if (virtualView != null) listOf(virtualView) else virtualViews
virtualViewsIt.forEach { vv ->
val rect = vv.containerRelativeRect
when {
rectsOverlap(rect, visibleRect) -> {
vv.onModeChange(VirtualViewMode.Visible, visibleRect)
}
rectsOverlap(rect, prerenderRect) -> {
vv.onModeChange(VirtualViewMode.Prerender, prerenderRect)
}
else -> {
vv.onModeChange(VirtualViewMode.Hidden, emptyRect)
}
}
}
}
}
private const val DEBUG_TAG: String = "VirtualViewContainerState"
private val IS_DEBUG_BUILD =
ReactBuildConfig.DEBUG || ReactBuildConfig.IS_INTERNAL_BUILD || ReactBuildConfig.ENABLE_PERFETTO
internal inline fun debugLog(subtag: String, block: () -> String = { "" }) {
if (IS_DEBUG_BUILD) {
FLog.d("$DEBUG_TAG:$subtag", block())
}
}
@@ -10,16 +10,26 @@ package com.facebook.react.views.textinput
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.WritableMap
import com.facebook.react.bridge.buildReadableMap
import com.facebook.react.uimanager.common.ViewUtil
import com.facebook.react.uimanager.events.Event
/** Event emitted by EditText native view when content size changes. */
internal class ReactContentSizeChangedEvent
constructor(
internal class ReactContentSizeChangedEvent(
surfaceId: Int,
viewId: Int,
private val contentWidth: Float,
private val contentHeight: Float
) : Event<ReactTextChangedEvent>(surfaceId, viewId) {
@Deprecated(
"Use the constructor with surfaceId instead",
ReplaceWith(
"ReactContentSizeChangedEvent(surfaceId, viewId, contentSizeWidth, contentSizeHeight)"))
constructor(
viewId: Int,
contentSizeWidth: Float,
contentSizeHeight: Float
) : this(ViewUtil.NO_SURFACE_ID, viewId, contentSizeWidth, contentSizeHeight)
override fun getEventName(): String = EVENT_NAME
override fun getEventData(): WritableMap {
@@ -9,6 +9,7 @@ package com.facebook.react.views.textinput
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.WritableMap
import com.facebook.react.uimanager.common.ViewUtil
import com.facebook.react.uimanager.events.Event
/** Event emitted by EditText native view when text changes. */
@@ -18,6 +19,15 @@ internal class ReactTextChangedEvent(
private val text: String,
private val eventCount: Int
) : Event<ReactTextChangedEvent>(surfaceId, viewId) {
@Deprecated(
"Use the constructor with surfaceId instead",
ReplaceWith("ReactTextChangedEvent(surfaceId, viewId, text, eventCount)"))
constructor(
viewId: Int,
text: String,
eventCount: Int
) : this(ViewUtil.NO_SURFACE_ID, viewId, text, eventCount)
override fun getEventName(): String = EVENT_NAME
override fun getEventData(): WritableMap {
@@ -9,6 +9,7 @@ package com.facebook.react.views.textinput
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.WritableMap
import com.facebook.react.uimanager.common.ViewUtil
import com.facebook.react.uimanager.events.Event
/**
@@ -20,6 +21,11 @@ internal class ReactTextInputEndEditingEvent(
viewId: Int,
private val text: String
) : Event<ReactTextInputEndEditingEvent>(surfaceId, viewId) {
@Deprecated(
"Use the constructor with surfaceId instead",
ReplaceWith("ReactTextInputEndEditingEvent(surfaceId, viewId, text)"))
constructor(viewId: Int, text: String) : this(ViewUtil.NO_SURFACE_ID, viewId, text)
override fun getEventName(): String = EVENT_NAME
override fun canCoalesce(): Boolean = false
@@ -9,11 +9,17 @@ package com.facebook.react.views.textinput
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.WritableMap
import com.facebook.react.uimanager.common.ViewUtil
import com.facebook.react.uimanager.events.Event
/** Event emitted by EditText native view when key pressed. */
internal class ReactTextInputKeyPressEvent(surfaceId: Int, viewId: Int, private val key: String) :
Event<ReactTextInputKeyPressEvent>(surfaceId, viewId) {
@Deprecated(
"Use the constructor with surfaceId instead",
ReplaceWith("ReactTextInputKeyPressEvent(surfaceId, viewId, key)"))
constructor(viewId: Int, key: String) : this(ViewUtil.NO_SURFACE_ID, viewId, key)
override fun getEventName(): String = EVENT_NAME
override fun getEventData(): WritableMap {
@@ -10,6 +10,7 @@ package com.facebook.react.views.textinput
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.WritableMap
import com.facebook.react.bridge.buildReadableMap
import com.facebook.react.uimanager.common.ViewUtil
import com.facebook.react.uimanager.events.Event
/** Event emitted by EditText native view when the text selection changes. */
@@ -19,6 +20,15 @@ internal class ReactTextInputSelectionEvent(
private val selectionStart: Int,
private val selectionEnd: Int
) : Event<ReactTextInputSelectionEvent>(surfaceId, viewId) {
@Deprecated(
"Use the constructor with surfaceId instead",
ReplaceWith("ReactTextInputSelectionEvent(surfaceId, viewId, selectionStart, selectionEnd)"))
constructor(
viewId: Int,
selectionStart: Int,
selectionEnd: Int
) : this(ViewUtil.NO_SURFACE_ID, viewId, selectionStart, selectionEnd)
override fun getEventName(): String = EVENT_NAME
override fun getEventData(): WritableMap {
@@ -9,6 +9,7 @@ package com.facebook.react.views.textinput
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.WritableMap
import com.facebook.react.uimanager.common.ViewUtil
import com.facebook.react.uimanager.events.Event
/** Event emitted by EditText native view when the user submits the text. */
@@ -17,6 +18,11 @@ internal class ReactTextInputSubmitEditingEvent(
viewId: Int,
private val text: String
) : Event<ReactTextInputSubmitEditingEvent>(surfaceId, viewId) {
@Deprecated(
"Use the constructor with surfaceId instead",
ReplaceWith("ReactTextInputSubmitEditingEvent(surfaceId, viewId, text)"))
constructor(viewId: Int, text: String) : this(ViewUtil.NO_SURFACE_ID, viewId, text)
override fun getEventName(): String = EVENT_NAME
override fun getEventData(): WritableMap {
@@ -22,6 +22,7 @@ import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.view.ViewStructure
import android.view.accessibility.AccessibilityManager
import com.facebook.common.logging.FLog
import com.facebook.react.R
import com.facebook.react.bridge.ReactNoCrashSoftException
@@ -49,6 +50,7 @@ import com.facebook.react.uimanager.PixelUtil.toDIPFromPixel
import com.facebook.react.uimanager.PointerEvents
import com.facebook.react.uimanager.PointerEvents.Companion.canBeTouchTarget
import com.facebook.react.uimanager.PointerEvents.Companion.canChildrenBeTouchTarget
import com.facebook.react.uimanager.ReactAxOrderHelper
import com.facebook.react.uimanager.ReactClippingProhibitedView
import com.facebook.react.uimanager.ReactClippingViewGroup
import com.facebook.react.uimanager.ReactClippingViewGroupHelper.calculateClippingRect
@@ -63,6 +65,7 @@ import com.facebook.react.uimanager.style.BorderStyle
import com.facebook.react.uimanager.style.LogicalEdge
import com.facebook.react.uimanager.style.Overflow
import com.facebook.react.views.view.CanvasUtil.enableZ
import java.util.ArrayList
import kotlin.concurrent.Volatile
import kotlin.math.max
@@ -139,12 +142,17 @@ public open class ReactViewGroup public constructor(context: Context?) :
public override var hitSlopRect: Rect? = null
public override var pointerEvents: PointerEvents = PointerEvents.AUTO
public var axOrderList: MutableList<String>? = null
private var childrenLayoutChangeListener: ChildrenLayoutChangeListener? = null
private var onInterceptTouchEventListener: OnInterceptTouchEventListener? = null
private var needsOffscreenAlphaCompositing = false
private var backfaceOpacity = 0f
private var backfaceVisible = false
private var childrenRemovedWhileTransitioning: MutableSet<Int>? = null
private var accessibilityStateChangeListener:
AccessibilityManager.AccessibilityStateChangeListener? =
null
init {
initView()
@@ -931,6 +939,70 @@ public open class ReactViewGroup public constructor(context: Context?) :
alpha = 0f
}
override fun addChildrenForAccessibility(outChildren: ArrayList<View>) {
val axOrderParentOrderList =
(getTag(R.id.accessibility_order_parent) as ReactViewGroup?)?.axOrderList
val axOrder: MutableList<*>? = axOrderList
if (axOrder != null) {
val am: AccessibilityManager? =
this.getContext().getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager?
if (accessibilityStateChangeListener == null && am != null) {
val newAccessibilityStateChangeListener =
AccessibilityManager.AccessibilityStateChangeListener { enabled ->
if (!enabled) {
ReactAxOrderHelper.restoreFocusability(this)
}
}
am.addAccessibilityStateChangeListener(newAccessibilityStateChangeListener)
accessibilityStateChangeListener = newAccessibilityStateChangeListener
}
val result = arrayOfNulls<View?>(axOrder.size)
for (i in 0..<childCount) {
ReactAxOrderHelper.buildAxOrderList(getChildAt(i), axOrder, result)
}
for (i in result.indices) {
val view = result[i]
if (view != null) {
if (view.isFocusable) {
outChildren.add(view)
} else {
view.addChildrenForAccessibility(outChildren)
}
}
}
} else if (axOrderParentOrderList != null) {
// view is a container so add its children normally
if (!isFocusable) {
super.addChildrenForAccessibility(outChildren)
return
// If this view can coopt, turn the focusability off its children but add them to the tree
} else if (isFocusable && (contentDescription == null || contentDescription == "")) {
super.addChildrenForAccessibility(outChildren)
ReactAxOrderHelper.disableFocusForSubtree(this, axOrderParentOrderList)
// if this view is focusable and has a contentDescription then we don't care about its
// descendants for accessibility
} else if (isFocusable && !(contentDescription == null || contentDescription == "")) {
return
}
} else {
super.addChildrenForAccessibility(outChildren)
}
}
public fun cleanUpAxOrderListener() {
val am = this.context.getSystemService(Context.ACCESSIBILITY_SERVICE) as? AccessibilityManager
if (am != null) {
accessibilityStateChangeListener?.let { am.removeAccessibilityStateChangeListener(it) }
}
accessibilityStateChangeListener = null
}
private companion object {
private const val ARRAY_CAPACITY_INCREMENT = 12
private val defaultLayoutParam = LayoutParams(0, 0)
@@ -25,6 +25,7 @@ import com.facebook.react.uimanager.LengthPercentage
import com.facebook.react.uimanager.LengthPercentageType
import com.facebook.react.uimanager.PixelUtil.dpToPx
import com.facebook.react.uimanager.PointerEvents
import com.facebook.react.uimanager.ReactAxOrderHelper
import com.facebook.react.uimanager.Spacing
import com.facebook.react.uimanager.ThemedReactContext
import com.facebook.react.uimanager.UIManagerHelper
@@ -83,11 +84,41 @@ public open class ReactViewManager : ReactClippingViewManager<ReactViewGroup>()
return preparedView
}
override fun onDropViewInstance(view: ReactViewGroup) {
super.onDropViewInstance(view)
view.cleanUpAxOrderListener()
}
@ReactProp(name = "accessible")
public open fun setAccessible(view: ReactViewGroup, accessible: Boolean) {
view.isFocusable = accessible
}
@ReactProp(name = ViewProps.ACCESSIBILITY_ORDER)
public open fun setAccessibilityOrder(view: ReactViewGroup, nativeIds: ReadableArray?) {
if (!ReactNativeFeatureFlags.enableAccessibilityOrder()) {
return
}
ReactAxOrderHelper.cleanUpAxOrder(view)
if (nativeIds == null) {
view.axOrderList = null
return
}
val axOrderList = mutableListOf<String>()
for (i in 0 until nativeIds.size()) {
val id = nativeIds.getString(i)
if (id != null) {
axOrderList.add(id)
}
}
view.axOrderList = axOrderList
}
@ReactProp(name = "hasTVPreferredFocus")
public open fun setTVPreferredFocus(view: ReactViewGroup, hasTVPreferredFocus: Boolean) {
if (hasTVPreferredFocus) {
@@ -7,7 +7,7 @@
package com.facebook.react.views.virtual
public enum class VirtualViewMode(public val value: Int) {
internal enum class VirtualViewMode(val value: Int) {
Visible(0),
Prerender(1),
Hidden(2),
@@ -1,19 +0,0 @@
/*
* 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.views.virtual
import android.graphics.Rect
internal fun interface VirtualViewModeChangeEmitter {
public fun emitModeChange(
mode: VirtualViewMode,
targetRect: Rect,
thresholdRect: Rect,
synchronous: Boolean,
)
}
@@ -25,11 +25,10 @@ import com.facebook.react.views.scroll.ReactScrollViewHelper
import com.facebook.react.views.scroll.ScrollEventType
import com.facebook.react.views.view.ReactViewGroup
import com.facebook.react.views.virtual.VirtualViewMode
import com.facebook.react.views.virtual.VirtualViewModeChangeEmitter
import com.facebook.react.views.virtual.VirtualViewRenderState
import com.facebook.systrace.Systrace
public class ReactVirtualView(context: Context) :
internal class ReactVirtualView(context: Context) :
ReactViewGroup(context),
ReactScrollViewHelper.ScrollListener,
ReactScrollViewHelper.LayoutChangeListener,
@@ -37,7 +36,7 @@ public class ReactVirtualView(context: Context) :
internal var mode: VirtualViewMode? = null
internal var renderState: VirtualViewRenderState = VirtualViewRenderState.Unknown
internal var modeChangeEmitter: VirtualViewModeChangeEmitter? = null
internal var modeChangeEmitter: ModeChangeEmitter? = null
internal var prerenderRatio: Double = ReactNativeFeatureFlags.virtualViewPrerenderRatio()
internal val debugLogEnabled: Boolean = ReactNativeFeatureFlags.enableVirtualViewDebugFeatures()
internal val detectWindowFocus = ReactNativeFeatureFlags.enableVirtualViewWindowFocusDetection()
@@ -370,6 +369,15 @@ public class ReactVirtualView(context: Context) :
}
}
internal fun interface ModeChangeEmitter {
fun emitModeChange(
mode: VirtualViewMode,
targetRect: Rect,
thresholdRect: Rect,
synchronous: Boolean,
)
}
private const val DEBUG_TAG: String = "ReactVirtualView"
private val IS_DEBUG_BUILD =
@@ -20,12 +20,11 @@ import com.facebook.react.uimanager.events.EventDispatcher
import com.facebook.react.viewmanagers.VirtualViewManagerDelegate
import com.facebook.react.viewmanagers.VirtualViewManagerInterface
import com.facebook.react.views.virtual.VirtualViewMode
import com.facebook.react.views.virtual.VirtualViewModeChangeEmitter
import com.facebook.react.views.virtual.VirtualViewModeChangeEvent
import com.facebook.react.views.virtual.VirtualViewRenderState
@ReactModule(name = ReactVirtualViewManager.REACT_CLASS)
public class ReactVirtualViewManager :
internal class ReactVirtualViewManager :
ViewGroupManager<ReactVirtualView>(), VirtualViewManagerInterface<ReactVirtualView> {
private val _delegate = VirtualViewManagerDelegate(this)
@@ -82,11 +81,11 @@ public class ReactVirtualViewManager :
}
@VisibleForTesting
public class VirtualViewEventEmitter(
internal class VirtualViewEventEmitter(
private val viewId: Int,
private val surfaceId: Int,
private val dispatcher: EventDispatcher
) : VirtualViewModeChangeEmitter {
) : ModeChangeEmitter {
override fun emitModeChange(
mode: VirtualViewMode,
targetRect: Rect,
@@ -1,200 +0,0 @@
/*
* 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.views.virtual.viewexperimental
import android.content.Context
import android.graphics.Rect
import android.view.View
import android.view.ViewParent
import androidx.annotation.VisibleForTesting
import com.facebook.common.logging.FLog
import com.facebook.react.R
import com.facebook.react.common.build.ReactBuildConfig
import com.facebook.react.uimanager.ReactRoot
import com.facebook.react.views.scroll.VirtualView
import com.facebook.react.views.scroll.VirtualViewContainer
import com.facebook.react.views.view.ReactViewGroup
import com.facebook.react.views.virtual.VirtualViewMode
import com.facebook.react.views.virtual.VirtualViewModeChangeEmitter
import com.facebook.react.views.virtual.VirtualViewRenderState
public class ReactVirtualViewExperimental(context: Context) :
ReactViewGroup(context), VirtualView, View.OnLayoutChangeListener {
internal var mode: VirtualViewMode? = null
internal var modeChangeEmitter: VirtualViewModeChangeEmitter? = null
internal var renderState: VirtualViewRenderState = VirtualViewRenderState.Unknown
private var scrollView: VirtualViewContainer? = null
override val containerRelativeRect: Rect = Rect()
private var offsetX: Int = 0
private var offsetY: Int = 0
internal val nativeId: String?
get() = getTag(R.id.view_tag_native_id) as? String
override fun onAttachedToWindow() {
super.onAttachedToWindow()
doAttachedToWindow()
}
@VisibleForTesting
internal fun doAttachedToWindow() {
// Assuming that layout has been called before this
scrollView = getScrollView()?.also { scrollView?.virtualViewContainerState?.add(this) }
}
/** From [View#onLayout] */
// This is when the view itself has layout changes
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
super.onLayout(changed, left, top, right, bottom)
if (changed) {
containerRelativeRect.set(
left + offsetX,
top + offsetY,
right + offsetX,
bottom + offsetY,
)
updateContainer()
}
}
// Here we're subscribing to all parent views up to scrollView and when their layout changes
override fun onLayoutChange(
v: View?,
left: Int,
top: Int,
right: Int,
bottom: Int,
oldLeft: Int,
oldTop: Int,
oldRight: Int,
oldBottom: Int
) {
if (oldLeft != left || oldTop != top) {
val virtualViewScrollView = scrollView ?: return
offsetX = 0
offsetY = 0
var parent: ViewParent? = parent
while (parent != null && parent != virtualViewScrollView) {
if (parent is View) {
offsetX += parent.left
offsetY += parent.top
}
parent = parent.parent
}
containerRelativeRect.set(
left + offsetX,
top + offsetY,
right + offsetX,
bottom + offsetY,
)
updateContainer()
}
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
recycleView()
}
override internal fun recycleView() {
cleanupLayoutListeners()
scrollView?.virtualViewContainerState?.remove(this)
scrollView = null
mode = null
modeChangeEmitter = null
}
override val virtualViewID: String
get() {
return "${nativeId ?: "unknown"}:${id}"
}
override fun onModeChange(newMode: VirtualViewMode, thresholdRect: Rect) {
if (newMode == mode) {
return
}
val oldMode = mode
mode = newMode
debugLog("onModeChange") { "$oldMode->$newMode" }
when (newMode) {
VirtualViewMode.Visible -> {
if (renderState == VirtualViewRenderState.Unknown) {
// Feature flag is disabled, so use the former logic.
modeChangeEmitter?.emitModeChange(
VirtualViewMode.Visible, containerRelativeRect, thresholdRect, synchronous = true)
} else {
// If the previous mode was prerender and the result of dispatching that event was
// committed, we do not need to dispatch an event for visible.
val wasPrerenderCommitted =
oldMode == VirtualViewMode.Prerender && renderState == VirtualViewRenderState.Rendered
if (!wasPrerenderCommitted) {
modeChangeEmitter?.emitModeChange(
VirtualViewMode.Visible, containerRelativeRect, thresholdRect, synchronous = true)
}
}
}
VirtualViewMode.Prerender -> {
if (oldMode != VirtualViewMode.Visible) {
modeChangeEmitter?.emitModeChange(
VirtualViewMode.Prerender, containerRelativeRect, thresholdRect, synchronous = false)
}
}
VirtualViewMode.Hidden -> {
modeChangeEmitter?.emitModeChange(
VirtualViewMode.Hidden, containerRelativeRect, thresholdRect, synchronous = false)
}
}
}
private fun updateContainer() {
scrollView?.virtualViewContainerState?.update(this)
}
private fun getScrollView(): VirtualViewContainer? = traverseParentStack(true)
private fun cleanupLayoutListeners() {
traverseParentStack(false)
}
private fun traverseParentStack(addListeners: Boolean): VirtualViewContainer? {
var parent: ViewParent? = parent
while (parent != null) {
if (parent is VirtualViewContainer) {
return parent
}
if (parent is ReactRoot) {
// don't look past the root - it could traverse into a separate hierarchy
return null
}
if (parent is View) {
// always remove, to ensure listeners aren't added more than once
parent.removeOnLayoutChangeListener(this)
if (addListeners) {
parent.addOnLayoutChangeListener(this)
}
}
parent = parent.parent
}
return null
}
internal inline fun debugLog(subtag: String, block: () -> String = { "" }) {
if (IS_DEBUG_BUILD) {
FLog.d("$DEBUG_TAG:$subtag", "${block()} [$id][$nativeId]")
}
}
}
private const val DEBUG_TAG: String = "ReactVirtualViewExperimental"
private val IS_DEBUG_BUILD =
ReactBuildConfig.DEBUG || ReactBuildConfig.IS_INTERNAL_BUILD || ReactBuildConfig.ENABLE_PERFETTO
@@ -1,109 +0,0 @@
/*
* 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.views.virtual.viewexperimental
import android.graphics.Rect
import androidx.annotation.VisibleForTesting
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags
import com.facebook.react.module.annotations.ReactModule
import com.facebook.react.uimanager.ThemedReactContext
import com.facebook.react.uimanager.UIManagerHelper
import com.facebook.react.uimanager.ViewGroupManager
import com.facebook.react.uimanager.ViewManagerDelegate
import com.facebook.react.uimanager.annotations.ReactProp
import com.facebook.react.uimanager.events.EventDispatcher
import com.facebook.react.viewmanagers.VirtualViewExperimentalManagerDelegate
import com.facebook.react.viewmanagers.VirtualViewExperimentalManagerInterface
import com.facebook.react.views.virtual.VirtualViewMode
import com.facebook.react.views.virtual.VirtualViewModeChangeEmitter
import com.facebook.react.views.virtual.VirtualViewModeChangeEvent
import com.facebook.react.views.virtual.VirtualViewRenderState
@ReactModule(name = ReactVirtualViewExperimentalManager.REACT_CLASS)
public class ReactVirtualViewExperimentalManager :
ViewGroupManager<ReactVirtualViewExperimental>(),
VirtualViewExperimentalManagerInterface<ReactVirtualViewExperimental> {
private val _delegate = VirtualViewExperimentalManagerDelegate(this)
override fun getDelegate(): ViewManagerDelegate<ReactVirtualViewExperimental> = _delegate
override fun getName(): String = REACT_CLASS
override fun createViewInstance(reactContext: ThemedReactContext): ReactVirtualViewExperimental =
ReactVirtualViewExperimental(reactContext)
@ReactProp(name = "initialHidden")
override fun setInitialHidden(view: ReactVirtualViewExperimental, value: Boolean) {
if (view.mode == null) {
view.mode = if (value) VirtualViewMode.Hidden else VirtualViewMode.Visible
}
}
@ReactProp(name = "renderState")
override fun setRenderState(view: ReactVirtualViewExperimental, value: Int) {
// If disabled, `renderState` will always be `VirtualViewRenderState.Unknown`.
if (ReactNativeFeatureFlags.enableVirtualViewRenderState()) {
view.renderState =
when (value) {
1 -> VirtualViewRenderState.Rendered
2 -> VirtualViewRenderState.None
else -> VirtualViewRenderState.Unknown
}
}
}
override fun setNativeId(view: ReactVirtualViewExperimental, nativeId: String?) {
super.setNativeId(view, nativeId)
}
override fun addEventEmitters(
reactContext: ThemedReactContext,
view: ReactVirtualViewExperimental
) {
val dispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, view.id) ?: return
view.modeChangeEmitter =
VirtualViewEventEmitter(view.id, UIManagerHelper.getSurfaceId(reactContext), dispatcher)
}
override fun prepareToRecycleView(
reactContext: ThemedReactContext,
view: ReactVirtualViewExperimental,
): ReactVirtualViewExperimental? {
view.recycleView()
return super.prepareToRecycleView(reactContext, view)
}
public companion object {
public const val REACT_CLASS: String = "VirtualViewExperimental"
}
}
@VisibleForTesting
public class VirtualViewEventEmitter(
private val viewId: Int,
private val surfaceId: Int,
private val dispatcher: EventDispatcher
) : VirtualViewModeChangeEmitter {
override fun emitModeChange(
mode: VirtualViewMode,
targetRect: Rect,
thresholdRect: Rect,
synchronous: Boolean,
) {
dispatcher.dispatchEvent(
VirtualViewModeChangeEvent(
surfaceId,
viewId,
mode,
targetRect,
thresholdRect,
synchronous,
))
}
}
@@ -25,7 +25,6 @@
#include <react/renderer/components/view/LayoutConformanceComponentDescriptor.h>
#include <react/renderer/components/view/ViewComponentDescriptor.h>
#include <react/renderer/components/virtualview/VirtualViewComponentDescriptor.h>
#include <react/renderer/components/virtualviewexperimental/VirtualViewExperimentalComponentDescriptor.h>
namespace facebook::react::CoreComponentsRegistry {
@@ -73,8 +72,6 @@ sharedProviderRegistry() {
LayoutConformanceComponentDescriptor>());
providerRegistry->add(
concreteComponentDescriptorProvider<VirtualViewComponentDescriptor>());
providerRegistry->add(concreteComponentDescriptorProvider<
VirtualViewExperimentalComponentDescriptor>());
return providerRegistry;
}();
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<62ecfcd8d00ce03d659715bbb3f4a235>>
* @generated SignedSource<<5effd7d4ac8034424144ea68c82b61a7>>
*/
/**
@@ -45,6 +45,12 @@ class ReactNativeFeatureFlagsJavaProvider
return method(javaProvider_);
}
bool animatedShouldSignalBatch() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("animatedShouldSignalBatch");
return method(javaProvider_);
}
bool cxxNativeAnimatedEnabled() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("cxxNativeAnimatedEnabled");
@@ -57,6 +63,12 @@ class ReactNativeFeatureFlagsJavaProvider
return method(javaProvider_);
}
bool disableMainQueueSyncDispatchIOS() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("disableMainQueueSyncDispatchIOS");
return method(javaProvider_);
}
bool disableMountItemReorderingAndroid() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("disableMountItemReorderingAndroid");
@@ -117,12 +129,6 @@ class ReactNativeFeatureFlagsJavaProvider
return method(javaProvider_);
}
bool enableEagerMainQueueModulesOnIOS() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableEagerMainQueueModulesOnIOS");
return method(javaProvider_);
}
bool enableEagerRootViewAttachment() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableEagerRootViewAttachment");
@@ -189,6 +195,12 @@ class ReactNativeFeatureFlagsJavaProvider
return method(javaProvider_);
}
bool enableMainQueueModulesOnIOS() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableMainQueueModulesOnIOS");
return method(javaProvider_);
}
bool enableModuleArgumentNSNullConversionIOS() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableModuleArgumentNSNullConversionIOS");
@@ -384,6 +396,11 @@ bool JReactNativeFeatureFlagsCxxInterop::commonTestFlag(
return ReactNativeFeatureFlags::commonTestFlag();
}
bool JReactNativeFeatureFlagsCxxInterop::animatedShouldSignalBatch(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::animatedShouldSignalBatch();
}
bool JReactNativeFeatureFlagsCxxInterop::cxxNativeAnimatedEnabled(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::cxxNativeAnimatedEnabled();
@@ -394,6 +411,11 @@ bool JReactNativeFeatureFlagsCxxInterop::cxxNativeAnimatedRemoveJsSync(
return ReactNativeFeatureFlags::cxxNativeAnimatedRemoveJsSync();
}
bool JReactNativeFeatureFlagsCxxInterop::disableMainQueueSyncDispatchIOS(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::disableMainQueueSyncDispatchIOS();
}
bool JReactNativeFeatureFlagsCxxInterop::disableMountItemReorderingAndroid(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::disableMountItemReorderingAndroid();
@@ -444,11 +466,6 @@ bool JReactNativeFeatureFlagsCxxInterop::enableDoubleMeasurementFixAndroid(
return ReactNativeFeatureFlags::enableDoubleMeasurementFixAndroid();
}
bool JReactNativeFeatureFlagsCxxInterop::enableEagerMainQueueModulesOnIOS(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::enableEagerMainQueueModulesOnIOS();
}
bool JReactNativeFeatureFlagsCxxInterop::enableEagerRootViewAttachment(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::enableEagerRootViewAttachment();
@@ -504,6 +521,11 @@ bool JReactNativeFeatureFlagsCxxInterop::enableMainQueueCoordinatorOnIOS(
return ReactNativeFeatureFlags::enableMainQueueCoordinatorOnIOS();
}
bool JReactNativeFeatureFlagsCxxInterop::enableMainQueueModulesOnIOS(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::enableMainQueueModulesOnIOS();
}
bool JReactNativeFeatureFlagsCxxInterop::enableModuleArgumentNSNullConversionIOS(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::enableModuleArgumentNSNullConversionIOS();
@@ -693,12 +715,18 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
makeNativeMethod(
"commonTestFlag",
JReactNativeFeatureFlagsCxxInterop::commonTestFlag),
makeNativeMethod(
"animatedShouldSignalBatch",
JReactNativeFeatureFlagsCxxInterop::animatedShouldSignalBatch),
makeNativeMethod(
"cxxNativeAnimatedEnabled",
JReactNativeFeatureFlagsCxxInterop::cxxNativeAnimatedEnabled),
makeNativeMethod(
"cxxNativeAnimatedRemoveJsSync",
JReactNativeFeatureFlagsCxxInterop::cxxNativeAnimatedRemoveJsSync),
makeNativeMethod(
"disableMainQueueSyncDispatchIOS",
JReactNativeFeatureFlagsCxxInterop::disableMainQueueSyncDispatchIOS),
makeNativeMethod(
"disableMountItemReorderingAndroid",
JReactNativeFeatureFlagsCxxInterop::disableMountItemReorderingAndroid),
@@ -729,9 +757,6 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
makeNativeMethod(
"enableDoubleMeasurementFixAndroid",
JReactNativeFeatureFlagsCxxInterop::enableDoubleMeasurementFixAndroid),
makeNativeMethod(
"enableEagerMainQueueModulesOnIOS",
JReactNativeFeatureFlagsCxxInterop::enableEagerMainQueueModulesOnIOS),
makeNativeMethod(
"enableEagerRootViewAttachment",
JReactNativeFeatureFlagsCxxInterop::enableEagerRootViewAttachment),
@@ -765,6 +790,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
makeNativeMethod(
"enableMainQueueCoordinatorOnIOS",
JReactNativeFeatureFlagsCxxInterop::enableMainQueueCoordinatorOnIOS),
makeNativeMethod(
"enableMainQueueModulesOnIOS",
JReactNativeFeatureFlagsCxxInterop::enableMainQueueModulesOnIOS),
makeNativeMethod(
"enableModuleArgumentNSNullConversionIOS",
JReactNativeFeatureFlagsCxxInterop::enableModuleArgumentNSNullConversionIOS),
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<ec300827bf856bec4f381351be4fae21>>
* @generated SignedSource<<f7bf09b9287dc649901b99ca3f250c28>>
*/
/**
@@ -33,12 +33,18 @@ class JReactNativeFeatureFlagsCxxInterop
static bool commonTestFlag(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static bool animatedShouldSignalBatch(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static bool cxxNativeAnimatedEnabled(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static bool cxxNativeAnimatedRemoveJsSync(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static bool disableMainQueueSyncDispatchIOS(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static bool disableMountItemReorderingAndroid(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
@@ -69,9 +75,6 @@ class JReactNativeFeatureFlagsCxxInterop
static bool enableDoubleMeasurementFixAndroid(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static bool enableEagerMainQueueModulesOnIOS(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static bool enableEagerRootViewAttachment(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
@@ -105,6 +108,9 @@ class JReactNativeFeatureFlagsCxxInterop
static bool enableMainQueueCoordinatorOnIOS(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static bool enableMainQueueModulesOnIOS(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static bool enableModuleArgumentNSNullConversionIOS(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
@@ -12,10 +12,7 @@
<!-- tag is used to store whether the view is coopted by an accessibilityOrder-->
<item type="id" name="accessibility_order_parent"/>
<!-- tag is used to store the current state of the accessibility order tree-->
<item type="id" name="accessibility_order_dirty"/>
<!-- tag is used to store the original focusability value of a view within the accessibility order tree if it was changed-->
<!-- tag is used to store the original focusability value of a view -->
<item type="id" name="original_focusability"/>
<!-- tag is used to store the nativeID tag -->
@@ -144,12 +144,6 @@ Pod::Spec.new do |s|
sss.header_dir = "react/renderer/components/virtualview"
end
ss.subspec "virtualviewexperimental" do |sss|
sss.source_files = "react/renderer/components/virtualviewexperimental/**/*.{m,mm,cpp,h}"
sss.exclude_files = "react/renderer/components/virtualviewexperimental/tests"
sss.header_dir = "react/renderer/components/virtualviewexperimental"
end
# Legacy header paths for backwards compat
ss.subspec "rncore" do |sss|
sss.source_files = podspec_sources("react/renderer/components/rncore/**/*.h", "react/renderer/components/rncore/**/*.h")
@@ -25,7 +25,6 @@ target_link_libraries(jsinspector
jsinspector_tracing
react_featureflags
runtimeexecutor
reactperflogger
)
target_compile_reactnative_options(jsinspector PRIVATE)
target_compile_options(jsinspector PRIVATE
@@ -8,7 +8,6 @@
#include <jsinspector-modern/RuntimeTarget.h>
#include <jsinspector-modern/tracing/PerformanceTracer.h>
#include <reactperflogger/ReactPerfettoLogger.h>
#include <concepts>
#include <deque>
#include <string>
@@ -20,20 +19,6 @@ namespace facebook::react::jsinspector_modern {
namespace {
inline std::optional<HighResTimeStamp> getTimeStampForPerfetto(
const std::optional<tracing::ConsoleTimeStampEntry>& consoleTimeStampEntry,
const HighResTimeStamp now) {
if (consoleTimeStampEntry) {
if (std::holds_alternative<HighResTimeStamp>(*consoleTimeStampEntry)) {
return std::get<HighResTimeStamp>(*consoleTimeStampEntry);
} else {
return std::nullopt;
}
} else {
return now;
}
}
struct ConsoleState {
/**
* https://console.spec.whatwg.org/#counting
@@ -391,8 +376,7 @@ void consoleTimeStamp(
const jsi::Value* arguments,
size_t argumentsCount) {
auto& performanceTracer = tracing::PerformanceTracer::getInstance();
if ((!performanceTracer.isTracing() && !ReactPerfettoLogger::isTracing()) ||
argumentsCount == 0) {
if (!performanceTracer.isTracing() || argumentsCount == 0) {
// If not tracing, just early return to avoid the cost of parsing.
return;
}
@@ -460,22 +444,8 @@ void consoleTimeStamp(
}
}
if (performanceTracer.isTracing()) {
performanceTracer.reportTimeStamp(
label, start, end, trackName, trackGroup, color);
}
if (ReactPerfettoLogger::isTracing()) {
std::optional<HighResTimeStamp> perfettoStart =
getTimeStampForPerfetto(start, now);
std::optional<HighResTimeStamp> perfettoEnd =
getTimeStampForPerfetto(end, now);
if (perfettoStart && perfettoEnd) {
ReactPerfettoLogger::measure(
label, *perfettoStart, *perfettoEnd, trackName, trackGroup);
}
}
performanceTracer.reportTimeStamp(
label, start, end, trackName, trackGroup, color);
}
/*
@@ -21,8 +21,6 @@ namespace facebook::react::jsinspector_modern::tracing {
using ConsoleTimeStampEntry = std::variant<HighResTimeStamp, std::string>;
// https://developer.chrome.com/docs/devtools/performance/extension#devtools_object
// Although warning is not listed in Chrome DevTools announcement, it is
// actually supported.
enum class ConsoleTimeStampColor {
Primary,
PrimaryLight,
@@ -33,7 +31,6 @@ enum class ConsoleTimeStampColor {
Tertiary,
TertiaryLight,
TertiaryDark,
Warning,
Error,
};
@@ -57,8 +54,6 @@ inline std::string consoleTimeStampColorToString(ConsoleTimeStampColor color) {
return "tertiary-light";
case ConsoleTimeStampColor::TertiaryDark:
return "tertiary-dark";
case ConsoleTimeStampColor::Warning:
return "warning";
case ConsoleTimeStampColor::Error:
return "error";
default:
@@ -86,8 +81,6 @@ inline std::optional<ConsoleTimeStampColor> getConsoleTimeStampColorFromString(
return ConsoleTimeStampColor::TertiaryLight;
} else if (str == "tertiary-dark") {
return ConsoleTimeStampColor::TertiaryDark;
} else if (str == "warning") {
return ConsoleTimeStampColor::Warning;
} else if (str == "error") {
return ConsoleTimeStampColor::Error;
} else {
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<03e0a51aa0f46ee7ad956b2a02192c2e>>
* @generated SignedSource<<20c25bf5541e37cd5c918684925726df>>
*/
/**
@@ -30,6 +30,10 @@ bool ReactNativeFeatureFlags::commonTestFlag() {
return getAccessor().commonTestFlag();
}
bool ReactNativeFeatureFlags::animatedShouldSignalBatch() {
return getAccessor().animatedShouldSignalBatch();
}
bool ReactNativeFeatureFlags::cxxNativeAnimatedEnabled() {
return getAccessor().cxxNativeAnimatedEnabled();
}
@@ -38,6 +42,10 @@ bool ReactNativeFeatureFlags::cxxNativeAnimatedRemoveJsSync() {
return getAccessor().cxxNativeAnimatedRemoveJsSync();
}
bool ReactNativeFeatureFlags::disableMainQueueSyncDispatchIOS() {
return getAccessor().disableMainQueueSyncDispatchIOS();
}
bool ReactNativeFeatureFlags::disableMountItemReorderingAndroid() {
return getAccessor().disableMountItemReorderingAndroid();
}
@@ -78,10 +86,6 @@ bool ReactNativeFeatureFlags::enableDoubleMeasurementFixAndroid() {
return getAccessor().enableDoubleMeasurementFixAndroid();
}
bool ReactNativeFeatureFlags::enableEagerMainQueueModulesOnIOS() {
return getAccessor().enableEagerMainQueueModulesOnIOS();
}
bool ReactNativeFeatureFlags::enableEagerRootViewAttachment() {
return getAccessor().enableEagerRootViewAttachment();
}
@@ -126,6 +130,10 @@ bool ReactNativeFeatureFlags::enableMainQueueCoordinatorOnIOS() {
return getAccessor().enableMainQueueCoordinatorOnIOS();
}
bool ReactNativeFeatureFlags::enableMainQueueModulesOnIOS() {
return getAccessor().enableMainQueueModulesOnIOS();
}
bool ReactNativeFeatureFlags::enableModuleArgumentNSNullConversionIOS() {
return getAccessor().enableModuleArgumentNSNullConversionIOS();
}
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<e6c1138d3b50c0a8db0194828b448741>>
* @generated SignedSource<<20809734183aa7bfd7aad9b8d01ea080>>
*/
/**
@@ -44,6 +44,11 @@ class ReactNativeFeatureFlags {
*/
RN_EXPORT static bool commonTestFlag();
/**
* Enables start- and finishOperationBatch on any platform.
*/
RN_EXPORT static bool animatedShouldSignalBatch();
/**
* Use a C++ implementation of Native Animated instead of the platform implementation.
*/
@@ -54,6 +59,11 @@ class ReactNativeFeatureFlags {
*/
RN_EXPORT static bool cxxNativeAnimatedRemoveJsSync();
/**
* Disable sync dispatch on the main queue on iOS
*/
RN_EXPORT static bool disableMainQueueSyncDispatchIOS();
/**
* Prevent FabricMountingManager from reordering mountItems, which may lead to invalid state on the UI thread
*/
@@ -104,11 +114,6 @@ class ReactNativeFeatureFlags {
*/
RN_EXPORT static bool enableDoubleMeasurementFixAndroid();
/**
* This infra allows native modules to initialize on the main thread, during React Native init.
*/
RN_EXPORT static bool enableEagerMainQueueModulesOnIOS();
/**
* Feature flag to configure eager attachment of the root view/initialisation of the JS code.
*/
@@ -164,6 +169,11 @@ class ReactNativeFeatureFlags {
*/
RN_EXPORT static bool enableMainQueueCoordinatorOnIOS();
/**
* Makes modules requiring main queue setup initialize on the main thread, during React Native init.
*/
RN_EXPORT static bool enableMainQueueModulesOnIOS();
/**
* Enable NSNull conversion when handling module arguments on iOS
*/
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<8dc8477fa5453260c803e37fb8c7f47c>>
* @generated SignedSource<<59ec29e038344c52eaa10845efc5240b>>
*/
/**
@@ -47,6 +47,24 @@ bool ReactNativeFeatureFlagsAccessor::commonTestFlag() {
return flagValue.value();
}
bool ReactNativeFeatureFlagsAccessor::animatedShouldSignalBatch() {
auto flagValue = animatedShouldSignalBatch_.load();
if (!flagValue.has_value()) {
// This block is not exclusive but it is not necessary.
// If multiple threads try to initialize the feature flag, we would only
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(1, "animatedShouldSignalBatch");
flagValue = currentProvider_->animatedShouldSignalBatch();
animatedShouldSignalBatch_ = flagValue;
}
return flagValue.value();
}
bool ReactNativeFeatureFlagsAccessor::cxxNativeAnimatedEnabled() {
auto flagValue = cxxNativeAnimatedEnabled_.load();
@@ -56,7 +74,7 @@ bool ReactNativeFeatureFlagsAccessor::cxxNativeAnimatedEnabled() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(1, "cxxNativeAnimatedEnabled");
markFlagAsAccessed(2, "cxxNativeAnimatedEnabled");
flagValue = currentProvider_->cxxNativeAnimatedEnabled();
cxxNativeAnimatedEnabled_ = flagValue;
@@ -74,7 +92,7 @@ bool ReactNativeFeatureFlagsAccessor::cxxNativeAnimatedRemoveJsSync() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(2, "cxxNativeAnimatedRemoveJsSync");
markFlagAsAccessed(3, "cxxNativeAnimatedRemoveJsSync");
flagValue = currentProvider_->cxxNativeAnimatedRemoveJsSync();
cxxNativeAnimatedRemoveJsSync_ = flagValue;
@@ -83,6 +101,24 @@ bool ReactNativeFeatureFlagsAccessor::cxxNativeAnimatedRemoveJsSync() {
return flagValue.value();
}
bool ReactNativeFeatureFlagsAccessor::disableMainQueueSyncDispatchIOS() {
auto flagValue = disableMainQueueSyncDispatchIOS_.load();
if (!flagValue.has_value()) {
// This block is not exclusive but it is not necessary.
// If multiple threads try to initialize the feature flag, we would only
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(4, "disableMainQueueSyncDispatchIOS");
flagValue = currentProvider_->disableMainQueueSyncDispatchIOS();
disableMainQueueSyncDispatchIOS_ = flagValue;
}
return flagValue.value();
}
bool ReactNativeFeatureFlagsAccessor::disableMountItemReorderingAndroid() {
auto flagValue = disableMountItemReorderingAndroid_.load();
@@ -92,7 +128,7 @@ bool ReactNativeFeatureFlagsAccessor::disableMountItemReorderingAndroid() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(3, "disableMountItemReorderingAndroid");
markFlagAsAccessed(5, "disableMountItemReorderingAndroid");
flagValue = currentProvider_->disableMountItemReorderingAndroid();
disableMountItemReorderingAndroid_ = flagValue;
@@ -110,7 +146,7 @@ bool ReactNativeFeatureFlagsAccessor::disableTextLayoutManagerCacheAndroid() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(4, "disableTextLayoutManagerCacheAndroid");
markFlagAsAccessed(6, "disableTextLayoutManagerCacheAndroid");
flagValue = currentProvider_->disableTextLayoutManagerCacheAndroid();
disableTextLayoutManagerCacheAndroid_ = flagValue;
@@ -128,7 +164,7 @@ bool ReactNativeFeatureFlagsAccessor::enableAccessibilityOrder() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(5, "enableAccessibilityOrder");
markFlagAsAccessed(7, "enableAccessibilityOrder");
flagValue = currentProvider_->enableAccessibilityOrder();
enableAccessibilityOrder_ = flagValue;
@@ -146,7 +182,7 @@ bool ReactNativeFeatureFlagsAccessor::enableAccumulatedUpdatesInRawPropsAndroid(
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(6, "enableAccumulatedUpdatesInRawPropsAndroid");
markFlagAsAccessed(8, "enableAccumulatedUpdatesInRawPropsAndroid");
flagValue = currentProvider_->enableAccumulatedUpdatesInRawPropsAndroid();
enableAccumulatedUpdatesInRawPropsAndroid_ = flagValue;
@@ -164,7 +200,7 @@ bool ReactNativeFeatureFlagsAccessor::enableAndroidTextMeasurementOptimizations(
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(7, "enableAndroidTextMeasurementOptimizations");
markFlagAsAccessed(9, "enableAndroidTextMeasurementOptimizations");
flagValue = currentProvider_->enableAndroidTextMeasurementOptimizations();
enableAndroidTextMeasurementOptimizations_ = flagValue;
@@ -182,7 +218,7 @@ bool ReactNativeFeatureFlagsAccessor::enableBridgelessArchitecture() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(8, "enableBridgelessArchitecture");
markFlagAsAccessed(10, "enableBridgelessArchitecture");
flagValue = currentProvider_->enableBridgelessArchitecture();
enableBridgelessArchitecture_ = flagValue;
@@ -200,7 +236,7 @@ bool ReactNativeFeatureFlagsAccessor::enableCppPropsIteratorSetter() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(9, "enableCppPropsIteratorSetter");
markFlagAsAccessed(11, "enableCppPropsIteratorSetter");
flagValue = currentProvider_->enableCppPropsIteratorSetter();
enableCppPropsIteratorSetter_ = flagValue;
@@ -218,7 +254,7 @@ bool ReactNativeFeatureFlagsAccessor::enableCustomFocusSearchOnClippedElementsAn
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(10, "enableCustomFocusSearchOnClippedElementsAndroid");
markFlagAsAccessed(12, "enableCustomFocusSearchOnClippedElementsAndroid");
flagValue = currentProvider_->enableCustomFocusSearchOnClippedElementsAndroid();
enableCustomFocusSearchOnClippedElementsAndroid_ = flagValue;
@@ -236,7 +272,7 @@ bool ReactNativeFeatureFlagsAccessor::enableDestroyShadowTreeRevisionAsync() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(11, "enableDestroyShadowTreeRevisionAsync");
markFlagAsAccessed(13, "enableDestroyShadowTreeRevisionAsync");
flagValue = currentProvider_->enableDestroyShadowTreeRevisionAsync();
enableDestroyShadowTreeRevisionAsync_ = flagValue;
@@ -254,7 +290,7 @@ bool ReactNativeFeatureFlagsAccessor::enableDoubleMeasurementFixAndroid() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(12, "enableDoubleMeasurementFixAndroid");
markFlagAsAccessed(14, "enableDoubleMeasurementFixAndroid");
flagValue = currentProvider_->enableDoubleMeasurementFixAndroid();
enableDoubleMeasurementFixAndroid_ = flagValue;
@@ -263,24 +299,6 @@ bool ReactNativeFeatureFlagsAccessor::enableDoubleMeasurementFixAndroid() {
return flagValue.value();
}
bool ReactNativeFeatureFlagsAccessor::enableEagerMainQueueModulesOnIOS() {
auto flagValue = enableEagerMainQueueModulesOnIOS_.load();
if (!flagValue.has_value()) {
// This block is not exclusive but it is not necessary.
// If multiple threads try to initialize the feature flag, we would only
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(13, "enableEagerMainQueueModulesOnIOS");
flagValue = currentProvider_->enableEagerMainQueueModulesOnIOS();
enableEagerMainQueueModulesOnIOS_ = flagValue;
}
return flagValue.value();
}
bool ReactNativeFeatureFlagsAccessor::enableEagerRootViewAttachment() {
auto flagValue = enableEagerRootViewAttachment_.load();
@@ -290,7 +308,7 @@ bool ReactNativeFeatureFlagsAccessor::enableEagerRootViewAttachment() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(14, "enableEagerRootViewAttachment");
markFlagAsAccessed(15, "enableEagerRootViewAttachment");
flagValue = currentProvider_->enableEagerRootViewAttachment();
enableEagerRootViewAttachment_ = flagValue;
@@ -308,7 +326,7 @@ bool ReactNativeFeatureFlagsAccessor::enableFabricLogs() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(15, "enableFabricLogs");
markFlagAsAccessed(16, "enableFabricLogs");
flagValue = currentProvider_->enableFabricLogs();
enableFabricLogs_ = flagValue;
@@ -326,7 +344,7 @@ bool ReactNativeFeatureFlagsAccessor::enableFabricRenderer() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(16, "enableFabricRenderer");
markFlagAsAccessed(17, "enableFabricRenderer");
flagValue = currentProvider_->enableFabricRenderer();
enableFabricRenderer_ = flagValue;
@@ -344,7 +362,7 @@ bool ReactNativeFeatureFlagsAccessor::enableFixForParentTagDuringReparenting() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(17, "enableFixForParentTagDuringReparenting");
markFlagAsAccessed(18, "enableFixForParentTagDuringReparenting");
flagValue = currentProvider_->enableFixForParentTagDuringReparenting();
enableFixForParentTagDuringReparenting_ = flagValue;
@@ -362,7 +380,7 @@ bool ReactNativeFeatureFlagsAccessor::enableFontScaleChangesUpdatingLayout() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(18, "enableFontScaleChangesUpdatingLayout");
markFlagAsAccessed(19, "enableFontScaleChangesUpdatingLayout");
flagValue = currentProvider_->enableFontScaleChangesUpdatingLayout();
enableFontScaleChangesUpdatingLayout_ = flagValue;
@@ -380,7 +398,7 @@ bool ReactNativeFeatureFlagsAccessor::enableIOSTextBaselineOffsetPerLine() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(19, "enableIOSTextBaselineOffsetPerLine");
markFlagAsAccessed(20, "enableIOSTextBaselineOffsetPerLine");
flagValue = currentProvider_->enableIOSTextBaselineOffsetPerLine();
enableIOSTextBaselineOffsetPerLine_ = flagValue;
@@ -398,7 +416,7 @@ bool ReactNativeFeatureFlagsAccessor::enableIOSViewClipToPaddingBox() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(20, "enableIOSViewClipToPaddingBox");
markFlagAsAccessed(21, "enableIOSViewClipToPaddingBox");
flagValue = currentProvider_->enableIOSViewClipToPaddingBox();
enableIOSViewClipToPaddingBox_ = flagValue;
@@ -416,7 +434,7 @@ bool ReactNativeFeatureFlagsAccessor::enableInteropViewManagerClassLookUpOptimiz
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(21, "enableInteropViewManagerClassLookUpOptimizationIOS");
markFlagAsAccessed(22, "enableInteropViewManagerClassLookUpOptimizationIOS");
flagValue = currentProvider_->enableInteropViewManagerClassLookUpOptimizationIOS();
enableInteropViewManagerClassLookUpOptimizationIOS_ = flagValue;
@@ -434,7 +452,7 @@ bool ReactNativeFeatureFlagsAccessor::enableLayoutAnimationsOnAndroid() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(22, "enableLayoutAnimationsOnAndroid");
markFlagAsAccessed(23, "enableLayoutAnimationsOnAndroid");
flagValue = currentProvider_->enableLayoutAnimationsOnAndroid();
enableLayoutAnimationsOnAndroid_ = flagValue;
@@ -452,7 +470,7 @@ bool ReactNativeFeatureFlagsAccessor::enableLayoutAnimationsOnIOS() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(23, "enableLayoutAnimationsOnIOS");
markFlagAsAccessed(24, "enableLayoutAnimationsOnIOS");
flagValue = currentProvider_->enableLayoutAnimationsOnIOS();
enableLayoutAnimationsOnIOS_ = flagValue;
@@ -470,7 +488,7 @@ bool ReactNativeFeatureFlagsAccessor::enableMainQueueCoordinatorOnIOS() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(24, "enableMainQueueCoordinatorOnIOS");
markFlagAsAccessed(25, "enableMainQueueCoordinatorOnIOS");
flagValue = currentProvider_->enableMainQueueCoordinatorOnIOS();
enableMainQueueCoordinatorOnIOS_ = flagValue;
@@ -479,6 +497,24 @@ bool ReactNativeFeatureFlagsAccessor::enableMainQueueCoordinatorOnIOS() {
return flagValue.value();
}
bool ReactNativeFeatureFlagsAccessor::enableMainQueueModulesOnIOS() {
auto flagValue = enableMainQueueModulesOnIOS_.load();
if (!flagValue.has_value()) {
// This block is not exclusive but it is not necessary.
// If multiple threads try to initialize the feature flag, we would only
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(26, "enableMainQueueModulesOnIOS");
flagValue = currentProvider_->enableMainQueueModulesOnIOS();
enableMainQueueModulesOnIOS_ = flagValue;
}
return flagValue.value();
}
bool ReactNativeFeatureFlagsAccessor::enableModuleArgumentNSNullConversionIOS() {
auto flagValue = enableModuleArgumentNSNullConversionIOS_.load();
@@ -488,7 +524,7 @@ bool ReactNativeFeatureFlagsAccessor::enableModuleArgumentNSNullConversionIOS()
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(25, "enableModuleArgumentNSNullConversionIOS");
markFlagAsAccessed(27, "enableModuleArgumentNSNullConversionIOS");
flagValue = currentProvider_->enableModuleArgumentNSNullConversionIOS();
enableModuleArgumentNSNullConversionIOS_ = flagValue;
@@ -506,7 +542,7 @@ bool ReactNativeFeatureFlagsAccessor::enableNativeCSSParsing() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(26, "enableNativeCSSParsing");
markFlagAsAccessed(28, "enableNativeCSSParsing");
flagValue = currentProvider_->enableNativeCSSParsing();
enableNativeCSSParsing_ = flagValue;
@@ -524,7 +560,7 @@ bool ReactNativeFeatureFlagsAccessor::enableNetworkEventReporting() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(27, "enableNetworkEventReporting");
markFlagAsAccessed(29, "enableNetworkEventReporting");
flagValue = currentProvider_->enableNetworkEventReporting();
enableNetworkEventReporting_ = flagValue;
@@ -542,7 +578,7 @@ bool ReactNativeFeatureFlagsAccessor::enableNewBackgroundAndBorderDrawables() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(28, "enableNewBackgroundAndBorderDrawables");
markFlagAsAccessed(30, "enableNewBackgroundAndBorderDrawables");
flagValue = currentProvider_->enableNewBackgroundAndBorderDrawables();
enableNewBackgroundAndBorderDrawables_ = flagValue;
@@ -560,7 +596,7 @@ bool ReactNativeFeatureFlagsAccessor::enablePreparedTextLayout() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(29, "enablePreparedTextLayout");
markFlagAsAccessed(31, "enablePreparedTextLayout");
flagValue = currentProvider_->enablePreparedTextLayout();
enablePreparedTextLayout_ = flagValue;
@@ -578,7 +614,7 @@ bool ReactNativeFeatureFlagsAccessor::enablePropsUpdateReconciliationAndroid() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(30, "enablePropsUpdateReconciliationAndroid");
markFlagAsAccessed(32, "enablePropsUpdateReconciliationAndroid");
flagValue = currentProvider_->enablePropsUpdateReconciliationAndroid();
enablePropsUpdateReconciliationAndroid_ = flagValue;
@@ -596,7 +632,7 @@ bool ReactNativeFeatureFlagsAccessor::enableResourceTimingAPI() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(31, "enableResourceTimingAPI");
markFlagAsAccessed(33, "enableResourceTimingAPI");
flagValue = currentProvider_->enableResourceTimingAPI();
enableResourceTimingAPI_ = flagValue;
@@ -614,7 +650,7 @@ bool ReactNativeFeatureFlagsAccessor::enableSynchronousStateUpdates() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(32, "enableSynchronousStateUpdates");
markFlagAsAccessed(34, "enableSynchronousStateUpdates");
flagValue = currentProvider_->enableSynchronousStateUpdates();
enableSynchronousStateUpdates_ = flagValue;
@@ -632,7 +668,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewCulling() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(33, "enableViewCulling");
markFlagAsAccessed(35, "enableViewCulling");
flagValue = currentProvider_->enableViewCulling();
enableViewCulling_ = flagValue;
@@ -650,7 +686,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecycling() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(34, "enableViewRecycling");
markFlagAsAccessed(36, "enableViewRecycling");
flagValue = currentProvider_->enableViewRecycling();
enableViewRecycling_ = flagValue;
@@ -668,7 +704,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecyclingForText() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(35, "enableViewRecyclingForText");
markFlagAsAccessed(37, "enableViewRecyclingForText");
flagValue = currentProvider_->enableViewRecyclingForText();
enableViewRecyclingForText_ = flagValue;
@@ -686,7 +722,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecyclingForView() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(36, "enableViewRecyclingForView");
markFlagAsAccessed(38, "enableViewRecyclingForView");
flagValue = currentProvider_->enableViewRecyclingForView();
enableViewRecyclingForView_ = flagValue;
@@ -704,7 +740,7 @@ bool ReactNativeFeatureFlagsAccessor::enableVirtualViewDebugFeatures() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(37, "enableVirtualViewDebugFeatures");
markFlagAsAccessed(39, "enableVirtualViewDebugFeatures");
flagValue = currentProvider_->enableVirtualViewDebugFeatures();
enableVirtualViewDebugFeatures_ = flagValue;
@@ -722,7 +758,7 @@ bool ReactNativeFeatureFlagsAccessor::enableVirtualViewRenderState() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(38, "enableVirtualViewRenderState");
markFlagAsAccessed(40, "enableVirtualViewRenderState");
flagValue = currentProvider_->enableVirtualViewRenderState();
enableVirtualViewRenderState_ = flagValue;
@@ -740,7 +776,7 @@ bool ReactNativeFeatureFlagsAccessor::enableVirtualViewWindowFocusDetection() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(39, "enableVirtualViewWindowFocusDetection");
markFlagAsAccessed(41, "enableVirtualViewWindowFocusDetection");
flagValue = currentProvider_->enableVirtualViewWindowFocusDetection();
enableVirtualViewWindowFocusDetection_ = flagValue;
@@ -758,7 +794,7 @@ bool ReactNativeFeatureFlagsAccessor::fixMappingOfEventPrioritiesBetweenFabricAn
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(40, "fixMappingOfEventPrioritiesBetweenFabricAndReact");
markFlagAsAccessed(42, "fixMappingOfEventPrioritiesBetweenFabricAndReact");
flagValue = currentProvider_->fixMappingOfEventPrioritiesBetweenFabricAndReact();
fixMappingOfEventPrioritiesBetweenFabricAndReact_ = flagValue;
@@ -776,7 +812,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxEnabledRelease() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(41, "fuseboxEnabledRelease");
markFlagAsAccessed(43, "fuseboxEnabledRelease");
flagValue = currentProvider_->fuseboxEnabledRelease();
fuseboxEnabledRelease_ = flagValue;
@@ -794,7 +830,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxNetworkInspectionEnabled() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(42, "fuseboxNetworkInspectionEnabled");
markFlagAsAccessed(44, "fuseboxNetworkInspectionEnabled");
flagValue = currentProvider_->fuseboxNetworkInspectionEnabled();
fuseboxNetworkInspectionEnabled_ = flagValue;
@@ -812,7 +848,7 @@ bool ReactNativeFeatureFlagsAccessor::hideOffscreenVirtualViewsOnIOS() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(43, "hideOffscreenVirtualViewsOnIOS");
markFlagAsAccessed(45, "hideOffscreenVirtualViewsOnIOS");
flagValue = currentProvider_->hideOffscreenVirtualViewsOnIOS();
hideOffscreenVirtualViewsOnIOS_ = flagValue;
@@ -830,7 +866,7 @@ double ReactNativeFeatureFlagsAccessor::preparedTextCacheSize() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(44, "preparedTextCacheSize");
markFlagAsAccessed(46, "preparedTextCacheSize");
flagValue = currentProvider_->preparedTextCacheSize();
preparedTextCacheSize_ = flagValue;
@@ -848,7 +884,7 @@ bool ReactNativeFeatureFlagsAccessor::traceTurboModulePromiseRejectionsOnAndroid
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(45, "traceTurboModulePromiseRejectionsOnAndroid");
markFlagAsAccessed(47, "traceTurboModulePromiseRejectionsOnAndroid");
flagValue = currentProvider_->traceTurboModulePromiseRejectionsOnAndroid();
traceTurboModulePromiseRejectionsOnAndroid_ = flagValue;
@@ -866,7 +902,7 @@ bool ReactNativeFeatureFlagsAccessor::updateRuntimeShadowNodeReferencesOnCommit(
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(46, "updateRuntimeShadowNodeReferencesOnCommit");
markFlagAsAccessed(48, "updateRuntimeShadowNodeReferencesOnCommit");
flagValue = currentProvider_->updateRuntimeShadowNodeReferencesOnCommit();
updateRuntimeShadowNodeReferencesOnCommit_ = flagValue;
@@ -884,7 +920,7 @@ bool ReactNativeFeatureFlagsAccessor::useAlwaysAvailableJSErrorHandling() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(47, "useAlwaysAvailableJSErrorHandling");
markFlagAsAccessed(49, "useAlwaysAvailableJSErrorHandling");
flagValue = currentProvider_->useAlwaysAvailableJSErrorHandling();
useAlwaysAvailableJSErrorHandling_ = flagValue;
@@ -902,7 +938,7 @@ bool ReactNativeFeatureFlagsAccessor::useFabricInterop() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(48, "useFabricInterop");
markFlagAsAccessed(50, "useFabricInterop");
flagValue = currentProvider_->useFabricInterop();
useFabricInterop_ = flagValue;
@@ -920,7 +956,7 @@ bool ReactNativeFeatureFlagsAccessor::useNativeViewConfigsInBridgelessMode() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(49, "useNativeViewConfigsInBridgelessMode");
markFlagAsAccessed(51, "useNativeViewConfigsInBridgelessMode");
flagValue = currentProvider_->useNativeViewConfigsInBridgelessMode();
useNativeViewConfigsInBridgelessMode_ = flagValue;
@@ -938,7 +974,7 @@ bool ReactNativeFeatureFlagsAccessor::useOptimizedEventBatchingOnAndroid() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(50, "useOptimizedEventBatchingOnAndroid");
markFlagAsAccessed(52, "useOptimizedEventBatchingOnAndroid");
flagValue = currentProvider_->useOptimizedEventBatchingOnAndroid();
useOptimizedEventBatchingOnAndroid_ = flagValue;
@@ -956,7 +992,7 @@ bool ReactNativeFeatureFlagsAccessor::useRawPropsJsiValue() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(51, "useRawPropsJsiValue");
markFlagAsAccessed(53, "useRawPropsJsiValue");
flagValue = currentProvider_->useRawPropsJsiValue();
useRawPropsJsiValue_ = flagValue;
@@ -974,7 +1010,7 @@ bool ReactNativeFeatureFlagsAccessor::useShadowNodeStateOnClone() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(52, "useShadowNodeStateOnClone");
markFlagAsAccessed(54, "useShadowNodeStateOnClone");
flagValue = currentProvider_->useShadowNodeStateOnClone();
useShadowNodeStateOnClone_ = flagValue;
@@ -992,7 +1028,7 @@ bool ReactNativeFeatureFlagsAccessor::useTurboModuleInterop() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(53, "useTurboModuleInterop");
markFlagAsAccessed(55, "useTurboModuleInterop");
flagValue = currentProvider_->useTurboModuleInterop();
useTurboModuleInterop_ = flagValue;
@@ -1010,7 +1046,7 @@ bool ReactNativeFeatureFlagsAccessor::useTurboModules() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(54, "useTurboModules");
markFlagAsAccessed(56, "useTurboModules");
flagValue = currentProvider_->useTurboModules();
useTurboModules_ = flagValue;
@@ -1028,7 +1064,7 @@ double ReactNativeFeatureFlagsAccessor::virtualViewPrerenderRatio() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(55, "virtualViewPrerenderRatio");
markFlagAsAccessed(57, "virtualViewPrerenderRatio");
flagValue = currentProvider_->virtualViewPrerenderRatio();
virtualViewPrerenderRatio_ = flagValue;
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<4e06f35e1af18fbf5219f7fd2f79767d>>
* @generated SignedSource<<043e1a56e7a302fbca38151b5d079616>>
*/
/**
@@ -33,8 +33,10 @@ class ReactNativeFeatureFlagsAccessor {
ReactNativeFeatureFlagsAccessor();
bool commonTestFlag();
bool animatedShouldSignalBatch();
bool cxxNativeAnimatedEnabled();
bool cxxNativeAnimatedRemoveJsSync();
bool disableMainQueueSyncDispatchIOS();
bool disableMountItemReorderingAndroid();
bool disableTextLayoutManagerCacheAndroid();
bool enableAccessibilityOrder();
@@ -45,7 +47,6 @@ class ReactNativeFeatureFlagsAccessor {
bool enableCustomFocusSearchOnClippedElementsAndroid();
bool enableDestroyShadowTreeRevisionAsync();
bool enableDoubleMeasurementFixAndroid();
bool enableEagerMainQueueModulesOnIOS();
bool enableEagerRootViewAttachment();
bool enableFabricLogs();
bool enableFabricRenderer();
@@ -57,6 +58,7 @@ class ReactNativeFeatureFlagsAccessor {
bool enableLayoutAnimationsOnAndroid();
bool enableLayoutAnimationsOnIOS();
bool enableMainQueueCoordinatorOnIOS();
bool enableMainQueueModulesOnIOS();
bool enableModuleArgumentNSNullConversionIOS();
bool enableNativeCSSParsing();
bool enableNetworkEventReporting();
@@ -99,11 +101,13 @@ class ReactNativeFeatureFlagsAccessor {
std::unique_ptr<ReactNativeFeatureFlagsProvider> currentProvider_;
bool wasOverridden_;
std::array<std::atomic<const char*>, 56> accessedFeatureFlags_;
std::array<std::atomic<const char*>, 58> accessedFeatureFlags_;
std::atomic<std::optional<bool>> commonTestFlag_;
std::atomic<std::optional<bool>> animatedShouldSignalBatch_;
std::atomic<std::optional<bool>> cxxNativeAnimatedEnabled_;
std::atomic<std::optional<bool>> cxxNativeAnimatedRemoveJsSync_;
std::atomic<std::optional<bool>> disableMainQueueSyncDispatchIOS_;
std::atomic<std::optional<bool>> disableMountItemReorderingAndroid_;
std::atomic<std::optional<bool>> disableTextLayoutManagerCacheAndroid_;
std::atomic<std::optional<bool>> enableAccessibilityOrder_;
@@ -114,7 +118,6 @@ class ReactNativeFeatureFlagsAccessor {
std::atomic<std::optional<bool>> enableCustomFocusSearchOnClippedElementsAndroid_;
std::atomic<std::optional<bool>> enableDestroyShadowTreeRevisionAsync_;
std::atomic<std::optional<bool>> enableDoubleMeasurementFixAndroid_;
std::atomic<std::optional<bool>> enableEagerMainQueueModulesOnIOS_;
std::atomic<std::optional<bool>> enableEagerRootViewAttachment_;
std::atomic<std::optional<bool>> enableFabricLogs_;
std::atomic<std::optional<bool>> enableFabricRenderer_;
@@ -126,6 +129,7 @@ class ReactNativeFeatureFlagsAccessor {
std::atomic<std::optional<bool>> enableLayoutAnimationsOnAndroid_;
std::atomic<std::optional<bool>> enableLayoutAnimationsOnIOS_;
std::atomic<std::optional<bool>> enableMainQueueCoordinatorOnIOS_;
std::atomic<std::optional<bool>> enableMainQueueModulesOnIOS_;
std::atomic<std::optional<bool>> enableModuleArgumentNSNullConversionIOS_;
std::atomic<std::optional<bool>> enableNativeCSSParsing_;
std::atomic<std::optional<bool>> enableNetworkEventReporting_;
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<a16b227254e43d57c46479d87bc45bf2>>
* @generated SignedSource<<7b5caffd8f748384aa32ed6e153ee9c1>>
*/
/**
@@ -31,6 +31,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider {
return false;
}
bool animatedShouldSignalBatch() override {
return false;
}
bool cxxNativeAnimatedEnabled() override {
return false;
}
@@ -39,6 +43,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider {
return false;
}
bool disableMainQueueSyncDispatchIOS() override {
return false;
}
bool disableMountItemReorderingAndroid() override {
return false;
}
@@ -79,10 +87,6 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider {
return false;
}
bool enableEagerMainQueueModulesOnIOS() override {
return false;
}
bool enableEagerRootViewAttachment() override {
return false;
}
@@ -127,6 +131,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider {
return false;
}
bool enableMainQueueModulesOnIOS() override {
return false;
}
bool enableModuleArgumentNSNullConversionIOS() override {
return false;
}
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<015e26c40f3a6bef540d8c4ca43b8502>>
* @generated SignedSource<<e78150be120e3fdf02f9420abce23bfc>>
*/
/**
@@ -54,6 +54,15 @@ class ReactNativeFeatureFlagsDynamicProvider : public ReactNativeFeatureFlagsDef
return ReactNativeFeatureFlagsDefaults::commonTestFlag();
}
bool animatedShouldSignalBatch() override {
auto value = values_["animatedShouldSignalBatch"];
if (!value.isNull()) {
return value.getBool();
}
return ReactNativeFeatureFlagsDefaults::animatedShouldSignalBatch();
}
bool cxxNativeAnimatedEnabled() override {
auto value = values_["cxxNativeAnimatedEnabled"];
if (!value.isNull()) {
@@ -72,6 +81,15 @@ class ReactNativeFeatureFlagsDynamicProvider : public ReactNativeFeatureFlagsDef
return ReactNativeFeatureFlagsDefaults::cxxNativeAnimatedRemoveJsSync();
}
bool disableMainQueueSyncDispatchIOS() override {
auto value = values_["disableMainQueueSyncDispatchIOS"];
if (!value.isNull()) {
return value.getBool();
}
return ReactNativeFeatureFlagsDefaults::disableMainQueueSyncDispatchIOS();
}
bool disableMountItemReorderingAndroid() override {
auto value = values_["disableMountItemReorderingAndroid"];
if (!value.isNull()) {
@@ -162,15 +180,6 @@ class ReactNativeFeatureFlagsDynamicProvider : public ReactNativeFeatureFlagsDef
return ReactNativeFeatureFlagsDefaults::enableDoubleMeasurementFixAndroid();
}
bool enableEagerMainQueueModulesOnIOS() override {
auto value = values_["enableEagerMainQueueModulesOnIOS"];
if (!value.isNull()) {
return value.getBool();
}
return ReactNativeFeatureFlagsDefaults::enableEagerMainQueueModulesOnIOS();
}
bool enableEagerRootViewAttachment() override {
auto value = values_["enableEagerRootViewAttachment"];
if (!value.isNull()) {
@@ -270,6 +279,15 @@ class ReactNativeFeatureFlagsDynamicProvider : public ReactNativeFeatureFlagsDef
return ReactNativeFeatureFlagsDefaults::enableMainQueueCoordinatorOnIOS();
}
bool enableMainQueueModulesOnIOS() override {
auto value = values_["enableMainQueueModulesOnIOS"];
if (!value.isNull()) {
return value.getBool();
}
return ReactNativeFeatureFlagsDefaults::enableMainQueueModulesOnIOS();
}
bool enableModuleArgumentNSNullConversionIOS() override {
auto value = values_["enableModuleArgumentNSNullConversionIOS"];
if (!value.isNull()) {
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<f3e838bc19232c5b2bb539133c825a71>>
* @generated SignedSource<<bdd21870bf567207ad837eb33ae4ca5b>>
*/
/**
@@ -26,8 +26,10 @@ class ReactNativeFeatureFlagsProvider {
virtual ~ReactNativeFeatureFlagsProvider() = default;
virtual bool commonTestFlag() = 0;
virtual bool animatedShouldSignalBatch() = 0;
virtual bool cxxNativeAnimatedEnabled() = 0;
virtual bool cxxNativeAnimatedRemoveJsSync() = 0;
virtual bool disableMainQueueSyncDispatchIOS() = 0;
virtual bool disableMountItemReorderingAndroid() = 0;
virtual bool disableTextLayoutManagerCacheAndroid() = 0;
virtual bool enableAccessibilityOrder() = 0;
@@ -38,7 +40,6 @@ class ReactNativeFeatureFlagsProvider {
virtual bool enableCustomFocusSearchOnClippedElementsAndroid() = 0;
virtual bool enableDestroyShadowTreeRevisionAsync() = 0;
virtual bool enableDoubleMeasurementFixAndroid() = 0;
virtual bool enableEagerMainQueueModulesOnIOS() = 0;
virtual bool enableEagerRootViewAttachment() = 0;
virtual bool enableFabricLogs() = 0;
virtual bool enableFabricRenderer() = 0;
@@ -50,6 +51,7 @@ class ReactNativeFeatureFlagsProvider {
virtual bool enableLayoutAnimationsOnAndroid() = 0;
virtual bool enableLayoutAnimationsOnIOS() = 0;
virtual bool enableMainQueueCoordinatorOnIOS() = 0;
virtual bool enableMainQueueModulesOnIOS() = 0;
virtual bool enableModuleArgumentNSNullConversionIOS() = 0;
virtual bool enableNativeCSSParsing() = 0;
virtual bool enableNetworkEventReporting() = 0;
@@ -601,7 +601,11 @@ typedef struct {
};
if ([self _requiresMainQueueSetup:moduleClass]) {
RCTUnsafeExecuteOnMainQueueSync(work);
NSString *message = [NSString
stringWithFormat:
@"Lazily setting up TurboModule \"%s\" on the main queue. This could deadlock react native, if it happens during sync rendering. Please fix this by avoiding lazy main queue setup.",
moduleName];
RCTUnsafeExecuteOnMainQueueSyncWithError(work, message);
} else {
work();
}
@@ -30,14 +30,15 @@ inline std::shared_ptr<const ShadowNode> getShadowNode(
return Bridging<std::shared_ptr<const ShadowNode>>::fromJs(
runtime, shadowNodeValue);
}
} // namespace
#pragma mark - Private helpers
UIManager& getUIManagerFromRuntime(facebook::jsi::Runtime& runtime) {
static UIManager& getUIManagerFromRuntime(facebook::jsi::Runtime& runtime) {
return UIManagerBinding::getBinding(runtime)->getUIManager();
}
RootShadowNode::Shared getCurrentShadowTreeRevision(
static RootShadowNode::Shared getCurrentShadowTreeRevision(
facebook::jsi::Runtime& runtime,
SurfaceId surfaceId) {
auto shadowTreeRevisionProvider =
@@ -45,7 +46,7 @@ RootShadowNode::Shared getCurrentShadowTreeRevision(
return shadowTreeRevisionProvider->getCurrentRevision(surfaceId);
}
RootShadowNode::Shared getCurrentShadowTreeRevision(
static RootShadowNode::Shared getCurrentShadowTreeRevision(
facebook::jsi::Runtime& runtime,
jsi::Value& nativeNodeReference) {
if (nativeNodeReference.isNumber()) {
@@ -57,13 +58,14 @@ RootShadowNode::Shared getCurrentShadowTreeRevision(
runtime, getShadowNode(runtime, nativeNodeReference)->getSurfaceId());
}
facebook::react::PointerEventsProcessor& getPointerEventsProcessorFromRuntime(
facebook::jsi::Runtime& runtime) {
static facebook::react::PointerEventsProcessor&
getPointerEventsProcessorFromRuntime(facebook::jsi::Runtime& runtime) {
return facebook::react::UIManagerBinding::getBinding(runtime)
->getPointerEventsProcessor();
}
std::vector<facebook::jsi::Value> getArrayOfInstanceHandlesFromShadowNodes(
static std::vector<facebook::jsi::Value>
getArrayOfInstanceHandlesFromShadowNodes(
const std::vector<std::shared_ptr<const ShadowNode>>& nodes,
facebook::jsi::Runtime& runtime) {
// JSI doesn't support adding elements to an array after creation,
@@ -81,12 +83,10 @@ std::vector<facebook::jsi::Value> getArrayOfInstanceHandlesFromShadowNodes(
return nonNullInstanceHandles;
}
bool isRootShadowNode(const ShadowNode& shadowNode) {
static bool isRootShadowNode(const ShadowNode& shadowNode) {
return shadowNode.getTraits().check(ShadowNodeTraits::Trait::RootNodeKind);
}
} // namespace
#pragma mark - NativeDOM
NativeDOM::NativeDOM(std::shared_ptr<CallInvoker> jsInvoker)
@@ -389,38 +389,44 @@ jsi::Value NativeDOM::linkRootNode(
void NativeDOM::measure(
jsi::Runtime& rt,
std::shared_ptr<const ShadowNode> shadowNode,
const MeasureOnSuccessCallback& callback) {
jsi::Function callback) {
auto currentRevision =
getCurrentShadowTreeRevision(rt, shadowNode->getSurfaceId());
if (currentRevision == nullptr) {
callback(0, 0, 0, 0, 0, 0);
callback.call(rt, {0, 0, 0, 0, 0, 0});
return;
}
auto measureRect = dom::measure(currentRevision, *shadowNode);
callback(
measureRect.x,
measureRect.y,
measureRect.width,
measureRect.height,
measureRect.pageX,
measureRect.pageY);
callback.call(
rt,
{jsi::Value{rt, measureRect.x},
jsi::Value{rt, measureRect.y},
jsi::Value{rt, measureRect.width},
jsi::Value{rt, measureRect.height},
jsi::Value{rt, measureRect.pageX},
jsi::Value{rt, measureRect.pageY}});
}
void NativeDOM::measureInWindow(
jsi::Runtime& rt,
std::shared_ptr<const ShadowNode> shadowNode,
const MeasureInWindowOnSuccessCallback& callback) {
jsi::Function callback) {
auto currentRevision =
getCurrentShadowTreeRevision(rt, shadowNode->getSurfaceId());
if (currentRevision == nullptr) {
callback(0, 0, 0, 0);
callback.call(rt, {0, 0, 0, 0});
return;
}
auto rect = dom::measureInWindow(currentRevision, *shadowNode);
callback(rect.x, rect.y, rect.width, rect.height);
callback.call(
rt,
{jsi::Value{rt, rect.x},
jsi::Value{rt, rect.y},
jsi::Value{rt, rect.width},
jsi::Value{rt, rect.height}});
}
void NativeDOM::measureLayout(
@@ -428,7 +434,7 @@ void NativeDOM::measureLayout(
std::shared_ptr<const ShadowNode> shadowNode,
std::shared_ptr<const ShadowNode> relativeToShadowNode,
jsi::Function onFail,
const MeasureLayoutOnSuccessCallback& onSuccess) {
jsi::Function onSuccess) {
auto currentRevision =
getCurrentShadowTreeRevision(rt, shadowNode->getSurfaceId());
if (currentRevision == nullptr) {
@@ -446,7 +452,12 @@ void NativeDOM::measureLayout(
auto rect = maybeRect.value();
onSuccess(rect.x, rect.y, rect.width, rect.height);
onSuccess.call(
rt,
{jsi::Value{rt, rect.x},
jsi::Value{rt, rect.y},
jsi::Value{rt, rect.width},
jsi::Value{rt, rect.height}});
}
#pragma mark - Legacy direct manipulation APIs (for `ReactNativeElement`).
@@ -21,15 +21,6 @@
namespace facebook::react {
using MeasureOnSuccessCallback =
SyncCallback<void(double, double, double, double, double, double)>;
using MeasureInWindowOnSuccessCallback =
SyncCallback<void(double, double, double, double)>;
using MeasureLayoutOnSuccessCallback =
SyncCallback<void(double, double, double, double)>;
class NativeDOM : public NativeDOMCxxSpec<NativeDOM> {
public:
NativeDOM(std::shared_ptr<CallInvoker> jsInvoker);
@@ -126,19 +117,19 @@ class NativeDOM : public NativeDOMCxxSpec<NativeDOM> {
void measure(
jsi::Runtime& rt,
std::shared_ptr<const ShadowNode> shadowNode,
const MeasureOnSuccessCallback& callback);
jsi::Function callback);
void measureInWindow(
jsi::Runtime& rt,
std::shared_ptr<const ShadowNode> shadowNode,
const MeasureInWindowOnSuccessCallback& callback);
jsi::Function callback);
void measureLayout(
jsi::Runtime& rt,
std::shared_ptr<const ShadowNode> shadowNode,
std::shared_ptr<const ShadowNode> relativeToShadowNode,
jsi::Function onFail,
const MeasureLayoutOnSuccessCallback& onSuccess);
jsi::Function onSuccess);
#pragma mark - Legacy direct manipulation APIs (for `ReactNativeElement`).
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<09ffa5d69974c01761505c26a61ce865>>
* @generated SignedSource<<aebe2ba2618903a0ac2df06f18df8c75>>
*/
/**
@@ -49,6 +49,11 @@ bool NativeReactNativeFeatureFlags::commonTestFlagWithoutNativeImplementation(
return false;
}
bool NativeReactNativeFeatureFlags::animatedShouldSignalBatch(
jsi::Runtime& /*runtime*/) {
return ReactNativeFeatureFlags::animatedShouldSignalBatch();
}
bool NativeReactNativeFeatureFlags::cxxNativeAnimatedEnabled(
jsi::Runtime& /*runtime*/) {
return ReactNativeFeatureFlags::cxxNativeAnimatedEnabled();
@@ -59,6 +64,11 @@ bool NativeReactNativeFeatureFlags::cxxNativeAnimatedRemoveJsSync(
return ReactNativeFeatureFlags::cxxNativeAnimatedRemoveJsSync();
}
bool NativeReactNativeFeatureFlags::disableMainQueueSyncDispatchIOS(
jsi::Runtime& /*runtime*/) {
return ReactNativeFeatureFlags::disableMainQueueSyncDispatchIOS();
}
bool NativeReactNativeFeatureFlags::disableMountItemReorderingAndroid(
jsi::Runtime& /*runtime*/) {
return ReactNativeFeatureFlags::disableMountItemReorderingAndroid();
@@ -109,11 +119,6 @@ bool NativeReactNativeFeatureFlags::enableDoubleMeasurementFixAndroid(
return ReactNativeFeatureFlags::enableDoubleMeasurementFixAndroid();
}
bool NativeReactNativeFeatureFlags::enableEagerMainQueueModulesOnIOS(
jsi::Runtime& /*runtime*/) {
return ReactNativeFeatureFlags::enableEagerMainQueueModulesOnIOS();
}
bool NativeReactNativeFeatureFlags::enableEagerRootViewAttachment(
jsi::Runtime& /*runtime*/) {
return ReactNativeFeatureFlags::enableEagerRootViewAttachment();
@@ -169,6 +174,11 @@ bool NativeReactNativeFeatureFlags::enableMainQueueCoordinatorOnIOS(
return ReactNativeFeatureFlags::enableMainQueueCoordinatorOnIOS();
}
bool NativeReactNativeFeatureFlags::enableMainQueueModulesOnIOS(
jsi::Runtime& /*runtime*/) {
return ReactNativeFeatureFlags::enableMainQueueModulesOnIOS();
}
bool NativeReactNativeFeatureFlags::enableModuleArgumentNSNullConversionIOS(
jsi::Runtime& /*runtime*/) {
return ReactNativeFeatureFlags::enableModuleArgumentNSNullConversionIOS();
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<736f6e9a9941d0a9a6fbde5c038f1622>>
* @generated SignedSource<<f3336bad491a91abb3af7e8fcd7e5938>>
*/
/**
@@ -38,10 +38,14 @@ class NativeReactNativeFeatureFlags
bool commonTestFlagWithoutNativeImplementation(jsi::Runtime& runtime);
bool animatedShouldSignalBatch(jsi::Runtime& runtime);
bool cxxNativeAnimatedEnabled(jsi::Runtime& runtime);
bool cxxNativeAnimatedRemoveJsSync(jsi::Runtime& runtime);
bool disableMainQueueSyncDispatchIOS(jsi::Runtime& runtime);
bool disableMountItemReorderingAndroid(jsi::Runtime& runtime);
bool disableTextLayoutManagerCacheAndroid(jsi::Runtime& runtime);
@@ -62,8 +66,6 @@ class NativeReactNativeFeatureFlags
bool enableDoubleMeasurementFixAndroid(jsi::Runtime& runtime);
bool enableEagerMainQueueModulesOnIOS(jsi::Runtime& runtime);
bool enableEagerRootViewAttachment(jsi::Runtime& runtime);
bool enableFabricLogs(jsi::Runtime& runtime);
@@ -86,6 +88,8 @@ class NativeReactNativeFeatureFlags
bool enableMainQueueCoordinatorOnIOS(jsi::Runtime& runtime);
bool enableMainQueueModulesOnIOS(jsi::Runtime& runtime);
bool enableModuleArgumentNSNullConversionIOS(jsi::Runtime& runtime);
bool enableNativeCSSParsing(jsi::Runtime& runtime);
@@ -224,11 +224,7 @@ AccessibilityProps::AccessibilityProps(
// it probably can, but this is a fairly rare edge-case that (1) is easy-ish
// to work around here, and (2) would require very careful work to address
// this case and not regress the more common cases.
if (ReactNativeFeatureFlags::enableCppPropsIteratorSetter()) {
accessibilityRole = sourceProps.accessibilityRole;
role = sourceProps.role;
accessibilityTraits = sourceProps.accessibilityTraits;
} else {
if (!ReactNativeFeatureFlags::enableCppPropsIteratorSetter()) {
auto* accessibilityRoleValue =
rawProps.at("accessibilityRole", nullptr, nullptr);
auto* roleValue = rawProps.at("role", nullptr, nullptr);
@@ -491,6 +491,45 @@ inline static void updateAccessibilityStateProp(
result["accessibilityState"] = resultState;
}
static folly::dynamic toDynamic(const std::vector<BoxShadow>& boxShadow) {
folly::dynamic boxShadowResult = folly::dynamic::array();
for (const auto& boxShadowValue : boxShadow) {
folly::dynamic boxShadowValueResult = folly::dynamic::object();
boxShadowValueResult["offsetX"] = boxShadowValue.offsetX;
boxShadowValueResult["offsetY"] = boxShadowValue.offsetY;
boxShadowValueResult["blurRadius"] = boxShadowValue.blurRadius;
boxShadowValueResult["spreadDistance"] = boxShadowValue.spreadDistance;
boxShadowValueResult["color"] = *boxShadowValue.color;
boxShadowValueResult["inset"] = boxShadowValue.inset;
boxShadowResult.push_back(boxShadowValueResult);
}
return boxShadowResult;
}
static folly::dynamic toDynamic(const std::vector<FilterFunction>& filter) {
folly::dynamic filterResult = folly::dynamic::array();
for (const auto& filterFunction : filter) {
folly::dynamic filterFunctionResult = folly::dynamic::object();
std::string typeKey = toString(filterFunction.type);
if (std::holds_alternative<Float>(filterFunction.parameters)) {
filterFunctionResult[typeKey] =
std::get<Float>(filterFunction.parameters);
} else if (std::holds_alternative<DropShadowParams>(
filterFunction.parameters)) {
const auto& parameters =
std::get<DropShadowParams>(filterFunction.parameters);
folly::dynamic parametersResult = folly::dynamic::object();
parametersResult["offsetX"] = parameters.offsetX;
parametersResult["offsetY"] = parameters.offsetY;
parametersResult["standardDeviation"] = parameters.standardDeviation;
parametersResult["color"] = *parameters.color;
filterFunctionResult[typeKey] = parametersResult;
}
filterResult.push_back(filterFunctionResult);
}
return filterResult;
}
ComponentName HostPlatformViewProps::getDiffPropsImplementationTarget() const {
return "View";
}
@@ -1,20 +0,0 @@
/*
* 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.
*/
#pragma once
#include <react/renderer/components/virtualviewexperimental/VirtualViewExperimentalShadowNode.h>
#include <react/renderer/core/ConcreteComponentDescriptor.h>
namespace facebook::react {
/*
* Descriptor for <VirtualView2> component.
*/
using VirtualViewExperimentalComponentDescriptor =
ConcreteComponentDescriptor<VirtualViewExperimentalShadowNode>;
} // namespace facebook::react
@@ -1,39 +0,0 @@
/*
* 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.
*/
#pragma once
#include <react/renderer/components/FBReactNativeSpec/EventEmitters.h>
#include <react/renderer/components/FBReactNativeSpec/Props.h>
#include <react/renderer/components/view/ConcreteViewShadowNode.h>
namespace facebook::react {
constexpr const char VirtualViewExperimentalComponentName[] =
"VirtualViewExperimental";
/*
* `ShadowNode` for <VirtualViewExperimental> component.
*/
class VirtualViewExperimentalShadowNode final
: public ConcreteViewShadowNode<
VirtualViewExperimentalComponentName,
VirtualViewExperimentalProps,
VirtualViewEventEmitter> {
public:
using ConcreteViewShadowNode::ConcreteViewShadowNode;
static ShadowNodeTraits BaseTraits() {
auto traits = ConcreteViewShadowNode::BaseTraits();
// <VirtualView> has a side effect: it listens to scroll events.
// It must not be culled, otherwise Fling will not work.
traits.set(ShadowNodeTraits::Trait::Unstable_uncullableView);
return traits;
}
};
} // namespace facebook::react
@@ -36,7 +36,7 @@ std::optional<double> DynamicEventPayload::extractValue(
if (dynamic.type() == folly::dynamic::Type::DOUBLE) {
return dynamic.asDouble();
} else if (dynamic.type() == folly::dynamic::Type::INT64) {
return static_cast<double>(dynamic.asInt());
return dynamic.asInt();
}
return std::nullopt;
}
@@ -82,15 +82,6 @@ class ShadowNodeTraits {
// Must not be set directly. It is used by the view culling algorithm to
// efficiently determine if a node is uncullable.
Unstable_uncullableTrace = 1 << 13,
// Indicates that the `YogaLayoutableShadowNode` must set `isDirty` flag for
// Yoga node when a `ShadowNode` is being cloned. `ShadowNode`s that modify
// Yoga styles in the constructor (or later) *after* the `ShadowNode`
// is cloned must set this trait.
// Any Yoga node (not only Leaf ones) can have this trait.
// **Deprecated**: This trait is deprecated and will be removed in a future
// version of React Native.
DirtyYogaNode = 1 << 14,
};
/*
@@ -34,9 +34,9 @@ constexpr uint8_t hexToNumeric(std::string_view hex, HexColorType hexType) {
}
if (hexType == HexColorType::Short) {
return static_cast<uint8_t>(result * 16 + result);
return result * 16 + result;
} else {
return static_cast<uint8_t>(result);
return result;
}
}

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