mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Compare commits
84
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
09900a900d | ||
|
|
21cd09d4c0 | ||
|
|
d00de31aef | ||
|
|
de67d6ec67 | ||
|
|
88bafeddab | ||
|
|
86994a6e22 | ||
|
|
b795d61592 | ||
|
|
0fd060f558 | ||
|
|
9967908e89 | ||
|
|
a9ece0c302 | ||
|
|
5d3d23b32e | ||
|
|
bd198324d8 | ||
|
|
2f67285545 | ||
|
|
4edc33e4e1 | ||
|
|
1b7c9ea523 | ||
|
|
cb59eb2b57 | ||
|
|
5050d0a89e | ||
|
|
46f3e32019 | ||
|
|
10bb2241fc | ||
|
|
6b550a279e | ||
|
|
339dc4979c | ||
|
|
21b93d8d7d | ||
|
|
09daad27ea | ||
|
|
b4a57dd85f | ||
|
|
f68e2b47fb | ||
|
|
188caa04e7 | ||
|
|
eca6c1b965 | ||
|
|
42b8921d91 | ||
|
|
f3b6eeb96e | ||
|
|
f004cd39bc | ||
|
|
0d2e0abc45 | ||
|
|
7dc84491e9 | ||
|
|
2a93767651 | ||
|
|
c2f39cfdd8 | ||
|
|
7f224941bb | ||
|
|
7cd0b42ca0 | ||
|
|
fc535ef542 | ||
|
|
04b6735fa5 | ||
|
|
e93afbd407 | ||
|
|
a5d61564a8 | ||
|
|
011425358a | ||
|
|
2321ae17ea | ||
|
|
bb0c370ab7 | ||
|
|
8524c13b5b | ||
|
|
1d452b17bf | ||
|
|
6747f2b118 | ||
|
|
79ca9036d3 | ||
|
|
e7d9e0d197 | ||
|
|
b18cd587dc | ||
|
|
cf45aa9dbc | ||
|
|
60b1b7a301 | ||
|
|
42ea4bc594 | ||
|
|
24777bba07 | ||
|
|
8083cb4ab1 | ||
|
|
77db9343b1 | ||
|
|
ec5bde62b6 | ||
|
|
bb3ef784e3 | ||
|
|
b8550251d8 | ||
|
|
5dc3e18671 | ||
|
|
e79808fa4b | ||
|
|
9747c955ac | ||
|
|
6f6945e64f | ||
|
|
0021dafc51 | ||
|
|
e69777d258 | ||
|
|
dc5110a8f2 | ||
|
|
3de1dc0fd1 | ||
|
|
88cb7832ea | ||
|
|
aa2a5a682f | ||
|
|
a0543b773c | ||
|
|
f5abce0932 | ||
|
|
38cf247c63 | ||
|
|
1fc168f005 | ||
|
|
5e0eb0a17c | ||
|
|
acd07c7e1c | ||
|
|
ff38d59cff | ||
|
|
7bbb13c9be | ||
|
|
d4b36b0300 | ||
|
|
84a2765c2a | ||
|
|
6b8bc5a1d0 | ||
|
|
0144798e25 | ||
|
|
263ccad3c5 | ||
|
|
c2a3e4420e | ||
|
|
5d4c22b4a7 | ||
|
|
b0606ba041 |
@@ -9,12 +9,3 @@ end_of_line = lf
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.gradle]
|
||||
indent_size = 4
|
||||
|
||||
[*.kts]
|
||||
indent_size = 4
|
||||
|
||||
[BUCK]
|
||||
indent_size = 4
|
||||
|
||||
@@ -48,6 +48,14 @@ 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: |
|
||||
@@ -73,6 +81,7 @@ 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
|
||||
|
||||
|
||||
@@ -94,6 +94,14 @@ 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:
|
||||
@@ -105,12 +113,13 @@ 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
|
||||
|
||||
@@ -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') }}-${{ hashFiles('packages/react-native/scripts/ios-prebuild/setup.js') }}
|
||||
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/**/*') }}
|
||||
path: packages/react-native/
|
||||
- name: Setup node.js
|
||||
if: steps.restore-ios-slice.outputs.cache-hit != 'true'
|
||||
@@ -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') }}-${{ hashFiles('packages/react-native/scripts/ios-prebuild/setup.js') }}
|
||||
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/**/*') }}
|
||||
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') }}-${{ hashFiles('packages/react-native/scripts/ios-prebuild/setup.js') }}
|
||||
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/**/*') }}
|
||||
- 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') }}-${{ hashFiles('packages/react-native/scripts/ios-prebuild/setup.js') }}
|
||||
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/**/*') }}
|
||||
|
||||
@@ -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]
|
||||
[build_apple_slices_hermes, prepare_hermes_workspace, build_hermes_macos, prebuild_apple_dependencies, prebuild_react_native_core]
|
||||
env:
|
||||
HERMES_WS_DIR: /tmp/hermes
|
||||
HERMES_TARBALL_ARTIFACTS_DIR: /tmp/hermes/hermes-runtime-darwin
|
||||
@@ -141,31 +141,12 @@ 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 }}
|
||||
|
||||
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 }}
|
||||
flavor: Debug
|
||||
|
||||
test_ios_rntester:
|
||||
runs-on: macos-14-large
|
||||
needs:
|
||||
[build_apple_slices_hermes, prepare_hermes_workspace, build_hermes_macos, prebuild_apple_dependencies]
|
||||
[build_apple_slices_hermes, prepare_hermes_workspace, build_hermes_macos, prebuild_apple_dependencies, prebuild_react_native_core]
|
||||
env:
|
||||
HERMES_WS_DIR: /tmp/hermes
|
||||
HERMES_TARBALL_ARTIFACTS_DIR: /tmp/hermes/hermes-runtime-darwin
|
||||
@@ -174,14 +155,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:
|
||||
run-unit-tests: "false"
|
||||
use-frameworks: StaticLibraries
|
||||
use-frameworks: ${{ matrix.frameworks }}
|
||||
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
|
||||
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
|
||||
flavor: ${{ matrix.flavor }}
|
||||
@@ -264,6 +245,14 @@ 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")
|
||||
@@ -286,6 +275,7 @@ 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 \
|
||||
@@ -548,7 +538,7 @@ jobs:
|
||||
|
||||
test_ios_helloworld_with_ruby_3_2_0:
|
||||
runs-on: macos-14
|
||||
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
|
||||
needs: [prepare_hermes_workspace, build_hermes_macos, prebuild_apple_dependencies, prebuild_react_native_core] # prepare_hermes_workspace must be there because we need its reference to retrieve a couple of outputs
|
||||
env:
|
||||
PROJECT_NAME: iOSTemplateProject
|
||||
HERMES_WS_DIR: /tmp/hermes
|
||||
@@ -565,7 +555,7 @@ jobs:
|
||||
|
||||
test_ios_helloworld:
|
||||
runs-on: macos-14
|
||||
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
|
||||
needs: [prepare_hermes_workspace, build_hermes_macos, prebuild_apple_dependencies, prebuild_react_native_core] # prepare_hermes_workspace must be there because we need its reference to retrieve a couple of outputs
|
||||
strategy:
|
||||
matrix:
|
||||
flavor: [Debug, Release]
|
||||
|
||||
@@ -1,5 +1,35 @@
|
||||
# Changelog
|
||||
|
||||
## v0.81.0-rc.1
|
||||
|
||||
### Added
|
||||
|
||||
#### iOS specific
|
||||
|
||||
- Add release/debug switch script for React-Core-prebuilt ([42d1a7934c](https://github.com/facebook/react-native/commit/42d1a7934cad4b2c92653e3fa7781c2af8f44df4) by [@chrfalch](https://github.com/chrfalch))
|
||||
- Added support for using USE_FRAMEWORKS with prebuilt React Native Core ([40e45f5366](https://github.com/facebook/react-native/commit/40e45f53661ce80c3a6fbbf07f52dc900afcad52) by [@chrfalch](https://github.com/chrfalch))
|
||||
- Add the `ENTERPRISE_REPOSITORY` env variable to cocopaods infra ([23f3bf9239](https://github.com/facebook/react-native/commit/23f3bf9239a849590f1c72b25732d0090780128c) by [@cipolleschi](https://github.com/cipolleschi))
|
||||
|
||||
### Changed
|
||||
|
||||
- Bump Metro to 0.83.0 ([6b9f5d622f](https://github.com/facebook/react-native/commit/6b9f5d622ffbe79da8f4e7b7d8094504a480425e) by [@robhogan](https://github.com/robhogan))
|
||||
|
||||
#### Android specific
|
||||
|
||||
- Gradle to 8.14.3 ([6892dde363](https://github.com/facebook/react-native/commit/6892dde36373bbef2d0afe535ae818b1a7164f08) by [@cortinico](https://github.com/cortinico))
|
||||
- Expose `react_renderer_bridging` headers via prefab ([d1730ff960](https://github.com/facebook/react-native/commit/d1730ff960fcb9a01ee94b9e46e5a9fbb7d73f4a) by [@tomekzaw](https://github.com/tomekzaw))
|
||||
- Introduce more deprecation warnings for Legacy Arch classes ([625f69f284](https://github.com/facebook/react-native/commit/625f69f284ddfd9c6beecaa4052a871d092053ef) by [@cortinico](https://github.com/cortinico))
|
||||
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed nodes with `display: contents` set being cloned with the wrong owner ([d4b36b0300](https://github.com/facebook/react-native/commit/d4b36b03003eb2de9eaf5b57bb639bae8cc12f20) by [@j-piasecki](https://github.com/j-piasecki))
|
||||
|
||||
#### iOS specific
|
||||
|
||||
- Fixed premature return in header file generation from podspec globs ([f2b064c2d4](https://github.com/facebook/react-native/commit/f2b064c2d40c39017ac2a31bf3caf8acef23038c) by [@chrfalch](https://github.com/chrfalch))
|
||||
|
||||
|
||||
## v0.81.0-rc.0
|
||||
|
||||
### Breaking
|
||||
|
||||
@@ -13,6 +13,7 @@ plugins {
|
||||
alias(libs.plugins.kotlin.android) apply false
|
||||
alias(libs.plugins.binary.compatibility.validator) apply true
|
||||
alias(libs.plugins.android.test) apply false
|
||||
alias(libs.plugins.ktfmt) apply true
|
||||
}
|
||||
|
||||
val reactAndroidProperties = java.util.Properties()
|
||||
@@ -130,3 +131,30 @@ if (project.findProperty("react.internal.useHermesNightly")?.toString()?.toBoole
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ktfmt {
|
||||
blockIndent.set(2)
|
||||
continuationIndent.set(4)
|
||||
maxWidth.set(100)
|
||||
removeUnusedImports.set(false)
|
||||
manageTrailingCommas.set(false)
|
||||
}
|
||||
|
||||
// Configure ktfmt tasks to include gradle-plugin
|
||||
listOf("ktfmtCheck", "ktfmtFormat").forEach { taskName ->
|
||||
tasks.named(taskName) { dependsOn(gradle.includedBuild("gradle-plugin").task(":$taskName")) }
|
||||
}
|
||||
|
||||
allprojects {
|
||||
// Apply exclusions for specific files that should not be formatted
|
||||
val excludePatterns =
|
||||
listOf(
|
||||
"**/build/**",
|
||||
"**/hermes-engine/**",
|
||||
"**/internal/featureflags/**",
|
||||
"**/systeminfo/ReactNativeVersion.kt")
|
||||
listOf(
|
||||
com.ncorti.ktfmt.gradle.tasks.KtfmtCheckTask::class,
|
||||
com.ncorti.ktfmt.gradle.tasks.KtfmtFormatTask::class)
|
||||
.forEach { tasks.withType(it) { exclude(excludePatterns) } }
|
||||
}
|
||||
|
||||
+8
-6
@@ -19,6 +19,8 @@
|
||||
"featureflags": "yarn --cwd packages/react-native featureflags",
|
||||
"js-api-diff": "node ./scripts/js-api/diff-api-snapshot",
|
||||
"lint-ci": "./.github/workflow-scripts/analyze_code.sh && yarn shellcheck",
|
||||
"lint-kotlin-check": "./gradlew ktfmtCheck",
|
||||
"lint-kotlin": "./gradlew ktfmtFormat",
|
||||
"lint-markdown": "markdownlint-cli2 2>&1",
|
||||
"lint": "eslint --max-warnings 0 .",
|
||||
"prettier": "prettier --write \"./**/*.{js,md,yml,ts,tsx}\"",
|
||||
@@ -28,8 +30,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-e2e-local-clean": "node ./scripts/release-testing/test-e2e-local-clean.js",
|
||||
"test-e2e-local": "node ./scripts/release-testing/test-e2e-local.js",
|
||||
"test-release-local-clean": "node ./scripts/release-testing/test-release-local-clean.js",
|
||||
"test-release-local": "node ./scripts/release-testing/test-release-local.js",
|
||||
"test-ios": "./scripts/objc-test.sh test",
|
||||
"test-typescript": "tsc -p packages/react-native/types/tsconfig.json",
|
||||
"test-generated-typescript": "tsc -p packages/react-native/types_generated/tsconfig.test.json",
|
||||
@@ -58,7 +60,7 @@
|
||||
"@react-native/metro-config": "0.81.0-main",
|
||||
"@tsconfig/node22": "22.0.2",
|
||||
"@types/react": "^19.1.0",
|
||||
"@typescript-eslint/parser": "^7.1.1",
|
||||
"@typescript-eslint/parser": "^8.36.0",
|
||||
"ansi-styles": "^4.2.1",
|
||||
"babel-plugin-minify-dead-code-elimination": "^0.5.2",
|
||||
"babel-plugin-syntax-hermes-parser": "0.29.1",
|
||||
@@ -93,9 +95,9 @@
|
||||
"jest-snapshot": "^29.7.0",
|
||||
"markdownlint-cli2": "^0.17.2",
|
||||
"markdownlint-rule-relative-links": "^3.0.0",
|
||||
"metro-babel-register": "^0.82.5",
|
||||
"metro-memory-fs": "^0.82.5",
|
||||
"metro-transform-plugins": "^0.82.5",
|
||||
"memfs": "^4.7.7",
|
||||
"metro-babel-register": "^0.83.0",
|
||||
"metro-transform-plugins": "^0.83.0",
|
||||
"micromatch": "^4.0.4",
|
||||
"node-fetch": "^2.2.0",
|
||||
"nullthrows": "^1.1.1",
|
||||
|
||||
@@ -25,13 +25,13 @@
|
||||
"@react-native/dev-middleware": "0.81.0-main",
|
||||
"debug": "^4.4.0",
|
||||
"invariant": "^2.2.4",
|
||||
"metro": "^0.82.5",
|
||||
"metro-config": "^0.82.5",
|
||||
"metro-core": "^0.82.5",
|
||||
"metro": "^0.83.0",
|
||||
"metro-config": "^0.83.0",
|
||||
"metro-core": "^0.83.0",
|
||||
"semver": "^7.1.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"metro-resolver": "^0.82.5"
|
||||
"metro-resolver": "^0.83.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@react-native-community/cli": "*",
|
||||
|
||||
@@ -147,7 +147,7 @@ async function runServer(
|
||||
// $FlowIgnore[cannot-write] Assigning to readonly property
|
||||
metroConfig.reporter = reporter;
|
||||
|
||||
const serverInstance = await Metro.runServer(metroConfig, {
|
||||
await Metro.runServer(metroConfig, {
|
||||
host: args.host,
|
||||
secure: args.https,
|
||||
secureCert: args.cert,
|
||||
@@ -161,18 +161,6 @@ 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);
|
||||
}
|
||||
|
||||
|
||||
@@ -76,9 +76,8 @@ function getNodePackagePath(packageName: string): string {
|
||||
}
|
||||
|
||||
function metro(...args: $ReadOnlyArray<string>): ExecaPromise {
|
||||
const metroPath = getNodePackagePath(path.join('metro', 'src', 'cli.js'));
|
||||
log(`🚇 ${metroPath} ${args.join(' ')} `);
|
||||
return execa('node', [metroPath, ...args]);
|
||||
log(`🚇 metro ${args.join(' ')} `);
|
||||
return execa('npx', ['--offline', 'metro', ...args]);
|
||||
}
|
||||
|
||||
export const tasks = {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
@generated SignedSource<<1ce3fb7dd23581737fedaf58528fe575>>
|
||||
Git revision: 844f225009e6445d088ed0e431d1fc430325ed95
|
||||
@generated SignedSource<<e2d97b04634bf3b566f33d455f38658f>>
|
||||
Git revision: 8dc0d5b365e6b4600b78e5a7381aa861d8c1c81e
|
||||
Built with --nohooks: false
|
||||
Is local checkout: false
|
||||
Remote URL: https://github.com/facebook/react-native-devtools-frontend
|
||||
|
||||
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+2
-2
File diff suppressed because one or more lines are too long
+5
-4
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
@@ -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": "^7.1.1",
|
||||
"@typescript-eslint/parser": "^7.1.1",
|
||||
"@typescript-eslint/eslint-plugin": "^8.36.0",
|
||||
"@typescript-eslint/parser": "^8.36.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-plugin-eslint-comments": "^3.2.0",
|
||||
"eslint-plugin-ft-flow": "^2.0.1",
|
||||
|
||||
@@ -5,7 +5,10 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
plugins { alias(libs.plugins.kotlin.jvm).apply(false) }
|
||||
plugins {
|
||||
alias(libs.plugins.kotlin.jvm).apply(false)
|
||||
alias(libs.plugins.ktfmt).apply(true)
|
||||
}
|
||||
|
||||
tasks.register("build") {
|
||||
dependsOn(
|
||||
@@ -24,3 +27,21 @@ tasks.register("clean") {
|
||||
":shared:clean",
|
||||
)
|
||||
}
|
||||
|
||||
tasks.named("ktfmtCheck") {
|
||||
dependsOn(
|
||||
":react-native-gradle-plugin:ktfmtCheck",
|
||||
":settings-plugin:ktfmtCheck",
|
||||
":shared-testutil:ktfmtCheck",
|
||||
":shared:ktfmtCheck",
|
||||
)
|
||||
}
|
||||
|
||||
tasks.named("ktfmtFormat") {
|
||||
dependsOn(
|
||||
":react-native-gradle-plugin:ktfmtFormat",
|
||||
":settings-plugin:ktfmtFormat",
|
||||
":shared-testutil:ktfmtFormat",
|
||||
":shared:ktfmtFormat",
|
||||
)
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ javapoet = "1.13.0"
|
||||
junit = "4.13.2"
|
||||
kotlin = "2.1.20"
|
||||
assertj = "3.25.1"
|
||||
ktfmt = "0.22.0"
|
||||
|
||||
[libraries]
|
||||
kotlin-gradle-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
|
||||
@@ -18,3 +19,4 @@ assertj = { module = "org.assertj:assertj-core", version.ref = "assertj" }
|
||||
|
||||
[plugins]
|
||||
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
|
||||
ktfmt = { id = "com.ncorti.ktfmt.gradle", version.ref = "ktfmt" }
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
|
||||
plugins {
|
||||
alias(libs.plugins.kotlin.jvm)
|
||||
alias(libs.plugins.ktfmt)
|
||||
id("java-gradle-plugin")
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
|
||||
plugins {
|
||||
alias(libs.plugins.kotlin.jvm)
|
||||
alias(libs.plugins.ktfmt)
|
||||
id("java-gradle-plugin")
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,10 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinVersion
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
|
||||
plugins { alias(libs.plugins.kotlin.jvm) }
|
||||
plugins {
|
||||
alias(libs.plugins.kotlin.jvm)
|
||||
alias(libs.plugins.ktfmt)
|
||||
}
|
||||
|
||||
repositories { mavenCentral() }
|
||||
|
||||
|
||||
@@ -10,7 +10,10 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinVersion
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
|
||||
plugins { alias(libs.plugins.kotlin.jvm) }
|
||||
plugins {
|
||||
alias(libs.plugins.kotlin.jvm)
|
||||
alias(libs.plugins.ktfmt)
|
||||
}
|
||||
|
||||
repositories { mavenCentral() }
|
||||
|
||||
|
||||
@@ -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.82.5",
|
||||
"metro-runtime": "^0.82.5"
|
||||
"metro-config": "^0.83.0",
|
||||
"metro-runtime": "^0.83.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,12 +51,13 @@ if (!schemaQuery.startsWith('@')) {
|
||||
const schemaQueryOutputFile = schemaQuery.replace(/^@/, '');
|
||||
const schemaQueryOutput = fs.readFileSync(schemaQueryOutputFile, 'utf8');
|
||||
|
||||
const schemaFiles = schemaQueryOutput.split(' ');
|
||||
const modules: {
|
||||
[hasteModuleName: string]: NativeModuleSchema | ComponentSchema,
|
||||
} = {};
|
||||
const specNameToFile: {[hasteModuleName: string]: string} = {};
|
||||
|
||||
const schemaFiles =
|
||||
schemaQueryOutput.length > 0 ? schemaQueryOutput.split(' ') : [];
|
||||
for (const file of schemaFiles) {
|
||||
const schema: SchemaType = JSON.parse(fs.readFileSync(file, 'utf8'));
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
`;
|
||||
|
||||
+240
-240
File diff suppressed because it is too large
Load Diff
@@ -537,3 +537,160 @@ 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);
|
||||
});
|
||||
|
||||
Vendored
+53
-1
@@ -5,7 +5,6 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @fantom_flags enableFixForParentTagDuringReparenting:true
|
||||
* @fantom_flags enableSynchronousStateUpdates:true
|
||||
* @fantom_flags enableViewCulling:true
|
||||
* @flow strict-local
|
||||
* @format
|
||||
@@ -2556,3 +2555,56 @@ describe('culling inside ScrollView with overflow visible', () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('horizontal ScrollView in RTL script', () => {
|
||||
it('renders item 1', () => {
|
||||
const root = Fantom.createRoot({viewportWidth: 100, viewportHeight: 100});
|
||||
|
||||
Fantom.runTask(() => {
|
||||
root.render(
|
||||
<ScrollView
|
||||
style={{direction: 'rtl', height: 100, width: 100}}
|
||||
horizontal={true}>
|
||||
<View nativeID={'item1'} style={{height: 90, width: 90, margin: 5}} />
|
||||
<View nativeID={'item2'} style={{height: 90, width: 90, margin: 5}} />
|
||||
</ScrollView>,
|
||||
);
|
||||
});
|
||||
|
||||
expect(root.takeMountingManagerLogs()).toEqual([
|
||||
'Update {type: "RootView", nativeID: (root)}',
|
||||
'Create {type: "ScrollView", nativeID: (N/A)}',
|
||||
'Create {type: "AndroidHorizontalScrollContentView", nativeID: (N/A)}',
|
||||
'Create {type: "View", nativeID: "item1"}',
|
||||
'Insert {type: "View", parentNativeID: (N/A), index: 0, nativeID: "item1"}',
|
||||
'Insert {type: "AndroidHorizontalScrollContentView", parentNativeID: (N/A), index: 0, nativeID: (N/A)}',
|
||||
'Insert {type: "ScrollView", parentNativeID: (root), index: 0, nativeID: (N/A)}',
|
||||
]);
|
||||
});
|
||||
|
||||
it('takes contentOffset into account', () => {
|
||||
const root = Fantom.createRoot({viewportWidth: 100, viewportHeight: 100});
|
||||
|
||||
Fantom.runTask(() => {
|
||||
root.render(
|
||||
<ScrollView
|
||||
style={{direction: 'rtl', height: 100, width: 100}}
|
||||
horizontal={true}
|
||||
contentOffset={{x: 100, y: 0}}>
|
||||
<View nativeID={'item1'} style={{height: 90, width: 90, margin: 5}} />
|
||||
<View nativeID={'item2'} style={{height: 90, width: 90, margin: 5}} />
|
||||
</ScrollView>,
|
||||
);
|
||||
});
|
||||
|
||||
expect(root.takeMountingManagerLogs()).toEqual([
|
||||
'Update {type: "RootView", nativeID: (root)}',
|
||||
'Create {type: "ScrollView", nativeID: (N/A)}',
|
||||
'Create {type: "AndroidHorizontalScrollContentView", nativeID: (N/A)}',
|
||||
'Create {type: "View", nativeID: "item2"}',
|
||||
'Insert {type: "View", parentNativeID: (N/A), index: 0, nativeID: "item2"}',
|
||||
'Insert {type: "AndroidHorizontalScrollContentView", parentNativeID: (N/A), index: 0, nativeID: (N/A)}',
|
||||
'Insert {type: "ScrollView", parentNativeID: (root), index: 0, nativeID: (N/A)}',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -10,9 +10,14 @@
|
||||
|
||||
import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
|
||||
|
||||
import type {HostInstance} from 'react-native';
|
||||
|
||||
import ensureInstance from '../../../../src/private/__tests__/utilities/ensureInstance';
|
||||
import * as Fantom from '@react-native/fantom';
|
||||
import * as React from 'react';
|
||||
import {createRef} from 'react';
|
||||
import {View} from 'react-native';
|
||||
import ReactNativeElement from 'react-native/src/private/webapis/dom/nodes/ReactNativeElement';
|
||||
|
||||
describe('<View>', () => {
|
||||
describe('width and height style', () => {
|
||||
@@ -181,6 +186,40 @@ describe('<View>', () => {
|
||||
<rn-view transform='[{"translateX": 10.000000}]' />,
|
||||
);
|
||||
});
|
||||
|
||||
[
|
||||
[undefined, {x: -5, y: 0, width: 20, height: 10}],
|
||||
['50% 50%', {x: -5, y: 0, width: 20, height: 10}],
|
||||
['top left', {x: 0, y: 0, width: 20, height: 10}],
|
||||
['right bottom', {x: -10, y: 0, width: 20, height: 10}],
|
||||
].forEach(([transformOrigin, expectedBounds]) => {
|
||||
it(`applies transformOrigin correctly for ${String(transformOrigin)}`, () => {
|
||||
const root = Fantom.createRoot();
|
||||
|
||||
const viewRef = createRef<HostInstance>();
|
||||
Fantom.runTask(() => {
|
||||
root.render(
|
||||
<View
|
||||
ref={viewRef}
|
||||
style={{
|
||||
width: 10,
|
||||
height: 10,
|
||||
transform: [{scaleX: 2}],
|
||||
transformOrigin,
|
||||
}}
|
||||
/>,
|
||||
);
|
||||
});
|
||||
|
||||
const viewElement = ensureInstance(viewRef.current, ReactNativeElement);
|
||||
|
||||
const viewBounds = viewElement.getBoundingClientRect();
|
||||
expect(viewBounds.x).toBe(expectedBounds.x);
|
||||
expect(viewBounds.y).toBe(expectedBounds.y);
|
||||
expect(viewBounds.width).toBe(expectedBounds.width);
|
||||
expect(viewBounds.height).toBe(expectedBounds.height);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('props', () => {
|
||||
|
||||
+20
-5
@@ -34,6 +34,9 @@ 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
|
||||
@@ -385,6 +388,9 @@ class XMLHttpRequest extends EventTarget {
|
||||
if (requestId !== this._requestId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const start = XMLHttpRequest._profiling ? performance.now() : undefined;
|
||||
|
||||
if (!this._response) {
|
||||
this._response = responseText;
|
||||
} else {
|
||||
@@ -392,8 +398,13 @@ class XMLHttpRequest extends EventTarget {
|
||||
}
|
||||
|
||||
if (XMLHttpRequest._profiling) {
|
||||
performance.mark(
|
||||
'Track:XMLHttpRequest:Incremental Data: ' + this._getMeasureURL(),
|
||||
console.timeStamp(
|
||||
'Incremental Data: ' + this._getMeasureURL(),
|
||||
// $FlowFixMe[extra-arg] Add correct typing for `console.timeStamp`
|
||||
start,
|
||||
undefined,
|
||||
PERFORMANCE_TRACK_NAME,
|
||||
PERFORMANCE_TRACK_GROUP,
|
||||
);
|
||||
}
|
||||
XMLHttpRequest._interceptor &&
|
||||
@@ -442,10 +453,14 @@ class XMLHttpRequest extends EventTarget {
|
||||
this.setReadyState(this.DONE);
|
||||
if (XMLHttpRequest._profiling && this._startTime != null) {
|
||||
const start = this._startTime;
|
||||
performance.measure('Track:XMLHttpRequest:' + this._getMeasureURL(), {
|
||||
console.timeStamp(
|
||||
this._getMeasureURL(),
|
||||
// $FlowFixMe[extra-arg] Add correct typing for `console.timeStamp`
|
||||
start,
|
||||
end: performance.now(),
|
||||
});
|
||||
undefined,
|
||||
PERFORMANCE_TRACK_NAME,
|
||||
PERFORMANCE_TRACK_GROUP,
|
||||
);
|
||||
}
|
||||
if (error) {
|
||||
XMLHttpRequest._interceptor &&
|
||||
|
||||
+4
-1
@@ -18,6 +18,7 @@ end
|
||||
|
||||
header_search_paths = [
|
||||
"\"${PODS_ROOT}/Headers/Public/ReactCodegen/react/renderer/components\"",
|
||||
"\"${PODS_ROOT}/Headers/Public/React-RCTFBReactNativeSpec/FBReactNativeSpec\"",
|
||||
]
|
||||
|
||||
Pod::Spec.new do |s|
|
||||
@@ -45,7 +46,9 @@ Pod::Spec.new do |s|
|
||||
s.dependency "React-Core/RCTPushNotificationHeaders"
|
||||
s.dependency "React-jsi"
|
||||
|
||||
add_dependency(s, "React-RCTFBReactNativeSpec")
|
||||
add_dependency(s, "React-RCTFBReactNativeSpec", :additional_framework_paths => ['FBReactNativeSpec'])
|
||||
add_dependency(s, "ReactCommon", :subspec => "turbomodule/core", :additional_framework_paths => ["react/nativemodule/core"])
|
||||
add_dependency(s, "React-NativeModulesApple")
|
||||
|
||||
add_rncore_dependency(s)
|
||||
end
|
||||
|
||||
@@ -67,7 +67,7 @@ template <typename T>
|
||||
facebook::react::LazyVector<T> RCTBridgingToVec(id value, T (^ctor)(id element))
|
||||
{
|
||||
NSArray *array = RCTBridgingToArray(value);
|
||||
typedef typename facebook::react::LazyVector<T>::size_type _size_t;
|
||||
using _size_t = typename facebook::react::LazyVector<T>::size_type;
|
||||
_size_t size = static_cast<_size_t>(array.count);
|
||||
return facebook::react::LazyVector<T>::fromUnsafeRawValue(array, size, ctor);
|
||||
}
|
||||
|
||||
@@ -166,7 +166,7 @@ let reactJsInspector = RNTarget(
|
||||
name: .reactJsInspector,
|
||||
path: "ReactCommon/jsinspector-modern",
|
||||
excludedPaths: ["tracing", "network", "tests"],
|
||||
dependencies: [.reactNativeDependencies, .reactFeatureFlags, .jsi, .reactJsInspectorTracing, .reactJsInspectorNetwork, .reactRuntimeExecutor],
|
||||
dependencies: [.reactNativeDependencies, .reactFeatureFlags, .jsi, .reactJsInspectorTracing, .reactJsInspectorNetwork, .reactRuntimeExecutor, .reactPerfLogger],
|
||||
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)),
|
||||
|
||||
@@ -47,7 +47,6 @@ 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,13 +304,6 @@ 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();
|
||||
@@ -322,10 +315,6 @@ void RCTUnsafeExecuteOnMainQueueSyncWithError(dispatch_block_t block, NSString *
|
||||
return;
|
||||
}
|
||||
|
||||
if (ReactNativeFeatureFlags::disableMainQueueSyncDispatchIOS()) {
|
||||
RCTLogError(@"RCTUnsafeExecuteOnMainQueueSync: %@", context);
|
||||
}
|
||||
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
block();
|
||||
});
|
||||
@@ -354,10 +343,6 @@ 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);
|
||||
}
|
||||
|
||||
@@ -725,13 +710,13 @@ NSData *__nullable RCTGzipData(NSData *__nullable input, float level)
|
||||
|
||||
void *libz = dlopen("/usr/lib/libz.dylib", RTLD_LAZY);
|
||||
|
||||
typedef int (*DeflateInit2_)(z_streamp, int, int, int, int, int, const char *, int);
|
||||
using DeflateInit2_ = int (*)(z_streamp, int, int, int, int, int, const char *, int);
|
||||
DeflateInit2_ deflateInit2_ = (DeflateInit2_)dlsym(libz, "deflateInit2_");
|
||||
|
||||
typedef int (*Deflate)(z_streamp, int);
|
||||
using Deflate = int (*)(z_streamp, int);
|
||||
Deflate deflate = (Deflate)dlsym(libz, "deflate");
|
||||
|
||||
typedef int (*DeflateEnd)(z_streamp);
|
||||
using DeflateEnd = int (*)(z_streamp);
|
||||
DeflateEnd deflateEnd = (DeflateEnd)dlsym(libz, "deflateEnd");
|
||||
|
||||
z_stream stream;
|
||||
|
||||
@@ -39,7 +39,7 @@ static NSString *const RCTPerfMonitorCellIdentifier = @"RCTPerfMonitorCellIdenti
|
||||
static const CGFloat RCTPerfMonitorBarHeight = 50;
|
||||
static const CGFloat RCTPerfMonitorExpandHeight = 250;
|
||||
|
||||
typedef BOOL (*RCTJSCSetOptionType)(const char *);
|
||||
using RCTJSCSetOptionType = BOOL (*)(const char *);
|
||||
|
||||
NSArray<NSString *> *LabelsForRCTPerformanceLoggerTags();
|
||||
|
||||
|
||||
+30
-25
@@ -24,9 +24,13 @@ using namespace facebook::react;
|
||||
@end
|
||||
|
||||
@implementation RCTPullToRefreshViewComponentView {
|
||||
BOOL _isBeforeInitialLayout;
|
||||
UIRefreshControl *_refreshControl;
|
||||
RCTScrollViewComponentView *__weak _scrollViewComponentView;
|
||||
// This variable keeps track of whether the view is recycled or not. Once the view is recycled, the component
|
||||
// creates a new instance of UIRefreshControl, resetting the native props to the default values.
|
||||
// However, when recycling, we are keeping around the old _props. The flag is used to force the application
|
||||
// of the current props to the newly created UIRefreshControl the first time that updateProps is called.
|
||||
BOOL _recycled;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
@@ -36,8 +40,7 @@ using namespace facebook::react;
|
||||
// attaching and detaching of a pull-to-refresh view to a scroll view.
|
||||
// The pull-to-refresh view is not a subview of this view.
|
||||
self.hidden = YES;
|
||||
|
||||
_isBeforeInitialLayout = YES;
|
||||
_recycled = NO;
|
||||
[self _initializeUIRefreshControl];
|
||||
}
|
||||
|
||||
@@ -63,54 +66,53 @@ using namespace facebook::react;
|
||||
{
|
||||
[super prepareForRecycle];
|
||||
_scrollViewComponentView = nil;
|
||||
_props = nil;
|
||||
_isBeforeInitialLayout = YES;
|
||||
[self _initializeUIRefreshControl];
|
||||
_recycled = YES;
|
||||
}
|
||||
|
||||
- (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &)oldProps
|
||||
{
|
||||
// Prop updates are ignored by _refreshControl until after the initial layout, so just store them in _props until then
|
||||
if (_isBeforeInitialLayout) {
|
||||
_props = std::static_pointer_cast<const PullToRefreshViewProps>(props);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto &oldConcreteProps = static_cast<const PullToRefreshViewProps &>(*_props);
|
||||
const auto &newConcreteProps = static_cast<const PullToRefreshViewProps &>(*props);
|
||||
|
||||
if (newConcreteProps.tintColor != oldConcreteProps.tintColor) {
|
||||
if (_recycled || newConcreteProps.tintColor != oldConcreteProps.tintColor) {
|
||||
_refreshControl.tintColor = RCTUIColorFromSharedColor(newConcreteProps.tintColor);
|
||||
}
|
||||
|
||||
if (newConcreteProps.progressViewOffset != oldConcreteProps.progressViewOffset) {
|
||||
if (_recycled || newConcreteProps.progressViewOffset != oldConcreteProps.progressViewOffset) {
|
||||
[self _updateProgressViewOffset:newConcreteProps.progressViewOffset];
|
||||
}
|
||||
|
||||
BOOL needsUpdateTitle = NO;
|
||||
|
||||
if (newConcreteProps.title != oldConcreteProps.title) {
|
||||
if (_recycled || newConcreteProps.title != oldConcreteProps.title) {
|
||||
needsUpdateTitle = YES;
|
||||
}
|
||||
|
||||
if (newConcreteProps.titleColor != oldConcreteProps.titleColor) {
|
||||
if (_recycled || newConcreteProps.titleColor != oldConcreteProps.titleColor) {
|
||||
needsUpdateTitle = YES;
|
||||
}
|
||||
|
||||
[super updateProps:props oldProps:oldProps];
|
||||
|
||||
if (needsUpdateTitle) {
|
||||
if (_recycled || needsUpdateTitle) {
|
||||
[self _updateTitle];
|
||||
}
|
||||
|
||||
// All prop updates must happen above the call to begin refreshing, or else _refreshControl will ignore the updates
|
||||
if (newConcreteProps.refreshing != oldConcreteProps.refreshing) {
|
||||
if (_recycled || newConcreteProps.refreshing != oldConcreteProps.refreshing) {
|
||||
if (newConcreteProps.refreshing) {
|
||||
[self beginRefreshingProgrammatically];
|
||||
} else {
|
||||
[_refreshControl endRefreshing];
|
||||
}
|
||||
}
|
||||
|
||||
if (_recycled || newConcreteProps.zIndex != oldConcreteProps.zIndex) {
|
||||
_refreshControl.layer.zPosition = newConcreteProps.zIndex.value_or(0);
|
||||
}
|
||||
|
||||
_recycled = NO;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
@@ -155,10 +157,12 @@ using namespace facebook::react;
|
||||
|
||||
// Attempts to begin refreshing before the initial layout are ignored by _refreshControl. So if the control is
|
||||
// refreshing when mounted, we need to call beginRefreshing in layoutSubviews or it won't work.
|
||||
if (_isBeforeInitialLayout) {
|
||||
_isBeforeInitialLayout = NO;
|
||||
if (self.window) {
|
||||
const auto &concreteProps = static_cast<const PullToRefreshViewProps &>(*_props);
|
||||
|
||||
[self updateProps:_props oldProps:PullToRefreshViewShadowNode::defaultSharedProps()];
|
||||
if (concreteProps.refreshing) {
|
||||
[self beginRefreshingProgrammatically];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,11 +218,12 @@ using namespace facebook::react;
|
||||
|
||||
// When refreshing programmatically (i.e. without pulling down), we must explicitly adjust the ScrollView content
|
||||
// offset, or else the _refreshControl won't be visible
|
||||
UIScrollView *scrollView = _scrollViewComponentView.scrollView;
|
||||
CGPoint offset = {scrollView.contentOffset.x, scrollView.contentOffset.y - _refreshControl.frame.size.height};
|
||||
[scrollView setContentOffset:offset];
|
||||
|
||||
[_refreshControl beginRefreshing];
|
||||
if (!_refreshControl.isRefreshing) {
|
||||
UIScrollView *scrollView = _scrollViewComponentView.scrollView;
|
||||
CGPoint offset = {scrollView.contentOffset.x, scrollView.contentOffset.y - _refreshControl.frame.size.height};
|
||||
[scrollView setContentOffset:offset];
|
||||
[_refreshControl beginRefreshing];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Native commands
|
||||
|
||||
+48
-4
@@ -112,6 +112,11 @@ RCTSendScrollEventForNativeAnimations_DEPRECATED(UIScrollView *scrollView, NSInt
|
||||
__weak UIView *_firstVisibleView;
|
||||
|
||||
CGFloat _endDraggingSensitivityMultiplier;
|
||||
|
||||
// A flag indicating that accessibility API is used.
|
||||
// It is not restored to the default value in prepareForRecycle.
|
||||
// Once an accessibility API is used, view culling will be disabled for the entire session.
|
||||
BOOL _isAccessibilityAPIUsed;
|
||||
}
|
||||
|
||||
+ (RCTScrollViewComponentView *_Nullable)findScrollViewComponentViewForView:(UIView *)view
|
||||
@@ -134,6 +139,7 @@ RCTSendScrollEventForNativeAnimations_DEPRECATED(UIScrollView *scrollView, NSInt
|
||||
_isUserTriggeredScrolling = NO;
|
||||
_shouldUpdateContentInsetAdjustmentBehavior = YES;
|
||||
_automaticallyAdjustKeyboardInsets = NO;
|
||||
_isAccessibilityAPIUsed = NO;
|
||||
[self addSubview:_scrollView];
|
||||
|
||||
_containerView = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
@@ -593,6 +599,38 @@ static inline UIViewAnimationOptions animationOptionsWithCurve(UIViewAnimationCu
|
||||
return metrics;
|
||||
}
|
||||
|
||||
/**
|
||||
* When use of accessibility APIs is detected, view culling is disabled to make accessibility work correctly.
|
||||
*/
|
||||
- (void)_disableViewCullingIfNecessary
|
||||
{
|
||||
if (!_isAccessibilityAPIUsed) {
|
||||
_isAccessibilityAPIUsed = YES;
|
||||
[self _updateStateWithContentOffset];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSInteger)accessibilityElementCount
|
||||
{
|
||||
// From empirical testing, method `accessibilityElementCount` is called lazily only
|
||||
// when accessibility is used.
|
||||
// Why we don't use UIAccessibilitySwitchControlStatusDidChangeNotification and
|
||||
// UIAccessibilityVoiceOverStatusDidChangeNotification? The notifications are not called when using Accessibility
|
||||
// Inspector. We anticipate developers will want to debug accessbility with Accessibility Inspector and don't want to
|
||||
// break that developer workflow with view culling. Therefore, we are using API use detection to disable view culling
|
||||
// instead of the notifications.
|
||||
[self _disableViewCullingIfNecessary];
|
||||
return [super accessibilityElementCount];
|
||||
}
|
||||
|
||||
- (NSArray<id<UIFocusItem>> *)focusItemsInRect:(CGRect)rect
|
||||
{
|
||||
// From empirical testing, method `focusItemsInRect:` is called lazily only
|
||||
// when keyboard navigation is used.
|
||||
[self _disableViewCullingIfNecessary];
|
||||
return [super focusItemsInRect:rect];
|
||||
}
|
||||
|
||||
- (void)_updateStateWithContentOffset
|
||||
{
|
||||
if (!_state) {
|
||||
@@ -600,17 +638,23 @@ static inline UIViewAnimationOptions animationOptionsWithCurve(UIViewAnimationCu
|
||||
}
|
||||
|
||||
auto contentOffset = RCTPointFromCGPoint(_scrollView.contentOffset);
|
||||
BOOL isAccessibilityAPIUsed = _isAccessibilityAPIUsed;
|
||||
_state->updateState(
|
||||
[contentOffset](
|
||||
[contentOffset, isAccessibilityAPIUsed](
|
||||
const ScrollViewShadowNode::ConcreteState::Data &oldData) -> ScrollViewShadowNode::ConcreteState::SharedData {
|
||||
if (oldData.contentOffset == contentOffset) {
|
||||
// avoid doing a state update if content offset didn't change.
|
||||
if (oldData.contentOffset == contentOffset && oldData.disableViewCulling == isAccessibilityAPIUsed) {
|
||||
// avoid doing a state update if content offset and use of accessibility didn't change.
|
||||
return nullptr;
|
||||
}
|
||||
auto newData = oldData;
|
||||
newData.contentOffset = contentOffset;
|
||||
newData.disableViewCulling =
|
||||
UIAccessibilityIsVoiceOverRunning() || UIAccessibilityIsSwitchControlRunning() || isAccessibilityAPIUsed;
|
||||
return std::make_shared<const ScrollViewShadowNode::ConcreteState::Data>(newData);
|
||||
});
|
||||
},
|
||||
ReactNativeFeatureFlags::enableImmediateUpdateModeForContentOffsetChanges()
|
||||
? EventQueue::UpdateMode::unstable_Immediate
|
||||
: EventQueue::UpdateMode::Asynchronous);
|
||||
}
|
||||
|
||||
- (void)prepareForRecycle
|
||||
|
||||
-5
@@ -9,7 +9,6 @@
|
||||
#import "RCTParagraphComponentAccessibilityProvider.h"
|
||||
|
||||
#import <MobileCoreServices/UTCoreTypes.h>
|
||||
#import <React/RCTViewAccessibilityElement.h>
|
||||
#import <react/renderer/components/text/ParagraphComponentDescriptor.h>
|
||||
#import <react/renderer/components/text/ParagraphProps.h>
|
||||
#import <react/renderer/components/text/ParagraphState.h>
|
||||
@@ -227,10 +226,6 @@ using namespace facebook::react;
|
||||
for (NSObject *element in elements) {
|
||||
if ([element isKindOfClass:[UIView class]] && [cooptingCandidates containsObject:((UIView *)element)]) {
|
||||
return YES;
|
||||
} else if (
|
||||
[element isKindOfClass:[RCTViewAccessibilityElement class]] &&
|
||||
[cooptingCandidates containsObject:((RCTViewAccessibilityElement *)element).view]) {
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-28
@@ -1,28 +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 "RCTViewComponentView.h"
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/*
|
||||
* A UIAcccessibilityElement representing a RCTViewComponentView from an
|
||||
* accessibility standpoint. This enables RCTViewComponentView's to reference
|
||||
* themselves in `accessibilityElements` without actually being an accessibility
|
||||
* element. If it were, then iOS would not call into `accessibilityElements`.
|
||||
*/
|
||||
@interface RCTViewAccessibilityElement : UIAccessibilityElement
|
||||
|
||||
@property (readonly) RCTViewComponentView *view;
|
||||
|
||||
- (instancetype)initWithView:(RCTViewComponentView *)view;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
-83
@@ -1,83 +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 "RCTViewAccessibilityElement.h"
|
||||
|
||||
@implementation RCTViewAccessibilityElement
|
||||
|
||||
- (instancetype)initWithView:(RCTViewComponentView *)view
|
||||
{
|
||||
if (self = [super initWithAccessibilityContainer:view]) {
|
||||
_view = view;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (CGRect)accessibilityFrame
|
||||
{
|
||||
return UIAccessibilityConvertFrameToScreenCoordinates(_view.bounds, _view);
|
||||
}
|
||||
|
||||
#pragma mark - Forwarding to _view
|
||||
|
||||
- (NSString *)accessibilityLabel
|
||||
{
|
||||
return _view.accessibilityLabel;
|
||||
}
|
||||
|
||||
- (NSString *)accessibilityValue
|
||||
{
|
||||
return _view.accessibilityValue;
|
||||
}
|
||||
|
||||
- (UIAccessibilityTraits)accessibilityTraits
|
||||
{
|
||||
return _view.accessibilityTraits;
|
||||
}
|
||||
|
||||
- (NSString *)accessibilityHint
|
||||
{
|
||||
return _view.accessibilityHint;
|
||||
}
|
||||
|
||||
- (BOOL)accessibilityIgnoresInvertColors
|
||||
{
|
||||
return _view.accessibilityIgnoresInvertColors;
|
||||
}
|
||||
|
||||
- (BOOL)shouldGroupAccessibilityChildren
|
||||
{
|
||||
return _view.shouldGroupAccessibilityChildren;
|
||||
}
|
||||
|
||||
- (NSArray<UIAccessibilityCustomAction *> *)accessibilityCustomActions
|
||||
{
|
||||
return _view.accessibilityCustomActions;
|
||||
}
|
||||
|
||||
- (NSString *)accessibilityLanguage
|
||||
{
|
||||
return _view.accessibilityLanguage;
|
||||
}
|
||||
|
||||
- (BOOL)accessibilityViewIsModal
|
||||
{
|
||||
return _view.accessibilityViewIsModal;
|
||||
}
|
||||
|
||||
- (BOOL)accessibilityElementsHidden
|
||||
{
|
||||
return _view.accessibilityElementsHidden;
|
||||
}
|
||||
|
||||
- (BOOL)accessibilityRespondsToUserInteraction
|
||||
{
|
||||
return _view.accessibilityRespondsToUserInteraction;
|
||||
}
|
||||
|
||||
@end
|
||||
+22
-35
@@ -6,7 +6,6 @@
|
||||
*/
|
||||
|
||||
#import "RCTViewComponentView.h"
|
||||
#import "RCTViewAccessibilityElement.h"
|
||||
|
||||
#import <CoreGraphics/CoreGraphics.h>
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
@@ -51,8 +50,6 @@ const CGFloat BACKGROUND_COLOR_ZPOSITION = -1024.0f;
|
||||
UIView *_containerView;
|
||||
BOOL _useCustomContainerView;
|
||||
NSMutableSet<NSString *> *_accessibilityOrderNativeIDs;
|
||||
NSMutableArray<NSObject *> *_accessibilityElements;
|
||||
RCTViewAccessibilityElement *_axElementDescribingSelf;
|
||||
}
|
||||
|
||||
#ifdef RCT_DYNAMIC_FRAMEWORKS
|
||||
@@ -405,7 +402,11 @@ const CGFloat BACKGROUND_COLOR_ZPOSITION = -1024.0f;
|
||||
[_accessibilityOrderNativeIDs addObject:RCTNSStringFromString(childId)];
|
||||
}
|
||||
|
||||
_accessibilityElements = [NSMutableArray new];
|
||||
// If we are prop updating and have children we can go ahead and assign this prop.
|
||||
// Otherwise, we might not have children attached yet and need to wait before then.
|
||||
if (self.currentContainerView.subviews.count > 0) {
|
||||
[self updateAccessibilityElements];
|
||||
}
|
||||
}
|
||||
|
||||
// `accessibilityTraits`
|
||||
@@ -617,7 +618,6 @@ const CGFloat BACKGROUND_COLOR_ZPOSITION = -1024.0f;
|
||||
_isJSResponder = NO;
|
||||
_removeClippedSubviews = NO;
|
||||
_reactSubviews = [NSMutableArray new];
|
||||
_accessibilityElements = [NSMutableArray new];
|
||||
}
|
||||
|
||||
- (void)setPropKeysManagedByAnimated_DO_NOT_USE_THIS_IS_BROKEN:(NSSet<NSString *> *_Nullable)props
|
||||
@@ -1149,43 +1149,37 @@ static RCTBorderStyle RCTBorderStyleFromOutlineStyle(OutlineStyle outlineStyle)
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSArray<NSObject *> *)accessibilityElements
|
||||
- (void)didMoveToSuperview
|
||||
{
|
||||
if ([_accessibilityOrderNativeIDs count] <= 0) {
|
||||
return super.accessibilityElements;
|
||||
// At this point we are guaranteed to have subviews, if we are going to have them
|
||||
if (ReactNativeFeatureFlags::enableAccessibilityOrder()) {
|
||||
[self updateAccessibilityElements];
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Currently this ignores changes to descendant nativeID's. While that should rarely, if ever happen, it's an
|
||||
// edge case we should address. Currently this fixes some app deaths so landing this without addressing that edge case
|
||||
// for now.
|
||||
if ([_accessibilityElements count] > 0) {
|
||||
return _accessibilityElements;
|
||||
- (void)updateAccessibilityElements
|
||||
{
|
||||
if ([_accessibilityOrderNativeIDs count] == 0) {
|
||||
self.accessibilityElements = nil;
|
||||
return;
|
||||
}
|
||||
|
||||
NSMutableDictionary<NSString *, UIView *> *nativeIdToView = [NSMutableDictionary new];
|
||||
|
||||
[RCTViewComponentView collectAccessibilityElements:self
|
||||
intoDictionary:nativeIdToView
|
||||
nativeIds:_accessibilityOrderNativeIDs];
|
||||
|
||||
for (auto childId : _props->accessibilityOrder) {
|
||||
NSMutableArray *accessibilityElements = [NSMutableArray new];
|
||||
for (const auto &childId : _props->accessibilityOrder) {
|
||||
NSString *nsStringChildId = RCTNSStringFromString(childId);
|
||||
// Special case to allow for self-referencing with accessibilityOrder
|
||||
if ([nsStringChildId isEqualToString:self.nativeId]) {
|
||||
if (!_axElementDescribingSelf) {
|
||||
_axElementDescribingSelf = [[RCTViewAccessibilityElement alloc] initWithView:self];
|
||||
}
|
||||
_axElementDescribingSelf.isAccessibilityElement = [super isAccessibilityElement];
|
||||
[_accessibilityElements addObject:_axElementDescribingSelf];
|
||||
} else {
|
||||
UIView *viewWithMatchingNativeId = [nativeIdToView objectForKey:nsStringChildId];
|
||||
if (viewWithMatchingNativeId) {
|
||||
[_accessibilityElements addObject:viewWithMatchingNativeId];
|
||||
}
|
||||
|
||||
UIView *viewWithMatchingNativeId = [nativeIdToView objectForKey:nsStringChildId];
|
||||
if (viewWithMatchingNativeId != nil) {
|
||||
[accessibilityElements addObject:viewWithMatchingNativeId];
|
||||
}
|
||||
}
|
||||
|
||||
return _accessibilityElements;
|
||||
self.accessibilityElements = accessibilityElements;
|
||||
}
|
||||
|
||||
+ (void)collectAccessibilityElements:(UIView *)view
|
||||
@@ -1252,13 +1246,6 @@ static NSString *RCTRecursiveAccessibilityLabel(UIView *view)
|
||||
return self.contentView.isAccessibilityElement;
|
||||
}
|
||||
|
||||
// If we reference ourselves in accessibilityOrder then we will make a
|
||||
// UIAccessibilityElement object to represent ourselves since returning YES
|
||||
// here would mean iOS would not call into accessibilityElements
|
||||
if ([_accessibilityOrderNativeIDs containsObject:self.nativeId]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
return [super isAccessibilityElement];
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ plugins {
|
||||
alias(libs.plugins.android.library)
|
||||
alias(libs.plugins.download)
|
||||
alias(libs.plugins.kotlin.android)
|
||||
alias(libs.plugins.ktfmt)
|
||||
}
|
||||
|
||||
version = project.findProperty("VERSION_NAME")?.toString()!!
|
||||
@@ -620,6 +621,7 @@ dependencies {
|
||||
api(libs.androidx.autofill)
|
||||
api(libs.androidx.swiperefreshlayout)
|
||||
api(libs.androidx.tracing)
|
||||
api(libs.androidx.window)
|
||||
|
||||
api(libs.fbjni)
|
||||
api(libs.fresco)
|
||||
|
||||
+1
@@ -117,6 +117,7 @@ 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();
|
||||
}
|
||||
|
||||
+4
-1
@@ -83,6 +83,9 @@ 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_MENU to "menu",
|
||||
KeyEvent.KEYCODE_CHANNEL_UP to "channelUp",
|
||||
KeyEvent.KEYCODE_CHANNEL_DOWN to "channelDown",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -865,7 +865,7 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
|
||||
private int mDeviceRotation = 0;
|
||||
|
||||
/* package */ CustomGlobalLayoutListener() {
|
||||
DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(getContext().getApplicationContext());
|
||||
DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(getContext());
|
||||
mVisibleViewArea = new Rect();
|
||||
mMinKeyboardHeightDetected = (int) PixelUtil.toPixelFromDIP(60);
|
||||
}
|
||||
@@ -988,7 +988,7 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
|
||||
return;
|
||||
}
|
||||
mDeviceRotation = rotation;
|
||||
DisplayMetricsHolder.initDisplayMetrics(getContext().getApplicationContext());
|
||||
DisplayMetricsHolder.initDisplayMetrics(getContext());
|
||||
emitOrientationChanged(rotation);
|
||||
}
|
||||
|
||||
|
||||
-10
@@ -7,21 +7,11 @@
|
||||
|
||||
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
|
||||
*
|
||||
|
||||
+9
-1
@@ -8,6 +8,7 @@
|
||||
package com.facebook.react.bridge
|
||||
|
||||
import com.facebook.proguard.annotations.DoNotStrip
|
||||
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags
|
||||
import java.util.ArrayList
|
||||
import java.util.Arrays
|
||||
import kotlin.jvm.JvmStatic
|
||||
@@ -65,9 +66,16 @@ public open class ReadableNativeArray protected constructor() : NativeArray(), R
|
||||
if (other !is ReadableNativeArray) {
|
||||
return false
|
||||
}
|
||||
return localArray.contentDeepEquals(other.localArray)
|
||||
|
||||
return if (ReactNativeFeatureFlags.useNativeEqualsInNativeReadableArrayAndroid()) {
|
||||
nativeEquals(other)
|
||||
} else {
|
||||
localArray.contentDeepEquals(other.localArray)
|
||||
}
|
||||
}
|
||||
|
||||
private external fun nativeEquals(other: ReadableNativeArray): Boolean
|
||||
|
||||
override fun toArrayList(): ArrayList<Any?> {
|
||||
val arrayList = ArrayList<Any?>()
|
||||
repeat(size()) { i ->
|
||||
|
||||
+49
-19
@@ -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<<48a25f3bf3e45c8864f84a8cccca473d>>
|
||||
* @generated SignedSource<<a90efac589511beb130c499e51150de8>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -48,18 +48,18 @@ 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
|
||||
*/
|
||||
@JvmStatic
|
||||
public fun disableMountItemReorderingAndroid(): Boolean = accessor.disableMountItemReorderingAndroid()
|
||||
|
||||
/**
|
||||
* Disable some workarounds for old Android versions in TextLayoutManager logic for retrieving attachment metrics
|
||||
*/
|
||||
@JvmStatic
|
||||
public fun disableOldAndroidAttachmentMetricsWorkarounds(): Boolean = accessor.disableOldAndroidAttachmentMetricsWorkarounds()
|
||||
|
||||
/**
|
||||
* Turns off the global measurement cache used by TextLayoutManager on Android.
|
||||
*/
|
||||
@@ -114,6 +114,12 @@ 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.
|
||||
*/
|
||||
@@ -156,6 +162,12 @@ public object ReactNativeFeatureFlags {
|
||||
@JvmStatic
|
||||
public fun enableIOSViewClipToPaddingBox(): Boolean = accessor.enableIOSViewClipToPaddingBox()
|
||||
|
||||
/**
|
||||
* Dispatches state updates for content offset changes synchronously on the main thread.
|
||||
*/
|
||||
@JvmStatic
|
||||
public fun enableImmediateUpdateModeForContentOffsetChanges(): Boolean = accessor.enableImmediateUpdateModeForContentOffsetChanges()
|
||||
|
||||
/**
|
||||
* This is to fix the issue with interop view manager where component descriptor lookup is causing ViewManager to preload.
|
||||
*/
|
||||
@@ -180,12 +192,6 @@ 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
|
||||
*/
|
||||
@@ -228,12 +234,6 @@ public object ReactNativeFeatureFlags {
|
||||
@JvmStatic
|
||||
public fun enableResourceTimingAPI(): Boolean = accessor.enableResourceTimingAPI()
|
||||
|
||||
/**
|
||||
* Dispatches state updates synchronously in Fabric (e.g.: updates the scroll position in the shadow tree synchronously from the main thread).
|
||||
*/
|
||||
@JvmStatic
|
||||
public fun enableSynchronousStateUpdates(): Boolean = accessor.enableSynchronousStateUpdates()
|
||||
|
||||
/**
|
||||
* Enables View Culling: as soon as a view goes off screen, it can be reused anywhere in the UI and pieced together with other items to create new UI elements.
|
||||
*/
|
||||
@@ -306,6 +306,24 @@ public object ReactNativeFeatureFlags {
|
||||
@JvmStatic
|
||||
public fun preparedTextCacheSize(): Double = accessor.preparedTextCacheSize()
|
||||
|
||||
/**
|
||||
* Enables a new mechanism in ShadowTree to prevent problems caused by multiple threads trying to commit concurrently. If a thread tries to commit a few times unsuccessfully, it will acquire a lock and try again.
|
||||
*/
|
||||
@JvmStatic
|
||||
public fun preventShadowTreeCommitExhaustionWithLocking(): Boolean = accessor.preventShadowTreeCommitExhaustionWithLocking()
|
||||
|
||||
/**
|
||||
* Releases the cached image data when it is consumed by the observers.
|
||||
*/
|
||||
@JvmStatic
|
||||
public fun releaseImageDataWhenConsumed(): Boolean = accessor.releaseImageDataWhenConsumed()
|
||||
|
||||
/**
|
||||
* Skip activity identity assertion in ReactHostImpl::onHostPause()
|
||||
*/
|
||||
@JvmStatic
|
||||
public fun skipActivityIdentityAssertionOnHostPause(): Boolean = accessor.skipActivityIdentityAssertionOnHostPause()
|
||||
|
||||
/**
|
||||
* Enables storing js caller stack when creating promise in native module. This is useful in case of Promise rejection and tracing the cause.
|
||||
*/
|
||||
@@ -330,6 +348,18 @@ public object ReactNativeFeatureFlags {
|
||||
@JvmStatic
|
||||
public fun useFabricInterop(): Boolean = accessor.useFabricInterop()
|
||||
|
||||
/**
|
||||
* Use a native implementation of equals in NativeReadableArray.
|
||||
*/
|
||||
@JvmStatic
|
||||
public fun useNativeEqualsInNativeReadableArrayAndroid(): Boolean = accessor.useNativeEqualsInNativeReadableArrayAndroid()
|
||||
|
||||
/**
|
||||
* Use a native implementation of TransformHelper
|
||||
*/
|
||||
@JvmStatic
|
||||
public fun useNativeTransformHelperAndroid(): Boolean = accessor.useNativeTransformHelperAndroid()
|
||||
|
||||
/**
|
||||
* When enabled, the native view configs are used in bridgeless mode.
|
||||
*/
|
||||
|
||||
+81
-31
@@ -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<<a2faaafc4bf1b41b69ea4341a16eeb76>>
|
||||
* @generated SignedSource<<b32f66fb09971e786dd1380bbf417720>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -23,8 +23,8 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
|
||||
private var commonTestFlagCache: Boolean? = null
|
||||
private var cxxNativeAnimatedEnabledCache: Boolean? = null
|
||||
private var cxxNativeAnimatedRemoveJsSyncCache: Boolean? = null
|
||||
private var disableMainQueueSyncDispatchIOSCache: Boolean? = null
|
||||
private var disableMountItemReorderingAndroidCache: Boolean? = null
|
||||
private var disableOldAndroidAttachmentMetricsWorkaroundsCache: Boolean? = null
|
||||
private var disableTextLayoutManagerCacheAndroidCache: Boolean? = null
|
||||
private var enableAccessibilityOrderCache: Boolean? = null
|
||||
private var enableAccumulatedUpdatesInRawPropsAndroidCache: Boolean? = null
|
||||
@@ -34,6 +34,7 @@ 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
|
||||
@@ -41,11 +42,11 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
|
||||
private var enableFontScaleChangesUpdatingLayoutCache: Boolean? = null
|
||||
private var enableIOSTextBaselineOffsetPerLineCache: Boolean? = null
|
||||
private var enableIOSViewClipToPaddingBoxCache: Boolean? = null
|
||||
private var enableImmediateUpdateModeForContentOffsetChangesCache: Boolean? = null
|
||||
private var enableInteropViewManagerClassLookUpOptimizationIOSCache: Boolean? = null
|
||||
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
|
||||
@@ -53,7 +54,6 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
|
||||
private var enablePreparedTextLayoutCache: Boolean? = null
|
||||
private var enablePropsUpdateReconciliationAndroidCache: Boolean? = null
|
||||
private var enableResourceTimingAPICache: Boolean? = null
|
||||
private var enableSynchronousStateUpdatesCache: Boolean? = null
|
||||
private var enableViewCullingCache: Boolean? = null
|
||||
private var enableViewRecyclingCache: Boolean? = null
|
||||
private var enableViewRecyclingForTextCache: Boolean? = null
|
||||
@@ -66,10 +66,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
|
||||
private var fuseboxNetworkInspectionEnabledCache: Boolean? = null
|
||||
private var hideOffscreenVirtualViewsOnIOSCache: Boolean? = null
|
||||
private var preparedTextCacheSizeCache: Double? = null
|
||||
private var preventShadowTreeCommitExhaustionWithLockingCache: Boolean? = null
|
||||
private var releaseImageDataWhenConsumedCache: Boolean? = null
|
||||
private var skipActivityIdentityAssertionOnHostPauseCache: Boolean? = null
|
||||
private var traceTurboModulePromiseRejectionsOnAndroidCache: Boolean? = null
|
||||
private var updateRuntimeShadowNodeReferencesOnCommitCache: Boolean? = null
|
||||
private var useAlwaysAvailableJSErrorHandlingCache: Boolean? = null
|
||||
private var useFabricInteropCache: Boolean? = null
|
||||
private var useNativeEqualsInNativeReadableArrayAndroidCache: Boolean? = null
|
||||
private var useNativeTransformHelperAndroidCache: Boolean? = null
|
||||
private var useNativeViewConfigsInBridgelessModeCache: Boolean? = null
|
||||
private var useOptimizedEventBatchingOnAndroidCache: Boolean? = null
|
||||
private var useRawPropsJsiValueCache: Boolean? = null
|
||||
@@ -105,15 +110,6 @@ 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) {
|
||||
@@ -123,6 +119,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun disableOldAndroidAttachmentMetricsWorkarounds(): Boolean {
|
||||
var cached = disableOldAndroidAttachmentMetricsWorkaroundsCache
|
||||
if (cached == null) {
|
||||
cached = ReactNativeFeatureFlagsCxxInterop.disableOldAndroidAttachmentMetricsWorkarounds()
|
||||
disableOldAndroidAttachmentMetricsWorkaroundsCache = cached
|
||||
}
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun disableTextLayoutManagerCacheAndroid(): Boolean {
|
||||
var cached = disableTextLayoutManagerCacheAndroidCache
|
||||
if (cached == null) {
|
||||
@@ -204,6 +209,15 @@ 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) {
|
||||
@@ -267,6 +281,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun enableImmediateUpdateModeForContentOffsetChanges(): Boolean {
|
||||
var cached = enableImmediateUpdateModeForContentOffsetChangesCache
|
||||
if (cached == null) {
|
||||
cached = ReactNativeFeatureFlagsCxxInterop.enableImmediateUpdateModeForContentOffsetChanges()
|
||||
enableImmediateUpdateModeForContentOffsetChangesCache = cached
|
||||
}
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun enableInteropViewManagerClassLookUpOptimizationIOS(): Boolean {
|
||||
var cached = enableInteropViewManagerClassLookUpOptimizationIOSCache
|
||||
if (cached == null) {
|
||||
@@ -303,15 +326,6 @@ 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) {
|
||||
@@ -375,15 +389,6 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun enableSynchronousStateUpdates(): Boolean {
|
||||
var cached = enableSynchronousStateUpdatesCache
|
||||
if (cached == null) {
|
||||
cached = ReactNativeFeatureFlagsCxxInterop.enableSynchronousStateUpdates()
|
||||
enableSynchronousStateUpdatesCache = cached
|
||||
}
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun enableViewCulling(): Boolean {
|
||||
var cached = enableViewCullingCache
|
||||
if (cached == null) {
|
||||
@@ -492,6 +497,33 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun preventShadowTreeCommitExhaustionWithLocking(): Boolean {
|
||||
var cached = preventShadowTreeCommitExhaustionWithLockingCache
|
||||
if (cached == null) {
|
||||
cached = ReactNativeFeatureFlagsCxxInterop.preventShadowTreeCommitExhaustionWithLocking()
|
||||
preventShadowTreeCommitExhaustionWithLockingCache = cached
|
||||
}
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun releaseImageDataWhenConsumed(): Boolean {
|
||||
var cached = releaseImageDataWhenConsumedCache
|
||||
if (cached == null) {
|
||||
cached = ReactNativeFeatureFlagsCxxInterop.releaseImageDataWhenConsumed()
|
||||
releaseImageDataWhenConsumedCache = cached
|
||||
}
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun skipActivityIdentityAssertionOnHostPause(): Boolean {
|
||||
var cached = skipActivityIdentityAssertionOnHostPauseCache
|
||||
if (cached == null) {
|
||||
cached = ReactNativeFeatureFlagsCxxInterop.skipActivityIdentityAssertionOnHostPause()
|
||||
skipActivityIdentityAssertionOnHostPauseCache = cached
|
||||
}
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun traceTurboModulePromiseRejectionsOnAndroid(): Boolean {
|
||||
var cached = traceTurboModulePromiseRejectionsOnAndroidCache
|
||||
if (cached == null) {
|
||||
@@ -528,6 +560,24 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun useNativeEqualsInNativeReadableArrayAndroid(): Boolean {
|
||||
var cached = useNativeEqualsInNativeReadableArrayAndroidCache
|
||||
if (cached == null) {
|
||||
cached = ReactNativeFeatureFlagsCxxInterop.useNativeEqualsInNativeReadableArrayAndroid()
|
||||
useNativeEqualsInNativeReadableArrayAndroidCache = cached
|
||||
}
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun useNativeTransformHelperAndroid(): Boolean {
|
||||
var cached = useNativeTransformHelperAndroidCache
|
||||
if (cached == null) {
|
||||
cached = ReactNativeFeatureFlagsCxxInterop.useNativeTransformHelperAndroid()
|
||||
useNativeTransformHelperAndroidCache = cached
|
||||
}
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun useNativeViewConfigsInBridgelessMode(): Boolean {
|
||||
var cached = useNativeViewConfigsInBridgelessModeCache
|
||||
if (cached == null) {
|
||||
|
||||
+17
-7
@@ -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<<e72a46d573dedebd70f763843eb459fa>>
|
||||
* @generated SignedSource<<d1da48f826bc6a1793d1630cb89cb5c1>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -34,10 +34,10 @@ public object ReactNativeFeatureFlagsCxxInterop {
|
||||
|
||||
@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 disableOldAndroidAttachmentMetricsWorkarounds(): Boolean
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun disableTextLayoutManagerCacheAndroid(): Boolean
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun enableAccessibilityOrder(): Boolean
|
||||
@@ -56,6 +56,8 @@ 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
|
||||
@@ -70,6 +72,8 @@ public object ReactNativeFeatureFlagsCxxInterop {
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun enableIOSViewClipToPaddingBox(): Boolean
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun enableImmediateUpdateModeForContentOffsetChanges(): Boolean
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun enableInteropViewManagerClassLookUpOptimizationIOS(): Boolean
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun enableLayoutAnimationsOnAndroid(): Boolean
|
||||
@@ -78,8 +82,6 @@ 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
|
||||
@@ -94,8 +96,6 @@ public object ReactNativeFeatureFlagsCxxInterop {
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun enableResourceTimingAPI(): Boolean
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun enableSynchronousStateUpdates(): Boolean
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun enableViewCulling(): Boolean
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun enableViewRecycling(): Boolean
|
||||
@@ -120,6 +120,12 @@ public object ReactNativeFeatureFlagsCxxInterop {
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun preparedTextCacheSize(): Double
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun preventShadowTreeCommitExhaustionWithLocking(): Boolean
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun releaseImageDataWhenConsumed(): Boolean
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun skipActivityIdentityAssertionOnHostPause(): Boolean
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun traceTurboModulePromiseRejectionsOnAndroid(): Boolean
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun updateRuntimeShadowNodeReferencesOnCommit(): Boolean
|
||||
@@ -128,6 +134,10 @@ public object ReactNativeFeatureFlagsCxxInterop {
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun useFabricInterop(): Boolean
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun useNativeEqualsInNativeReadableArrayAndroid(): Boolean
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun useNativeTransformHelperAndroid(): Boolean
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun useNativeViewConfigsInBridgelessMode(): Boolean
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun useOptimizedEventBatchingOnAndroid(): Boolean
|
||||
|
||||
+17
-7
@@ -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<<c7dc0406f2a4e8b4bedde09e8dec5b07>>
|
||||
* @generated SignedSource<<99019349a8f3642c42e6dac5f1476e7f>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -29,10 +29,10 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
|
||||
|
||||
override fun cxxNativeAnimatedRemoveJsSync(): Boolean = false
|
||||
|
||||
override fun disableMainQueueSyncDispatchIOS(): Boolean = false
|
||||
|
||||
override fun disableMountItemReorderingAndroid(): Boolean = false
|
||||
|
||||
override fun disableOldAndroidAttachmentMetricsWorkarounds(): Boolean = true
|
||||
|
||||
override fun disableTextLayoutManagerCacheAndroid(): Boolean = false
|
||||
|
||||
override fun enableAccessibilityOrder(): Boolean = false
|
||||
@@ -51,6 +51,8 @@ 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
|
||||
@@ -65,6 +67,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
|
||||
|
||||
override fun enableIOSViewClipToPaddingBox(): Boolean = false
|
||||
|
||||
override fun enableImmediateUpdateModeForContentOffsetChanges(): Boolean = false
|
||||
|
||||
override fun enableInteropViewManagerClassLookUpOptimizationIOS(): Boolean = false
|
||||
|
||||
override fun enableLayoutAnimationsOnAndroid(): Boolean = false
|
||||
@@ -73,8 +77,6 @@ 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
|
||||
@@ -89,8 +91,6 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
|
||||
|
||||
override fun enableResourceTimingAPI(): Boolean = false
|
||||
|
||||
override fun enableSynchronousStateUpdates(): Boolean = false
|
||||
|
||||
override fun enableViewCulling(): Boolean = false
|
||||
|
||||
override fun enableViewRecycling(): Boolean = false
|
||||
@@ -115,6 +115,12 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
|
||||
|
||||
override fun preparedTextCacheSize(): Double = 200.0
|
||||
|
||||
override fun preventShadowTreeCommitExhaustionWithLocking(): Boolean = false
|
||||
|
||||
override fun releaseImageDataWhenConsumed(): Boolean = false
|
||||
|
||||
override fun skipActivityIdentityAssertionOnHostPause(): Boolean = false
|
||||
|
||||
override fun traceTurboModulePromiseRejectionsOnAndroid(): Boolean = false
|
||||
|
||||
override fun updateRuntimeShadowNodeReferencesOnCommit(): Boolean = false
|
||||
@@ -123,6 +129,10 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
|
||||
|
||||
override fun useFabricInterop(): Boolean = true
|
||||
|
||||
override fun useNativeEqualsInNativeReadableArrayAndroid(): Boolean = false
|
||||
|
||||
override fun useNativeTransformHelperAndroid(): Boolean = false
|
||||
|
||||
override fun useNativeViewConfigsInBridgelessMode(): Boolean = false
|
||||
|
||||
override fun useOptimizedEventBatchingOnAndroid(): Boolean = false
|
||||
|
||||
+89
-34
@@ -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<<5e082a56b9e6594828e50e2dfef76ea9>>
|
||||
* @generated SignedSource<<23605f090bfbebe911caa9d3d834d3e8>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -27,8 +27,8 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
|
||||
private var commonTestFlagCache: Boolean? = null
|
||||
private var cxxNativeAnimatedEnabledCache: Boolean? = null
|
||||
private var cxxNativeAnimatedRemoveJsSyncCache: Boolean? = null
|
||||
private var disableMainQueueSyncDispatchIOSCache: Boolean? = null
|
||||
private var disableMountItemReorderingAndroidCache: Boolean? = null
|
||||
private var disableOldAndroidAttachmentMetricsWorkaroundsCache: Boolean? = null
|
||||
private var disableTextLayoutManagerCacheAndroidCache: Boolean? = null
|
||||
private var enableAccessibilityOrderCache: Boolean? = null
|
||||
private var enableAccumulatedUpdatesInRawPropsAndroidCache: Boolean? = null
|
||||
@@ -38,6 +38,7 @@ 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
|
||||
@@ -45,11 +46,11 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
|
||||
private var enableFontScaleChangesUpdatingLayoutCache: Boolean? = null
|
||||
private var enableIOSTextBaselineOffsetPerLineCache: Boolean? = null
|
||||
private var enableIOSViewClipToPaddingBoxCache: Boolean? = null
|
||||
private var enableImmediateUpdateModeForContentOffsetChangesCache: Boolean? = null
|
||||
private var enableInteropViewManagerClassLookUpOptimizationIOSCache: Boolean? = null
|
||||
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
|
||||
@@ -57,7 +58,6 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
|
||||
private var enablePreparedTextLayoutCache: Boolean? = null
|
||||
private var enablePropsUpdateReconciliationAndroidCache: Boolean? = null
|
||||
private var enableResourceTimingAPICache: Boolean? = null
|
||||
private var enableSynchronousStateUpdatesCache: Boolean? = null
|
||||
private var enableViewCullingCache: Boolean? = null
|
||||
private var enableViewRecyclingCache: Boolean? = null
|
||||
private var enableViewRecyclingForTextCache: Boolean? = null
|
||||
@@ -70,10 +70,15 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
|
||||
private var fuseboxNetworkInspectionEnabledCache: Boolean? = null
|
||||
private var hideOffscreenVirtualViewsOnIOSCache: Boolean? = null
|
||||
private var preparedTextCacheSizeCache: Double? = null
|
||||
private var preventShadowTreeCommitExhaustionWithLockingCache: Boolean? = null
|
||||
private var releaseImageDataWhenConsumedCache: Boolean? = null
|
||||
private var skipActivityIdentityAssertionOnHostPauseCache: Boolean? = null
|
||||
private var traceTurboModulePromiseRejectionsOnAndroidCache: Boolean? = null
|
||||
private var updateRuntimeShadowNodeReferencesOnCommitCache: Boolean? = null
|
||||
private var useAlwaysAvailableJSErrorHandlingCache: Boolean? = null
|
||||
private var useFabricInteropCache: Boolean? = null
|
||||
private var useNativeEqualsInNativeReadableArrayAndroidCache: Boolean? = null
|
||||
private var useNativeTransformHelperAndroidCache: Boolean? = null
|
||||
private var useNativeViewConfigsInBridgelessModeCache: Boolean? = null
|
||||
private var useOptimizedEventBatchingOnAndroidCache: Boolean? = null
|
||||
private var useRawPropsJsiValueCache: Boolean? = null
|
||||
@@ -112,16 +117,6 @@ 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) {
|
||||
@@ -132,6 +127,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun disableOldAndroidAttachmentMetricsWorkarounds(): Boolean {
|
||||
var cached = disableOldAndroidAttachmentMetricsWorkaroundsCache
|
||||
if (cached == null) {
|
||||
cached = currentProvider.disableOldAndroidAttachmentMetricsWorkarounds()
|
||||
accessedFeatureFlags.add("disableOldAndroidAttachmentMetricsWorkarounds")
|
||||
disableOldAndroidAttachmentMetricsWorkaroundsCache = cached
|
||||
}
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun disableTextLayoutManagerCacheAndroid(): Boolean {
|
||||
var cached = disableTextLayoutManagerCacheAndroidCache
|
||||
if (cached == null) {
|
||||
@@ -222,6 +227,16 @@ 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) {
|
||||
@@ -292,6 +307,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun enableImmediateUpdateModeForContentOffsetChanges(): Boolean {
|
||||
var cached = enableImmediateUpdateModeForContentOffsetChangesCache
|
||||
if (cached == null) {
|
||||
cached = currentProvider.enableImmediateUpdateModeForContentOffsetChanges()
|
||||
accessedFeatureFlags.add("enableImmediateUpdateModeForContentOffsetChanges")
|
||||
enableImmediateUpdateModeForContentOffsetChangesCache = cached
|
||||
}
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun enableInteropViewManagerClassLookUpOptimizationIOS(): Boolean {
|
||||
var cached = enableInteropViewManagerClassLookUpOptimizationIOSCache
|
||||
if (cached == null) {
|
||||
@@ -332,16 +357,6 @@ 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) {
|
||||
@@ -412,16 +427,6 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun enableSynchronousStateUpdates(): Boolean {
|
||||
var cached = enableSynchronousStateUpdatesCache
|
||||
if (cached == null) {
|
||||
cached = currentProvider.enableSynchronousStateUpdates()
|
||||
accessedFeatureFlags.add("enableSynchronousStateUpdates")
|
||||
enableSynchronousStateUpdatesCache = cached
|
||||
}
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun enableViewCulling(): Boolean {
|
||||
var cached = enableViewCullingCache
|
||||
if (cached == null) {
|
||||
@@ -542,6 +547,36 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun preventShadowTreeCommitExhaustionWithLocking(): Boolean {
|
||||
var cached = preventShadowTreeCommitExhaustionWithLockingCache
|
||||
if (cached == null) {
|
||||
cached = currentProvider.preventShadowTreeCommitExhaustionWithLocking()
|
||||
accessedFeatureFlags.add("preventShadowTreeCommitExhaustionWithLocking")
|
||||
preventShadowTreeCommitExhaustionWithLockingCache = cached
|
||||
}
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun releaseImageDataWhenConsumed(): Boolean {
|
||||
var cached = releaseImageDataWhenConsumedCache
|
||||
if (cached == null) {
|
||||
cached = currentProvider.releaseImageDataWhenConsumed()
|
||||
accessedFeatureFlags.add("releaseImageDataWhenConsumed")
|
||||
releaseImageDataWhenConsumedCache = cached
|
||||
}
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun skipActivityIdentityAssertionOnHostPause(): Boolean {
|
||||
var cached = skipActivityIdentityAssertionOnHostPauseCache
|
||||
if (cached == null) {
|
||||
cached = currentProvider.skipActivityIdentityAssertionOnHostPause()
|
||||
accessedFeatureFlags.add("skipActivityIdentityAssertionOnHostPause")
|
||||
skipActivityIdentityAssertionOnHostPauseCache = cached
|
||||
}
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun traceTurboModulePromiseRejectionsOnAndroid(): Boolean {
|
||||
var cached = traceTurboModulePromiseRejectionsOnAndroidCache
|
||||
if (cached == null) {
|
||||
@@ -582,6 +617,26 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun useNativeEqualsInNativeReadableArrayAndroid(): Boolean {
|
||||
var cached = useNativeEqualsInNativeReadableArrayAndroidCache
|
||||
if (cached == null) {
|
||||
cached = currentProvider.useNativeEqualsInNativeReadableArrayAndroid()
|
||||
accessedFeatureFlags.add("useNativeEqualsInNativeReadableArrayAndroid")
|
||||
useNativeEqualsInNativeReadableArrayAndroidCache = cached
|
||||
}
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun useNativeTransformHelperAndroid(): Boolean {
|
||||
var cached = useNativeTransformHelperAndroidCache
|
||||
if (cached == null) {
|
||||
cached = currentProvider.useNativeTransformHelperAndroid()
|
||||
accessedFeatureFlags.add("useNativeTransformHelperAndroid")
|
||||
useNativeTransformHelperAndroidCache = cached
|
||||
}
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun useNativeViewConfigsInBridgelessMode(): Boolean {
|
||||
var cached = useNativeViewConfigsInBridgelessModeCache
|
||||
if (cached == null) {
|
||||
|
||||
+17
-7
@@ -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<<d6de753a08bc272f918066ad90fda301>>
|
||||
* @generated SignedSource<<780793412b76f101be1569d7a866c435>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -29,10 +29,10 @@ public interface ReactNativeFeatureFlagsProvider {
|
||||
|
||||
@DoNotStrip public fun cxxNativeAnimatedRemoveJsSync(): Boolean
|
||||
|
||||
@DoNotStrip public fun disableMainQueueSyncDispatchIOS(): Boolean
|
||||
|
||||
@DoNotStrip public fun disableMountItemReorderingAndroid(): Boolean
|
||||
|
||||
@DoNotStrip public fun disableOldAndroidAttachmentMetricsWorkarounds(): Boolean
|
||||
|
||||
@DoNotStrip public fun disableTextLayoutManagerCacheAndroid(): Boolean
|
||||
|
||||
@DoNotStrip public fun enableAccessibilityOrder(): Boolean
|
||||
@@ -51,6 +51,8 @@ public interface ReactNativeFeatureFlagsProvider {
|
||||
|
||||
@DoNotStrip public fun enableDoubleMeasurementFixAndroid(): Boolean
|
||||
|
||||
@DoNotStrip public fun enableEagerMainQueueModulesOnIOS(): Boolean
|
||||
|
||||
@DoNotStrip public fun enableEagerRootViewAttachment(): Boolean
|
||||
|
||||
@DoNotStrip public fun enableFabricLogs(): Boolean
|
||||
@@ -65,6 +67,8 @@ public interface ReactNativeFeatureFlagsProvider {
|
||||
|
||||
@DoNotStrip public fun enableIOSViewClipToPaddingBox(): Boolean
|
||||
|
||||
@DoNotStrip public fun enableImmediateUpdateModeForContentOffsetChanges(): Boolean
|
||||
|
||||
@DoNotStrip public fun enableInteropViewManagerClassLookUpOptimizationIOS(): Boolean
|
||||
|
||||
@DoNotStrip public fun enableLayoutAnimationsOnAndroid(): Boolean
|
||||
@@ -73,8 +77,6 @@ public interface ReactNativeFeatureFlagsProvider {
|
||||
|
||||
@DoNotStrip public fun enableMainQueueCoordinatorOnIOS(): Boolean
|
||||
|
||||
@DoNotStrip public fun enableMainQueueModulesOnIOS(): Boolean
|
||||
|
||||
@DoNotStrip public fun enableModuleArgumentNSNullConversionIOS(): Boolean
|
||||
|
||||
@DoNotStrip public fun enableNativeCSSParsing(): Boolean
|
||||
@@ -89,8 +91,6 @@ public interface ReactNativeFeatureFlagsProvider {
|
||||
|
||||
@DoNotStrip public fun enableResourceTimingAPI(): Boolean
|
||||
|
||||
@DoNotStrip public fun enableSynchronousStateUpdates(): Boolean
|
||||
|
||||
@DoNotStrip public fun enableViewCulling(): Boolean
|
||||
|
||||
@DoNotStrip public fun enableViewRecycling(): Boolean
|
||||
@@ -115,6 +115,12 @@ public interface ReactNativeFeatureFlagsProvider {
|
||||
|
||||
@DoNotStrip public fun preparedTextCacheSize(): Double
|
||||
|
||||
@DoNotStrip public fun preventShadowTreeCommitExhaustionWithLocking(): Boolean
|
||||
|
||||
@DoNotStrip public fun releaseImageDataWhenConsumed(): Boolean
|
||||
|
||||
@DoNotStrip public fun skipActivityIdentityAssertionOnHostPause(): Boolean
|
||||
|
||||
@DoNotStrip public fun traceTurboModulePromiseRejectionsOnAndroid(): Boolean
|
||||
|
||||
@DoNotStrip public fun updateRuntimeShadowNodeReferencesOnCommit(): Boolean
|
||||
@@ -123,6 +129,10 @@ public interface ReactNativeFeatureFlagsProvider {
|
||||
|
||||
@DoNotStrip public fun useFabricInterop(): Boolean
|
||||
|
||||
@DoNotStrip public fun useNativeEqualsInNativeReadableArrayAndroid(): Boolean
|
||||
|
||||
@DoNotStrip public fun useNativeTransformHelperAndroid(): Boolean
|
||||
|
||||
@DoNotStrip public fun useNativeViewConfigsInBridgelessMode(): Boolean
|
||||
|
||||
@DoNotStrip public fun useOptimizedEventBatchingOnAndroid(): Boolean
|
||||
|
||||
+3
-5
@@ -35,7 +35,6 @@ import java.util.HashMap
|
||||
import java.util.UUID
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.ResponseBody
|
||||
import okio.ByteString
|
||||
|
||||
@ReactModule(name = NativeBlobModuleSpec.NAME)
|
||||
@@ -72,7 +71,7 @@ public class BlobModule(reactContext: ReactApplicationContext) :
|
||||
return !isRemote && responseType == "blob"
|
||||
}
|
||||
|
||||
override fun fetch(uri: Uri): WritableMap {
|
||||
override fun fetch(uri: Uri): Pair<WritableMap, ByteArray> {
|
||||
val data = getBytesFromUri(uri)
|
||||
|
||||
val blob = Arguments.createMap()
|
||||
@@ -85,7 +84,7 @@ public class BlobModule(reactContext: ReactApplicationContext) :
|
||||
blob.putString("name", getNameFromUri(uri))
|
||||
blob.putDouble("lastModified", getLastModifiedFromUri(uri))
|
||||
|
||||
return blob
|
||||
return blob to data
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,8 +118,7 @@ public class BlobModule(reactContext: ReactApplicationContext) :
|
||||
return responseType == "blob"
|
||||
}
|
||||
|
||||
override fun toResponseData(body: ResponseBody): WritableMap {
|
||||
val data = body.bytes()
|
||||
override fun toResponseData(data: ByteArray): WritableMap {
|
||||
val blob = Arguments.createMap()
|
||||
blob.putString("blobId", store(data))
|
||||
blob.putInt("offset", 0)
|
||||
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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.modules.network
|
||||
|
||||
import com.facebook.proguard.annotations.DoNotStripAny
|
||||
|
||||
/**
|
||||
* [Experimental] An interface for reporting network events to the modern debugger server and Web
|
||||
* Performance APIs.
|
||||
*
|
||||
* In a production (non dev or profiling) build, CDP reporting is disabled.
|
||||
*
|
||||
* This is a helper class wrapping `facebook::react::jsinspector_modern::NetworkReporter`.
|
||||
*/
|
||||
@DoNotStripAny
|
||||
internal object InspectorNetworkReporter {
|
||||
/**
|
||||
* Report a network request that is about to be sent.
|
||||
* - Corresponds to `Network.requestWillBeSent` in CDP.
|
||||
* - Corresponds to `PerformanceResourceTiming.requestStart` (specifically, marking when the
|
||||
* native request was initiated).
|
||||
*/
|
||||
@JvmStatic
|
||||
external fun reportRequestStart(
|
||||
requestId: Int,
|
||||
requestUrl: String,
|
||||
requestMethod: String,
|
||||
requestHeaders: Map<String, String>,
|
||||
requestBody: String,
|
||||
encodedDataLength: Long
|
||||
)
|
||||
|
||||
/**
|
||||
* Report detailed timing info, such as DNS lookup, when a request has started.
|
||||
* - Corresponds to `Network.requestWillBeSentExtraInfo` in CDP.
|
||||
* - Corresponds to `PerformanceResourceTiming.domainLookupStart`,
|
||||
* `PerformanceResourceTiming.connectStart`.
|
||||
*/
|
||||
@JvmStatic external fun reportConnectionTiming(requestId: Int, headers: Map<String, String>)
|
||||
|
||||
/**
|
||||
* Report when HTTP response headers have been received, corresponding to when the first byte of
|
||||
* the response is available.
|
||||
* - Corresponds to `Network.responseReceived` in CDP.
|
||||
* - Corresponds to `PerformanceResourceTiming.responseStart`.
|
||||
*/
|
||||
@JvmStatic
|
||||
external fun reportResponseStart(
|
||||
requestId: Int,
|
||||
requestUrl: String,
|
||||
responseStatus: Int,
|
||||
responseHeaders: Map<String, String>,
|
||||
expectedDataLength: Long
|
||||
)
|
||||
|
||||
/**
|
||||
* Report when additional chunks of the response body have been received.
|
||||
*
|
||||
* Corresponds to `Network.dataReceived` in CDP.
|
||||
*/
|
||||
@JvmStatic external fun reportDataReceived(requestId: Int, dataLength: Int)
|
||||
|
||||
/**
|
||||
* Report when a network request is complete and we are no longer receiving response data.
|
||||
* - Corresponds to `Network.loadingFinished` in CDP.
|
||||
* - Corresponds to `PerformanceResourceTiming.responseEnd`.
|
||||
*/
|
||||
@JvmStatic external fun reportResponseEnd(requestId: Int, encodedDataLength: Long)
|
||||
|
||||
/**
|
||||
* Store response body preview. This is an optional reporting method, and is a no-op if CDP
|
||||
* debugging is disabled.
|
||||
*/
|
||||
@JvmStatic
|
||||
external fun maybeStoreResponseBody(requestId: Int, body: String, base64Encoded: Boolean)
|
||||
|
||||
/**
|
||||
* Incrementally store a response body preview, when a string response is received in chunks.
|
||||
* Buffered contents will be flushed to `NetworkReporter` with `reportResponseEnd`.
|
||||
*
|
||||
* As with `maybeStoreResponseBody`, calling this method is optional and a no-op if CDP debugging
|
||||
* is disabled.
|
||||
*/
|
||||
@JvmStatic external fun maybeStoreResponseBodyIncremental(requestId: Int, data: String)
|
||||
}
|
||||
+250
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
@file:Suppress("DEPRECATION_ERROR") // Conflicting okhttp versions
|
||||
|
||||
package com.facebook.react.modules.network
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.Base64
|
||||
import com.facebook.react.bridge.Arguments
|
||||
import com.facebook.react.bridge.ReactApplicationContext
|
||||
import com.facebook.react.bridge.WritableMap
|
||||
import com.facebook.react.bridge.buildReadableArray
|
||||
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags
|
||||
import java.net.SocketTimeoutException
|
||||
import okhttp3.Headers
|
||||
import okhttp3.Protocol
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
|
||||
/**
|
||||
* Utility class for reporting network lifecycle events to JavaScript and InspectorNetworkReporter.
|
||||
*/
|
||||
internal object NetworkEventUtil {
|
||||
@JvmStatic
|
||||
fun onCreateRequest(requestId: Int, request: Request) {
|
||||
if (ReactNativeFeatureFlags.enableNetworkEventReporting()) {
|
||||
val headersMap = okHttpHeadersToMap(request.headers())
|
||||
InspectorNetworkReporter.reportRequestStart(
|
||||
requestId,
|
||||
request.url().toString(),
|
||||
request.method(),
|
||||
headersMap,
|
||||
request.body()?.toString().orEmpty(),
|
||||
request.body()?.contentLength() ?: 0,
|
||||
)
|
||||
InspectorNetworkReporter.reportConnectionTiming(requestId, headersMap)
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun onDataSend(
|
||||
reactContext: ReactApplicationContext?,
|
||||
requestId: Int,
|
||||
progress: Long,
|
||||
total: Long
|
||||
) {
|
||||
reactContext?.emitDeviceEvent(
|
||||
"didSendNetworkData",
|
||||
buildReadableArray {
|
||||
add(requestId)
|
||||
add(progress.toInt())
|
||||
add(total.toInt())
|
||||
})
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun onIncrementalDataReceived(
|
||||
reactContext: ReactApplicationContext?,
|
||||
requestId: Int,
|
||||
data: String?,
|
||||
progress: Long,
|
||||
total: Long
|
||||
) {
|
||||
if (ReactNativeFeatureFlags.enableNetworkEventReporting() && data != null) {
|
||||
InspectorNetworkReporter.reportDataReceived(requestId, data.encodeToByteArray().size)
|
||||
InspectorNetworkReporter.maybeStoreResponseBodyIncremental(requestId, data)
|
||||
}
|
||||
reactContext?.emitDeviceEvent(
|
||||
"didReceiveNetworkIncrementalData",
|
||||
buildReadableArray {
|
||||
add(requestId)
|
||||
add(data)
|
||||
add(progress.toInt())
|
||||
add(total.toInt())
|
||||
})
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun onDataReceivedProgress(
|
||||
reactContext: ReactApplicationContext?,
|
||||
requestId: Int,
|
||||
progress: Long,
|
||||
total: Long
|
||||
) {
|
||||
reactContext?.emitDeviceEvent(
|
||||
"didReceiveNetworkDataProgress",
|
||||
buildReadableArray {
|
||||
add(requestId)
|
||||
add(progress.toInt())
|
||||
add(total.toInt())
|
||||
})
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun onDataReceived(
|
||||
reactContext: ReactApplicationContext?,
|
||||
requestId: Int,
|
||||
data: String?,
|
||||
responseType: String
|
||||
) {
|
||||
if (ReactNativeFeatureFlags.enableNetworkEventReporting()) {
|
||||
InspectorNetworkReporter.maybeStoreResponseBody(
|
||||
requestId, data.orEmpty(), responseType == "base64")
|
||||
}
|
||||
reactContext?.emitDeviceEvent(
|
||||
"didReceiveNetworkData",
|
||||
buildReadableArray {
|
||||
add(requestId)
|
||||
add(data)
|
||||
})
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun onDataReceived(
|
||||
reactContext: ReactApplicationContext?,
|
||||
requestId: Int,
|
||||
data: WritableMap,
|
||||
rawData: ByteArray
|
||||
) {
|
||||
if (ReactNativeFeatureFlags.enableNetworkEventReporting()) {
|
||||
InspectorNetworkReporter.maybeStoreResponseBody(
|
||||
requestId, Base64.encodeToString(rawData, Base64.NO_WRAP), true)
|
||||
}
|
||||
reactContext?.emitDeviceEvent(
|
||||
"didReceiveNetworkData",
|
||||
Arguments.createArray().apply {
|
||||
pushInt(requestId)
|
||||
pushMap(data)
|
||||
})
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun onRequestError(
|
||||
reactContext: ReactApplicationContext?,
|
||||
requestId: Int,
|
||||
error: String?,
|
||||
e: Throwable?
|
||||
) {
|
||||
reactContext?.emitDeviceEvent(
|
||||
"didCompleteNetworkResponse",
|
||||
buildReadableArray {
|
||||
add(requestId)
|
||||
add(error)
|
||||
if (e?.javaClass == SocketTimeoutException::class.java) {
|
||||
add(true) // last argument is a time out boolean
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun onRequestSuccess(
|
||||
reactContext: ReactApplicationContext?,
|
||||
requestId: Int,
|
||||
encodedDataLength: Long
|
||||
) {
|
||||
if (ReactNativeFeatureFlags.enableNetworkEventReporting()) {
|
||||
InspectorNetworkReporter.reportResponseEnd(requestId, encodedDataLength)
|
||||
}
|
||||
reactContext?.emitDeviceEvent(
|
||||
"didCompleteNetworkResponse",
|
||||
buildReadableArray {
|
||||
add(requestId)
|
||||
addNull()
|
||||
})
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun onResponseReceived(
|
||||
reactContext: ReactApplicationContext?,
|
||||
requestId: Int,
|
||||
requestUrl: String?,
|
||||
response: Response,
|
||||
) {
|
||||
val headersMap = okHttpHeadersToMap(response.headers())
|
||||
val headersBundle = Bundle()
|
||||
for ((headerName, headerValue) in headersMap) {
|
||||
headersBundle.putString(headerName, headerValue)
|
||||
}
|
||||
|
||||
if (ReactNativeFeatureFlags.enableNetworkEventReporting()) {
|
||||
InspectorNetworkReporter.reportResponseStart(
|
||||
requestId,
|
||||
requestUrl.orEmpty(),
|
||||
response.code(),
|
||||
headersMap,
|
||||
response.body()?.contentLength() ?: 0,
|
||||
)
|
||||
}
|
||||
reactContext?.emitDeviceEvent(
|
||||
"didReceiveNetworkResponse",
|
||||
Arguments.createArray().apply {
|
||||
pushInt(requestId)
|
||||
pushInt(response.code())
|
||||
pushMap(Arguments.fromBundle(headersBundle))
|
||||
pushString(requestUrl)
|
||||
})
|
||||
}
|
||||
|
||||
@Deprecated("Compatibility overload")
|
||||
@JvmStatic
|
||||
fun onResponseReceived(
|
||||
reactContext: ReactApplicationContext?,
|
||||
requestId: Int,
|
||||
statusCode: Int,
|
||||
headers: WritableMap?,
|
||||
url: String?
|
||||
) {
|
||||
val headersBuilder = Headers.Builder()
|
||||
headers?.let { map ->
|
||||
val iterator = map.keySetIterator()
|
||||
while (iterator.hasNextKey()) {
|
||||
val key = iterator.nextKey()
|
||||
val value = map.getString(key)
|
||||
if (value != null) {
|
||||
headersBuilder.add(key, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
onResponseReceived(
|
||||
reactContext,
|
||||
requestId,
|
||||
url,
|
||||
Response.Builder()
|
||||
.protocol(Protocol.HTTP_1_1)
|
||||
.request(Request.Builder().url(url.orEmpty()).build())
|
||||
.headers(headersBuilder.build())
|
||||
.code(statusCode)
|
||||
.message("")
|
||||
.build())
|
||||
}
|
||||
|
||||
private fun okHttpHeadersToMap(headers: Headers): Map<String, String> {
|
||||
val responseHeaders = mutableMapOf<String, String>()
|
||||
for (i in 0 until headers.size()) {
|
||||
val headerName = headers.name(i)
|
||||
// multiple values for the same header
|
||||
if (responseHeaders.containsKey(headerName)) {
|
||||
responseHeaders[headerName] = "${responseHeaders[headerName]}, ${headers.value(i)}"
|
||||
} else {
|
||||
responseHeaders[headerName] = headers.value(i)
|
||||
}
|
||||
}
|
||||
return responseHeaders
|
||||
}
|
||||
}
|
||||
+66
-66
@@ -11,11 +11,9 @@
|
||||
package com.facebook.react.modules.network
|
||||
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.util.Base64
|
||||
import com.facebook.common.logging.FLog
|
||||
import com.facebook.fbreact.specs.NativeNetworkingAndroidSpec
|
||||
import com.facebook.react.bridge.Arguments
|
||||
import com.facebook.react.bridge.ReactApplicationContext
|
||||
import com.facebook.react.bridge.ReactMethod
|
||||
import com.facebook.react.bridge.ReadableArray
|
||||
@@ -36,6 +34,7 @@ import okhttp3.JavaNetCookieJar
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.MultipartBody
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Protocol
|
||||
import okhttp3.Request
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.Response
|
||||
@@ -61,8 +60,10 @@ public class NetworkingModule(
|
||||
/** Returns if the handler should be used for an URI. */
|
||||
public fun supports(uri: Uri, responseType: String): Boolean
|
||||
|
||||
/** Fetch the URI and return the JS body payload. */
|
||||
@Throws(IOException::class) public fun fetch(uri: Uri): WritableMap
|
||||
/**
|
||||
* Fetch the URI and return a tuple containing the JS body payload and the raw response body.
|
||||
*/
|
||||
@Throws(IOException::class) public fun fetch(uri: Uri): Pair<WritableMap, ByteArray>
|
||||
}
|
||||
|
||||
/** Allows adding custom handling to build the [RequestBody] from the JS body payload. */
|
||||
@@ -80,7 +81,7 @@ public class NetworkingModule(
|
||||
public fun supports(responseType: String): Boolean
|
||||
|
||||
/** Returns the JS body payload for the [ResponseBody]. */
|
||||
@Throws(IOException::class) public fun toResponseData(body: ResponseBody): WritableMap
|
||||
@Throws(IOException::class) public fun toResponseData(data: ByteArray): WritableMap
|
||||
}
|
||||
|
||||
private val client: OkHttpClient
|
||||
@@ -231,7 +232,7 @@ public class NetworkingModule(
|
||||
} catch (th: Throwable) {
|
||||
FLog.e(TAG, "Failed to send url request: $url", th)
|
||||
|
||||
ResponseUtil.onRequestError(
|
||||
NetworkEventUtil.onRequestError(
|
||||
getReactApplicationContextIfActiveOrWarn(), requestId, th.message, th)
|
||||
}
|
||||
}
|
||||
@@ -255,18 +256,26 @@ public class NetworkingModule(
|
||||
// Check if a handler is registered
|
||||
for (handler in uriHandlers) {
|
||||
if (handler.supports(uri, responseType)) {
|
||||
val res = handler.fetch(uri)
|
||||
val (res, rawBody) = handler.fetch(uri)
|
||||
val encodedDataLength = res.toString().toByteArray().size
|
||||
// fix: UriHandlers which are not using file:// scheme fail in whatwg-fetch at this line
|
||||
// https://github.com/JakeChampion/fetch/blob/main/fetch.js#L547
|
||||
ResponseUtil.onResponseReceived(
|
||||
reactApplicationContext, requestId, 200, Arguments.createMap(), url)
|
||||
ResponseUtil.onDataReceived(reactApplicationContext, requestId, res)
|
||||
ResponseUtil.onRequestSuccess(reactApplicationContext, requestId)
|
||||
val response =
|
||||
Response.Builder()
|
||||
.protocol(Protocol.HTTP_1_1)
|
||||
.request(Request.Builder().url(url.orEmpty()).build())
|
||||
.code(200)
|
||||
.message("OK")
|
||||
.build()
|
||||
NetworkEventUtil.onResponseReceived(reactApplicationContext, requestId, url, response)
|
||||
NetworkEventUtil.onDataReceived(reactApplicationContext, requestId, res, rawBody)
|
||||
NetworkEventUtil.onRequestSuccess(
|
||||
reactApplicationContext, requestId, encodedDataLength.toLong())
|
||||
return
|
||||
}
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
ResponseUtil.onRequestError(reactApplicationContext, requestId, e.message, e)
|
||||
NetworkEventUtil.onRequestError(reactApplicationContext, requestId, e.message, e)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -274,7 +283,7 @@ public class NetworkingModule(
|
||||
try {
|
||||
requestBuilder = Request.Builder().url(url.orEmpty())
|
||||
} catch (e: Exception) {
|
||||
ResponseUtil.onRequestError(reactApplicationContext, requestId, e.message, null)
|
||||
NetworkEventUtil.onRequestError(reactApplicationContext, requestId, e.message, e)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -313,7 +322,7 @@ public class NetworkingModule(
|
||||
// JS below, so no need to do anything here.
|
||||
return
|
||||
}
|
||||
ResponseUtil.onDataReceivedProgress(
|
||||
NetworkEventUtil.onDataReceivedProgress(
|
||||
reactApplicationContext, requestId, bytesWritten, contentLength)
|
||||
last = now
|
||||
}
|
||||
@@ -333,7 +342,7 @@ public class NetworkingModule(
|
||||
|
||||
val requestHeaders = extractHeaders(headers, data)
|
||||
if (requestHeaders == null) {
|
||||
ResponseUtil.onRequestError(
|
||||
NetworkEventUtil.onRequestError(
|
||||
reactApplicationContext, requestId, "Unrecognized headers format", null)
|
||||
return
|
||||
}
|
||||
@@ -359,7 +368,7 @@ public class NetworkingModule(
|
||||
handler != null -> requestBody = handler.toRequestBody(data, contentType)
|
||||
data.hasKey(REQUEST_BODY_KEY_STRING) -> {
|
||||
if (contentType == null) {
|
||||
ResponseUtil.onRequestError(
|
||||
NetworkEventUtil.onRequestError(
|
||||
reactApplicationContext,
|
||||
requestId,
|
||||
"Payload is set but no content-type header specified",
|
||||
@@ -374,7 +383,7 @@ public class NetworkingModule(
|
||||
requestBody = RequestBodyUtil.createGzip(contentMediaType, body)
|
||||
}
|
||||
if (requestBody == null) {
|
||||
ResponseUtil.onRequestError(
|
||||
NetworkEventUtil.onRequestError(
|
||||
reactApplicationContext, requestId, "Failed to gzip request body", null)
|
||||
return
|
||||
}
|
||||
@@ -389,7 +398,7 @@ public class NetworkingModule(
|
||||
checkNotNull(contentMediaType.charset(StandardCharsets.UTF_8))
|
||||
}
|
||||
if (body == null) {
|
||||
ResponseUtil.onRequestError(
|
||||
NetworkEventUtil.onRequestError(
|
||||
reactApplicationContext, requestId, "Received request but body was empty", null)
|
||||
return
|
||||
}
|
||||
@@ -399,7 +408,7 @@ public class NetworkingModule(
|
||||
}
|
||||
data.hasKey(REQUEST_BODY_KEY_BASE64) -> {
|
||||
if (contentType == null) {
|
||||
ResponseUtil.onRequestError(
|
||||
NetworkEventUtil.onRequestError(
|
||||
reactApplicationContext,
|
||||
requestId,
|
||||
"Payload is set but no content-type header specified",
|
||||
@@ -411,7 +420,7 @@ public class NetworkingModule(
|
||||
|
||||
val contentMediaType = MediaType.parse(contentType)
|
||||
if (contentMediaType == null) {
|
||||
ResponseUtil.onRequestError(
|
||||
NetworkEventUtil.onRequestError(
|
||||
reactApplicationContext,
|
||||
requestId,
|
||||
"Invalid content type specified: $contentType",
|
||||
@@ -420,7 +429,7 @@ public class NetworkingModule(
|
||||
}
|
||||
val base64DecodedString = ByteString.decodeBase64(base64String)
|
||||
if (base64DecodedString == null) {
|
||||
ResponseUtil.onRequestError(
|
||||
NetworkEventUtil.onRequestError(
|
||||
reactApplicationContext, requestId, "Request body base64 string was invalid", null)
|
||||
return
|
||||
}
|
||||
@@ -429,7 +438,7 @@ public class NetworkingModule(
|
||||
}
|
||||
data.hasKey(REQUEST_BODY_KEY_URI) -> {
|
||||
if (contentType == null) {
|
||||
ResponseUtil.onRequestError(
|
||||
NetworkEventUtil.onRequestError(
|
||||
reactApplicationContext,
|
||||
requestId,
|
||||
"Payload is set but no content-type header specified",
|
||||
@@ -438,13 +447,13 @@ public class NetworkingModule(
|
||||
}
|
||||
val uri = data.getString(REQUEST_BODY_KEY_URI)
|
||||
if (uri == null) {
|
||||
ResponseUtil.onRequestError(
|
||||
NetworkEventUtil.onRequestError(
|
||||
reactApplicationContext, requestId, "Request body URI field was set but null", null)
|
||||
return
|
||||
}
|
||||
val fileInputStream = RequestBodyUtil.getFileInputStream(getReactApplicationContext(), uri)
|
||||
if (fileInputStream == null) {
|
||||
ResponseUtil.onRequestError(
|
||||
NetworkEventUtil.onRequestError(
|
||||
reactApplicationContext, requestId, "Could not retrieve file for uri $uri", null)
|
||||
return
|
||||
}
|
||||
@@ -456,7 +465,7 @@ public class NetworkingModule(
|
||||
}
|
||||
val parts = data.getArray(REQUEST_BODY_KEY_FORMDATA)
|
||||
if (parts == null) {
|
||||
ResponseUtil.onRequestError(
|
||||
NetworkEventUtil.onRequestError(
|
||||
reactApplicationContext, requestId, "Received request but form data was empty", null)
|
||||
return
|
||||
}
|
||||
@@ -472,8 +481,11 @@ public class NetworkingModule(
|
||||
requestBuilder.method(method, wrapRequestBodyWithProgressEmitter(requestBody, requestId))
|
||||
|
||||
addRequest(requestId)
|
||||
val request = requestBuilder.build()
|
||||
NetworkEventUtil.onCreateRequest(requestId, request)
|
||||
|
||||
client
|
||||
.newCall(requestBuilder.build())
|
||||
.newCall(request)
|
||||
.enqueue(
|
||||
object : Callback {
|
||||
override fun onFailure(call: Call, e: IOException) {
|
||||
@@ -483,7 +495,7 @@ public class NetworkingModule(
|
||||
removeRequest(requestId)
|
||||
val errorMessage =
|
||||
e.message ?: ("Error while executing request: ${e.javaClass.simpleName}")
|
||||
ResponseUtil.onRequestError(reactApplicationContext, requestId, errorMessage, e)
|
||||
NetworkEventUtil.onRequestError(reactApplicationContext, requestId, errorMessage, e)
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
@@ -493,12 +505,8 @@ public class NetworkingModule(
|
||||
}
|
||||
removeRequest(requestId)
|
||||
// Before we touch the body send headers to JS
|
||||
ResponseUtil.onResponseReceived(
|
||||
reactApplicationContext,
|
||||
requestId,
|
||||
response.code(),
|
||||
translateHeaders(response.headers()),
|
||||
response.request().url().toString())
|
||||
NetworkEventUtil.onResponseReceived(
|
||||
reactApplicationContext, requestId, url, response)
|
||||
|
||||
try {
|
||||
// OkHttp implements something called transparent gzip, which mean that it will
|
||||
@@ -517,7 +525,7 @@ public class NetworkingModule(
|
||||
// https://github.com/square/okhttp/blob/5b37cda9e00626f43acf354df145fd452c3031f1/okhttp/src/main/java/okhttp3/internal/http/BridgeInterceptor.java#L76-L111
|
||||
var responseBody: ResponseBody? = response.body()
|
||||
if (responseBody == null) {
|
||||
ResponseUtil.onRequestError(
|
||||
NetworkEventUtil.onRequestError(
|
||||
reactApplicationContext, requestId, "Response body is null", null)
|
||||
return
|
||||
}
|
||||
@@ -537,9 +545,12 @@ public class NetworkingModule(
|
||||
// Check if a handler is registered
|
||||
for (responseHandler in responseHandlers) {
|
||||
if (responseHandler.supports(responseType)) {
|
||||
val res = responseHandler.toResponseData(responseBody)
|
||||
ResponseUtil.onDataReceived(reactApplicationContext, requestId, res)
|
||||
ResponseUtil.onRequestSuccess(reactApplicationContext, requestId)
|
||||
val responseData = responseBody.bytes()
|
||||
val res = responseHandler.toResponseData(responseData)
|
||||
NetworkEventUtil.onDataReceived(
|
||||
reactApplicationContext, requestId, res, responseData)
|
||||
NetworkEventUtil.onRequestSuccess(
|
||||
reactApplicationContext, requestId, responseBody.contentLength())
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -549,7 +560,8 @@ public class NetworkingModule(
|
||||
// periodically send response data updates to JS.
|
||||
if (useIncrementalUpdates && responseType == "text") {
|
||||
readWithProgress(requestId, responseBody)
|
||||
ResponseUtil.onRequestSuccess(reactApplicationContext, requestId)
|
||||
NetworkEventUtil.onRequestSuccess(
|
||||
reactApplicationContext, requestId, responseBody.contentLength())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -566,17 +578,19 @@ public class NetworkingModule(
|
||||
// Javascript layer.
|
||||
// Introduced to fix issue #7463.
|
||||
} else {
|
||||
ResponseUtil.onRequestError(
|
||||
NetworkEventUtil.onRequestError(
|
||||
reactApplicationContext, requestId, e.message, e)
|
||||
}
|
||||
}
|
||||
} else if (responseType == "base64") {
|
||||
responseString = Base64.encodeToString(responseBody.bytes(), Base64.NO_WRAP)
|
||||
}
|
||||
ResponseUtil.onDataReceived(reactApplicationContext, requestId, responseString)
|
||||
ResponseUtil.onRequestSuccess(reactApplicationContext, requestId)
|
||||
NetworkEventUtil.onDataReceived(
|
||||
reactApplicationContext, requestId, responseString, responseType)
|
||||
NetworkEventUtil.onRequestSuccess(
|
||||
reactApplicationContext, requestId, responseBody.contentLength())
|
||||
} catch (e: IOException) {
|
||||
ResponseUtil.onRequestError(reactApplicationContext, requestId, e.message, e)
|
||||
NetworkEventUtil.onRequestError(reactApplicationContext, requestId, e.message, e)
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -598,7 +612,7 @@ public class NetworkingModule(
|
||||
override fun onProgress(bytesWritten: Long, contentLength: Long, done: Boolean) {
|
||||
val now = System.nanoTime()
|
||||
if (done || shouldDispatch(now, last)) {
|
||||
ResponseUtil.onDataSend(
|
||||
NetworkEventUtil.onDataSend(
|
||||
reactApplicationContext, requestId, bytesWritten, contentLength)
|
||||
last = now
|
||||
}
|
||||
@@ -633,7 +647,7 @@ public class NetworkingModule(
|
||||
var read: Int
|
||||
val reactApplicationContext = getReactApplicationContextIfActiveOrWarn()
|
||||
while ((inputStream.read(buffer).also { read = it }) != -1) {
|
||||
ResponseUtil.onIncrementalDataReceived(
|
||||
NetworkEventUtil.onIncrementalDataReceived(
|
||||
reactApplicationContext,
|
||||
requestId,
|
||||
streamDecoder.decodeNext(buffer, read),
|
||||
@@ -691,7 +705,8 @@ public class NetworkingModule(
|
||||
val multipartBuilder = MultipartBody.Builder()
|
||||
val mediaType = MediaType.parse(contentType)
|
||||
if (mediaType == null) {
|
||||
ResponseUtil.onRequestError(reactApplicationContext, requestId, "Invalid media type.", null)
|
||||
NetworkEventUtil.onRequestError(
|
||||
reactApplicationContext, requestId, "Invalid media type.", null)
|
||||
return null
|
||||
}
|
||||
multipartBuilder.setType(mediaType)
|
||||
@@ -699,7 +714,7 @@ public class NetworkingModule(
|
||||
for (i in 0 until body.size()) {
|
||||
val bodyPart = body.getMap(i)
|
||||
if (bodyPart == null) {
|
||||
ResponseUtil.onRequestError(
|
||||
NetworkEventUtil.onRequestError(
|
||||
reactApplicationContext, requestId, "Unrecognized FormData part.", null)
|
||||
return null
|
||||
}
|
||||
@@ -708,7 +723,7 @@ public class NetworkingModule(
|
||||
val headersArray = bodyPart.getArray("headers")
|
||||
var headers = extractHeaders(headersArray, null)
|
||||
if (headers == null) {
|
||||
ResponseUtil.onRequestError(
|
||||
NetworkEventUtil.onRequestError(
|
||||
reactApplicationContext,
|
||||
requestId,
|
||||
"Missing or invalid header format for FormData part.",
|
||||
@@ -732,7 +747,7 @@ public class NetworkingModule(
|
||||
} else if (bodyPart.hasKey(REQUEST_BODY_KEY_URI) &&
|
||||
bodyPart.getString(REQUEST_BODY_KEY_URI) != null) {
|
||||
if (partContentType == null) {
|
||||
ResponseUtil.onRequestError(
|
||||
NetworkEventUtil.onRequestError(
|
||||
reactApplicationContext,
|
||||
requestId,
|
||||
"Binary FormData part needs a content-type header.",
|
||||
@@ -741,14 +756,14 @@ public class NetworkingModule(
|
||||
}
|
||||
val fileContentUriStr = bodyPart.getString(REQUEST_BODY_KEY_URI)
|
||||
if (fileContentUriStr == null) {
|
||||
ResponseUtil.onRequestError(
|
||||
NetworkEventUtil.onRequestError(
|
||||
reactApplicationContext, requestId, "Body must have a valid file uri", null)
|
||||
return null
|
||||
}
|
||||
val fileInputStream =
|
||||
RequestBodyUtil.getFileInputStream(getReactApplicationContext(), fileContentUriStr)
|
||||
if (fileInputStream == null) {
|
||||
ResponseUtil.onRequestError(
|
||||
NetworkEventUtil.onRequestError(
|
||||
reactApplicationContext,
|
||||
requestId,
|
||||
"Could not retrieve file for uri $fileContentUriStr",
|
||||
@@ -757,7 +772,7 @@ public class NetworkingModule(
|
||||
}
|
||||
multipartBuilder.addPart(headers, RequestBodyUtil.create(partContentType, fileInputStream))
|
||||
} else {
|
||||
ResponseUtil.onRequestError(
|
||||
NetworkEventUtil.onRequestError(
|
||||
reactApplicationContext, requestId, "Unrecognized FormData part.", null)
|
||||
}
|
||||
}
|
||||
@@ -827,20 +842,5 @@ public class NetworkingModule(
|
||||
}
|
||||
|
||||
private fun shouldDispatch(now: Long, last: Long): Boolean = last + CHUNK_TIMEOUT_NS < now
|
||||
|
||||
private fun translateHeaders(headers: Headers): WritableMap {
|
||||
val responseHeaders = Bundle()
|
||||
for (i in 0..<headers.size()) {
|
||||
val headerName = headers.name(i)
|
||||
// multiple values for the same header
|
||||
if (responseHeaders.containsKey(headerName)) {
|
||||
responseHeaders.putString(
|
||||
headerName, "${responseHeaders.getString(headerName)}, ${headers.value(i)}")
|
||||
} else {
|
||||
responseHeaders.putString(headerName, headers.value(i))
|
||||
}
|
||||
}
|
||||
return Arguments.fromBundle(responseHeaders)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-133
@@ -1,133 +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.modules.network
|
||||
|
||||
import com.facebook.react.bridge.Arguments
|
||||
import com.facebook.react.bridge.ReactApplicationContext
|
||||
import com.facebook.react.bridge.WritableMap
|
||||
import com.facebook.react.bridge.buildReadableArray
|
||||
import java.net.SocketTimeoutException
|
||||
|
||||
/** Util methods to send network responses to JS. */
|
||||
internal object ResponseUtil {
|
||||
@JvmStatic
|
||||
fun onDataSend(
|
||||
reactContext: ReactApplicationContext?,
|
||||
requestId: Int,
|
||||
progress: Long,
|
||||
total: Long
|
||||
) {
|
||||
reactContext?.emitDeviceEvent(
|
||||
"didSendNetworkData",
|
||||
buildReadableArray {
|
||||
add(requestId)
|
||||
add(progress.toInt())
|
||||
add(total.toInt())
|
||||
})
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun onIncrementalDataReceived(
|
||||
reactContext: ReactApplicationContext?,
|
||||
requestId: Int,
|
||||
data: String?,
|
||||
progress: Long,
|
||||
total: Long
|
||||
) {
|
||||
reactContext?.emitDeviceEvent(
|
||||
"didReceiveNetworkIncrementalData",
|
||||
buildReadableArray {
|
||||
add(requestId)
|
||||
add(data)
|
||||
add(progress.toInt())
|
||||
add(total.toInt())
|
||||
})
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun onDataReceivedProgress(
|
||||
reactContext: ReactApplicationContext?,
|
||||
requestId: Int,
|
||||
progress: Long,
|
||||
total: Long
|
||||
) {
|
||||
reactContext?.emitDeviceEvent(
|
||||
"didReceiveNetworkDataProgress",
|
||||
buildReadableArray {
|
||||
add(requestId)
|
||||
add(progress.toInt())
|
||||
add(total.toInt())
|
||||
})
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun onDataReceived(reactContext: ReactApplicationContext?, requestId: Int, data: String?) {
|
||||
reactContext?.emitDeviceEvent(
|
||||
"didReceiveNetworkData",
|
||||
buildReadableArray {
|
||||
add(requestId)
|
||||
add(data)
|
||||
})
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun onDataReceived(reactContext: ReactApplicationContext?, requestId: Int, data: WritableMap?) {
|
||||
reactContext?.emitDeviceEvent(
|
||||
"didReceiveNetworkData",
|
||||
Arguments.createArray().apply {
|
||||
pushInt(requestId)
|
||||
pushMap(data)
|
||||
})
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun onRequestError(
|
||||
reactContext: ReactApplicationContext?,
|
||||
requestId: Int,
|
||||
error: String?,
|
||||
e: Throwable?
|
||||
) {
|
||||
reactContext?.emitDeviceEvent(
|
||||
"didCompleteNetworkResponse",
|
||||
buildReadableArray {
|
||||
add(requestId)
|
||||
add(error)
|
||||
if (e?.javaClass == SocketTimeoutException::class.java) {
|
||||
add(true) // last argument is a time out boolean
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun onRequestSuccess(reactContext: ReactApplicationContext?, requestId: Int) {
|
||||
reactContext?.emitDeviceEvent(
|
||||
"didCompleteNetworkResponse",
|
||||
buildReadableArray {
|
||||
add(requestId)
|
||||
addNull()
|
||||
})
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun onResponseReceived(
|
||||
reactContext: ReactApplicationContext?,
|
||||
requestId: Int,
|
||||
statusCode: Int,
|
||||
headers: WritableMap?,
|
||||
url: String?
|
||||
) {
|
||||
reactContext?.emitDeviceEvent(
|
||||
"didReceiveNetworkResponse",
|
||||
Arguments.createArray().apply {
|
||||
pushInt(requestId)
|
||||
pushInt(statusCode)
|
||||
pushMap(headers)
|
||||
pushString(url)
|
||||
})
|
||||
}
|
||||
}
|
||||
+12
-5
@@ -253,11 +253,18 @@ public class ReactHostImpl(
|
||||
|
||||
val currentActivity = this.currentActivity
|
||||
if (currentActivity != null) {
|
||||
val currentActivityClass = currentActivity.javaClass.simpleName
|
||||
val activityClass = if (activity == null) "null" else activity.javaClass.simpleName
|
||||
Assertions.assertCondition(
|
||||
activity === currentActivity,
|
||||
"Pausing an activity that is not the current activity, this is incorrect! Current activity: $currentActivityClass Paused activity: $activityClass")
|
||||
val isSameActivity = activity === currentActivity
|
||||
if (!isSameActivity) {
|
||||
val currentActivityClass = currentActivity.javaClass.simpleName
|
||||
val activityClass = if (activity == null) "null" else activity.javaClass.simpleName
|
||||
val isNotSameActivityMessage =
|
||||
"Pausing an activity that is not the current activity, this is incorrect! Current activity: $currentActivityClass Paused activity: $activityClass"
|
||||
if (ReactNativeFeatureFlags.skipActivityIdentityAssertionOnHostPause()) {
|
||||
log(method, isNotSameActivityMessage)
|
||||
} else {
|
||||
Assertions.assertCondition(isSameActivity, isNotSameActivityMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
maybeEnableDevSupport(false)
|
||||
|
||||
+15
-1
@@ -13,8 +13,10 @@ import android.util.DisplayMetrics
|
||||
import android.view.WindowManager
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.window.layout.WindowMetricsCalculator
|
||||
import com.facebook.react.bridge.WritableMap
|
||||
import com.facebook.react.bridge.WritableNativeMap
|
||||
import com.facebook.react.views.view.isEdgeToEdgeFeatureFlagOn
|
||||
|
||||
/**
|
||||
* Holds an instance of the current DisplayMetrics so we don't have to thread it through all the
|
||||
@@ -62,9 +64,19 @@ public object DisplayMetricsHolder {
|
||||
@JvmStatic
|
||||
public fun initDisplayMetrics(context: Context) {
|
||||
val displayMetrics = context.resources.displayMetrics
|
||||
windowDisplayMetrics = displayMetrics
|
||||
val windowDisplayMetrics = DisplayMetrics()
|
||||
val screenDisplayMetrics = DisplayMetrics()
|
||||
|
||||
windowDisplayMetrics.setTo(displayMetrics)
|
||||
screenDisplayMetrics.setTo(displayMetrics)
|
||||
|
||||
if (isEdgeToEdgeFeatureFlagOn) {
|
||||
WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(context).let {
|
||||
windowDisplayMetrics.widthPixels = it.bounds.width()
|
||||
windowDisplayMetrics.heightPixels = it.bounds.height()
|
||||
}
|
||||
}
|
||||
|
||||
val wm = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
|
||||
// Get the real display metrics if we are using API level 17 or higher.
|
||||
// The real metrics include system decor elements (e.g. soft menu bar).
|
||||
@@ -72,6 +84,8 @@ public object DisplayMetricsHolder {
|
||||
// See:
|
||||
// http://developer.android.com/reference/android/view/Display.html#getRealMetrics(android.util.DisplayMetrics)
|
||||
@Suppress("DEPRECATION") wm.defaultDisplay.getRealMetrics(screenDisplayMetrics)
|
||||
|
||||
DisplayMetricsHolder.windowDisplayMetrics = windowDisplayMetrics
|
||||
DisplayMetricsHolder.screenDisplayMetrics = screenDisplayMetrics
|
||||
}
|
||||
|
||||
|
||||
+19
@@ -8,10 +8,12 @@
|
||||
package com.facebook.react.uimanager
|
||||
|
||||
import com.facebook.common.logging.FLog
|
||||
import com.facebook.react.bridge.NativeArray
|
||||
import com.facebook.react.bridge.ReadableArray
|
||||
import com.facebook.react.bridge.ReadableMap
|
||||
import com.facebook.react.bridge.ReadableType
|
||||
import com.facebook.react.common.ReactConstants
|
||||
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags
|
||||
|
||||
public object TransformHelper {
|
||||
|
||||
@@ -69,6 +71,14 @@ public object TransformHelper {
|
||||
transformOrigin: ReadableArray?,
|
||||
allowPercentageResolution: Boolean
|
||||
) {
|
||||
if (allowPercentageResolution &&
|
||||
ReactNativeFeatureFlags.useNativeTransformHelperAndroid() &&
|
||||
transforms is NativeArray &&
|
||||
transformOrigin is NativeArray?) {
|
||||
nativeProcessTransform(transforms, result, viewWidth, viewHeight, transformOrigin)
|
||||
return
|
||||
}
|
||||
|
||||
val helperMatrix = helperMatrix.get()!!
|
||||
MatrixMathHelper.resetIdentityMatrix(result)
|
||||
val offsets =
|
||||
@@ -220,4 +230,13 @@ public object TransformHelper {
|
||||
|
||||
return doubleArrayOf(newTranslateX, newTranslateY, newTranslateZ)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
private external fun nativeProcessTransform(
|
||||
transforms: NativeArray,
|
||||
result: DoubleArray,
|
||||
viewWidth: Float,
|
||||
viewHeight: Float,
|
||||
transformOrigin: NativeArray?
|
||||
)
|
||||
}
|
||||
|
||||
+6
-9
@@ -30,15 +30,12 @@ internal class DebuggingOverlayManager :
|
||||
|
||||
override fun getDelegate(): ViewManagerDelegate<DebuggingOverlay> = delegate
|
||||
|
||||
override fun highlightTraceUpdates(
|
||||
view: DebuggingOverlay,
|
||||
providedTraceUpdates: ReadableArray
|
||||
): Unit {
|
||||
override fun highlightTraceUpdates(view: DebuggingOverlay, updates: ReadableArray): Unit {
|
||||
val formattedTraceUpdates = mutableListOf<TraceUpdate>()
|
||||
|
||||
var successfullyParsedPayload = true
|
||||
for (i in 0 until providedTraceUpdates.size()) {
|
||||
val traceUpdate = providedTraceUpdates.getMap(i) ?: continue
|
||||
for (i in 0 until updates.size()) {
|
||||
val traceUpdate = updates.getMap(i) ?: continue
|
||||
val serializedRectangle = traceUpdate.getMap("rectangle")
|
||||
if (serializedRectangle == null) {
|
||||
ReactSoftExceptionLogger.logSoftException(
|
||||
@@ -82,12 +79,12 @@ internal class DebuggingOverlayManager :
|
||||
}
|
||||
}
|
||||
|
||||
override fun highlightElements(view: DebuggingOverlay, providedElements: ReadableArray): Unit {
|
||||
override fun highlightElements(view: DebuggingOverlay, elements: ReadableArray): Unit {
|
||||
val elementsRectangles = mutableListOf<RectF>()
|
||||
|
||||
var successfullyParsedPayload = true
|
||||
for (i in 0 until providedElements.size()) {
|
||||
val element = providedElements.getMap(i) ?: continue
|
||||
for (i in 0 until elements.size()) {
|
||||
val element = elements.getMap(i) ?: continue
|
||||
try {
|
||||
val left = element.getDouble("x").toFloat()
|
||||
val top = element.getDouble("y").toFloat()
|
||||
|
||||
+5
-5
@@ -108,20 +108,20 @@ public class ReactDrawerLayoutManager :
|
||||
view.setDrawerWidth(widthInPx)
|
||||
}
|
||||
|
||||
public override fun setDrawerWidth(view: ReactDrawerLayout, width: Float?) {
|
||||
val widthInPx = width?.let { Math.round(it.dpToPx()) } ?: ReactDrawerLayout.DEFAULT_DRAWER_WIDTH
|
||||
public override fun setDrawerWidth(view: ReactDrawerLayout, value: Float?) {
|
||||
val widthInPx = value?.let { Math.round(it.dpToPx()) } ?: ReactDrawerLayout.DEFAULT_DRAWER_WIDTH
|
||||
view.setDrawerWidth(widthInPx)
|
||||
}
|
||||
|
||||
@ReactProp(name = "drawerLockMode")
|
||||
public override fun setDrawerLockMode(view: ReactDrawerLayout, drawerLockMode: String?) {
|
||||
when (drawerLockMode) {
|
||||
public override fun setDrawerLockMode(view: ReactDrawerLayout, value: String?) {
|
||||
when (value) {
|
||||
null,
|
||||
"unlocked" -> view.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
|
||||
"locked-closed" -> view.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
|
||||
"locked-open" -> view.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_OPEN)
|
||||
else -> {
|
||||
FLog.w(ReactConstants.TAG, "Unknown drawerLockMode $drawerLockMode")
|
||||
FLog.w(ReactConstants.TAG, "Unknown drawerLockMode $value")
|
||||
view.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
|
||||
}
|
||||
}
|
||||
|
||||
+12
-15
@@ -38,37 +38,34 @@ internal class ReactModalHostManager :
|
||||
}
|
||||
|
||||
@ReactProp(name = "animationType")
|
||||
override fun setAnimationType(view: ReactModalHostView, animationType: String?) {
|
||||
if (animationType != null) {
|
||||
view.animationType = animationType
|
||||
override fun setAnimationType(view: ReactModalHostView, value: String?) {
|
||||
if (value != null) {
|
||||
view.animationType = value
|
||||
}
|
||||
}
|
||||
|
||||
@ReactProp(name = "transparent")
|
||||
override fun setTransparent(view: ReactModalHostView, transparent: Boolean) {
|
||||
view.transparent = transparent
|
||||
override fun setTransparent(view: ReactModalHostView, value: Boolean) {
|
||||
view.transparent = value
|
||||
}
|
||||
|
||||
@ReactProp(name = "statusBarTranslucent")
|
||||
override fun setStatusBarTranslucent(view: ReactModalHostView, statusBarTranslucent: Boolean) {
|
||||
view.statusBarTranslucent = statusBarTranslucent
|
||||
override fun setStatusBarTranslucent(view: ReactModalHostView, value: Boolean) {
|
||||
view.statusBarTranslucent = value
|
||||
}
|
||||
|
||||
@ReactProp(name = "navigationBarTranslucent")
|
||||
override fun setNavigationBarTranslucent(
|
||||
view: ReactModalHostView,
|
||||
navigationBarTranslucent: Boolean
|
||||
) {
|
||||
view.navigationBarTranslucent = navigationBarTranslucent
|
||||
override fun setNavigationBarTranslucent(view: ReactModalHostView, value: Boolean) {
|
||||
view.navigationBarTranslucent = value
|
||||
}
|
||||
|
||||
@ReactProp(name = "hardwareAccelerated")
|
||||
override fun setHardwareAccelerated(view: ReactModalHostView, hardwareAccelerated: Boolean) {
|
||||
view.hardwareAccelerated = hardwareAccelerated
|
||||
override fun setHardwareAccelerated(view: ReactModalHostView, value: Boolean) {
|
||||
view.hardwareAccelerated = value
|
||||
}
|
||||
|
||||
@ReactProp(name = "visible")
|
||||
override fun setVisible(view: ReactModalHostView, visible: Boolean) {
|
||||
override fun setVisible(view: ReactModalHostView, value: Boolean) {
|
||||
// iOS only
|
||||
}
|
||||
|
||||
|
||||
+10
-10
@@ -49,28 +49,28 @@ internal class ReactProgressBarViewManager :
|
||||
}
|
||||
|
||||
@ReactProp(name = PROP_STYLE)
|
||||
override fun setStyleAttr(view: ProgressBarContainerView, styleName: String?) {
|
||||
view.setStyle(styleName)
|
||||
override fun setStyleAttr(view: ProgressBarContainerView, value: String?) {
|
||||
view.setStyle(value)
|
||||
}
|
||||
|
||||
@ReactProp(name = ViewProps.COLOR, customType = "Color")
|
||||
override fun setColor(view: ProgressBarContainerView, color: Int?) {
|
||||
view.color = color
|
||||
override fun setColor(view: ProgressBarContainerView, value: Int?) {
|
||||
view.color = value
|
||||
}
|
||||
|
||||
@ReactProp(name = PROP_INDETERMINATE)
|
||||
override fun setIndeterminate(view: ProgressBarContainerView, indeterminate: Boolean) {
|
||||
view.indeterminate = indeterminate
|
||||
override fun setIndeterminate(view: ProgressBarContainerView, value: Boolean) {
|
||||
view.indeterminate = value
|
||||
}
|
||||
|
||||
@ReactProp(name = PROP_PROGRESS)
|
||||
override fun setProgress(view: ProgressBarContainerView, progress: Double) {
|
||||
view.progress = progress
|
||||
override fun setProgress(view: ProgressBarContainerView, value: Double) {
|
||||
view.progress = value
|
||||
}
|
||||
|
||||
@ReactProp(name = PROP_ANIMATING)
|
||||
override fun setAnimating(view: ProgressBarContainerView, animating: Boolean) {
|
||||
view.animating = animating
|
||||
override fun setAnimating(view: ProgressBarContainerView, value: Boolean) {
|
||||
view.animating = value
|
||||
}
|
||||
|
||||
override fun setTestID(view: ProgressBarContainerView, value: String?) {
|
||||
|
||||
+19
-19
@@ -42,19 +42,19 @@ internal open class SwipeRefreshLayoutManager :
|
||||
override fun getName(): String = REACT_CLASS
|
||||
|
||||
@ReactProp(name = ViewProps.ENABLED, defaultBoolean = true)
|
||||
override fun setEnabled(view: ReactSwipeRefreshLayout, enabled: Boolean) {
|
||||
view.isEnabled = enabled
|
||||
override fun setEnabled(view: ReactSwipeRefreshLayout, value: Boolean) {
|
||||
view.isEnabled = value
|
||||
}
|
||||
|
||||
@ReactProp(name = "colors", customType = "ColorArray")
|
||||
override fun setColors(view: ReactSwipeRefreshLayout, colors: ReadableArray?) {
|
||||
if (colors != null) {
|
||||
val colorValues = IntArray(colors.size())
|
||||
for (i in 0..<colors.size()) {
|
||||
if (colors.getType(i) == ReadableType.Map) {
|
||||
colorValues[i] = ColorPropConverter.getColor(colors.getMap(i), view.context, 0)
|
||||
override fun setColors(view: ReactSwipeRefreshLayout, value: ReadableArray?) {
|
||||
if (value != null) {
|
||||
val colorValues = IntArray(value.size())
|
||||
for (i in 0..<value.size()) {
|
||||
if (value.getType(i) == ReadableType.Map) {
|
||||
colorValues[i] = ColorPropConverter.getColor(value.getMap(i), view.context, 0)
|
||||
} else {
|
||||
colorValues[i] = colors.getInt(i)
|
||||
colorValues[i] = value.getInt(i)
|
||||
}
|
||||
}
|
||||
view.setColorSchemeColors(*colorValues)
|
||||
@@ -64,8 +64,8 @@ internal open class SwipeRefreshLayoutManager :
|
||||
}
|
||||
|
||||
@ReactProp(name = "progressBackgroundColor", customType = "Color")
|
||||
override fun setProgressBackgroundColor(view: ReactSwipeRefreshLayout, color: Int?) {
|
||||
view.setProgressBackgroundColorSchemeColor(color ?: Color.TRANSPARENT)
|
||||
override fun setProgressBackgroundColor(view: ReactSwipeRefreshLayout, value: Int?) {
|
||||
view.setProgressBackgroundColorSchemeColor(value ?: Color.TRANSPARENT)
|
||||
}
|
||||
|
||||
// TODO(T46143833): Remove this method once the 'size' prop has been migrated to String in JS.
|
||||
@@ -73,13 +73,13 @@ internal open class SwipeRefreshLayoutManager :
|
||||
view.setSize(value)
|
||||
}
|
||||
|
||||
override fun setSize(view: ReactSwipeRefreshLayout, size: String?) {
|
||||
if (size == null || size.equals("default")) {
|
||||
override fun setSize(view: ReactSwipeRefreshLayout, value: String?) {
|
||||
if (value == null || value.equals("default")) {
|
||||
view.setSize(SwipeRefreshLayout.DEFAULT)
|
||||
} else if (size.equals("large")) {
|
||||
} else if (value.equals("large")) {
|
||||
view.setSize(SwipeRefreshLayout.LARGE)
|
||||
} else {
|
||||
throw IllegalArgumentException("Size must be 'default' or 'large', received: $size")
|
||||
throw IllegalArgumentException("Size must be 'default' or 'large', received: $value")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,13 +97,13 @@ internal open class SwipeRefreshLayoutManager :
|
||||
}
|
||||
|
||||
@ReactProp(name = "refreshing")
|
||||
override fun setRefreshing(view: ReactSwipeRefreshLayout, refreshing: Boolean) {
|
||||
view.isRefreshing = refreshing
|
||||
override fun setRefreshing(view: ReactSwipeRefreshLayout, value: Boolean) {
|
||||
view.isRefreshing = value
|
||||
}
|
||||
|
||||
@ReactProp(name = "progressViewOffset", defaultFloat = 0f)
|
||||
override fun setProgressViewOffset(view: ReactSwipeRefreshLayout, offset: Float) {
|
||||
view.setProgressViewOffset(offset)
|
||||
override fun setProgressViewOffset(view: ReactSwipeRefreshLayout, value: Float) {
|
||||
view.setProgressViewOffset(value)
|
||||
}
|
||||
|
||||
override fun setNativeRefreshing(view: ReactSwipeRefreshLayout, value: Boolean) {
|
||||
|
||||
+16
-16
@@ -46,18 +46,18 @@ internal class ReactSwitchManager :
|
||||
}
|
||||
|
||||
@ReactProp(name = "disabled", defaultBoolean = false)
|
||||
override fun setDisabled(view: ReactSwitch, disabled: Boolean) {
|
||||
view.isEnabled = !disabled
|
||||
override fun setDisabled(view: ReactSwitch, value: Boolean) {
|
||||
view.isEnabled = !value
|
||||
}
|
||||
|
||||
@ReactProp(name = ViewProps.ENABLED, defaultBoolean = true)
|
||||
override fun setEnabled(view: ReactSwitch, enabled: Boolean) {
|
||||
view.isEnabled = enabled
|
||||
override fun setEnabled(view: ReactSwitch, value: Boolean) {
|
||||
view.isEnabled = value
|
||||
}
|
||||
|
||||
@ReactProp(name = ViewProps.ON)
|
||||
override fun setOn(view: ReactSwitch, on: Boolean) {
|
||||
setValueInternal(view, on)
|
||||
override fun setOn(view: ReactSwitch, value: Boolean) {
|
||||
setValueInternal(view, value)
|
||||
}
|
||||
|
||||
@ReactProp(name = "value")
|
||||
@@ -66,28 +66,28 @@ internal class ReactSwitchManager :
|
||||
}
|
||||
|
||||
@ReactProp(name = "thumbTintColor", customType = "Color")
|
||||
override fun setThumbTintColor(view: ReactSwitch, color: Int?) {
|
||||
setThumbColor(view, color)
|
||||
override fun setThumbTintColor(view: ReactSwitch, value: Int?) {
|
||||
setThumbColor(view, value)
|
||||
}
|
||||
|
||||
@ReactProp(name = "thumbColor", customType = "Color")
|
||||
override fun setThumbColor(view: ReactSwitch, color: Int?) {
|
||||
view.setThumbColor(color)
|
||||
override fun setThumbColor(view: ReactSwitch, value: Int?) {
|
||||
view.setThumbColor(value)
|
||||
}
|
||||
|
||||
@ReactProp(name = "trackColorForFalse", customType = "Color")
|
||||
override fun setTrackColorForFalse(view: ReactSwitch, color: Int?) {
|
||||
view.setTrackColorForFalse(color)
|
||||
override fun setTrackColorForFalse(view: ReactSwitch, value: Int?) {
|
||||
view.setTrackColorForFalse(value)
|
||||
}
|
||||
|
||||
@ReactProp(name = "trackColorForTrue", customType = "Color")
|
||||
override fun setTrackColorForTrue(view: ReactSwitch, color: Int?) {
|
||||
view.setTrackColorForTrue(color)
|
||||
override fun setTrackColorForTrue(view: ReactSwitch, value: Int?) {
|
||||
view.setTrackColorForTrue(value)
|
||||
}
|
||||
|
||||
@ReactProp(name = "trackTintColor", customType = "Color")
|
||||
override fun setTrackTintColor(view: ReactSwitch, color: Int?) {
|
||||
view.setTrackColor(color)
|
||||
override fun setTrackTintColor(view: ReactSwitch, value: Int?) {
|
||||
view.setTrackColor(value)
|
||||
}
|
||||
|
||||
override fun setNativeValue(view: ReactSwitch, value: Boolean) {
|
||||
|
||||
+5
-2
@@ -1102,7 +1102,8 @@ internal object TextLayoutManager {
|
||||
// There's a bug on Samsung devices where calling getPrimaryHorizontal on
|
||||
// the last offset in the layout will result in an endless loop. Work around
|
||||
// this bug by avoiding getPrimaryHorizontal in that case.
|
||||
if (start == text.length - 1) {
|
||||
if (!ReactNativeFeatureFlags.disableOldAndroidAttachmentMetricsWorkarounds() &&
|
||||
start == text.length - 1) {
|
||||
val endsWithNewLine = text.length > 0 && text[layout.getLineEnd(line) - 1] == '\n'
|
||||
val lineWidth = if (endsWithNewLine) layout.getLineMax(line) else layout.getLineWidth(line)
|
||||
placeholderLeftPosition =
|
||||
@@ -1127,7 +1128,9 @@ internal object TextLayoutManager {
|
||||
placeholderLeftPosition =
|
||||
if (characterAndParagraphDirectionMatch) layout.getPrimaryHorizontal(start)
|
||||
else layout.getSecondaryHorizontal(start)
|
||||
if (isRtlParagraph && !isRtlChar) {
|
||||
if (!ReactNativeFeatureFlags.disableOldAndroidAttachmentMetricsWorkarounds() &&
|
||||
isRtlParagraph &&
|
||||
!isRtlChar) {
|
||||
// Adjust `placeholderLeftPosition` to work around an Android bug.
|
||||
// The bug is when the paragraph is RTL and `setSingleLine(true)`, some layout
|
||||
// methods such as `getPrimaryHorizontal`, `getSecondaryHorizontal`, and
|
||||
|
||||
+2
-12
@@ -10,26 +10,16 @@ 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(
|
||||
internal class ReactContentSizeChangedEvent
|
||||
constructor(
|
||||
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 {
|
||||
|
||||
-10
@@ -9,7 +9,6 @@ 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. */
|
||||
@@ -19,15 +18,6 @@ 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 {
|
||||
|
||||
-6
@@ -9,7 +9,6 @@ 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
|
||||
|
||||
/**
|
||||
@@ -21,11 +20,6 @@ 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
|
||||
|
||||
-6
@@ -9,17 +9,11 @@ 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
@@ -10,7 +10,6 @@ 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. */
|
||||
@@ -20,15 +19,6 @@ 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 {
|
||||
|
||||
-6
@@ -9,7 +9,6 @@ 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. */
|
||||
@@ -18,11 +17,6 @@ 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 {
|
||||
|
||||
+2
-2
@@ -35,8 +35,8 @@ internal class ReactUnimplementedViewManager :
|
||||
override fun getName(): String = REACT_CLASS
|
||||
|
||||
@ReactProp(name = "name")
|
||||
override fun setName(view: ReactUnimplementedView, name: String?): Unit =
|
||||
view.setName(name ?: "<null component name>")
|
||||
override fun setName(view: ReactUnimplementedView, value: String?): Unit =
|
||||
view.setName(value ?: "<null component name>")
|
||||
|
||||
internal companion object {
|
||||
const val REACT_CLASS: String = "UnimplementedNativeView"
|
||||
|
||||
+1
-1
@@ -101,7 +101,7 @@ public class ReactVirtualView(context: Context) :
|
||||
ReactScrollViewHelper.removeScrollListener(this)
|
||||
ReactScrollViewHelper.removeLayoutChangeListener(this)
|
||||
if (detectWindowFocus) {
|
||||
viewTreeObserver.addOnWindowFocusChangeListener(onWindowFocusChangeListener)
|
||||
viewTreeObserver.removeOnWindowFocusChangeListener(onWindowFocusChangeListener)
|
||||
}
|
||||
cleanupLayoutListeners()
|
||||
}
|
||||
|
||||
+113
-43
@@ -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<<d2e4ec09356f6857d789cfcc44a83552>>
|
||||
* @generated SignedSource<<f310a5dc27fd655eab4445cb25d4c85c>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -57,18 +57,18 @@ 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");
|
||||
return method(javaProvider_);
|
||||
}
|
||||
|
||||
bool disableOldAndroidAttachmentMetricsWorkarounds() override {
|
||||
static const auto method =
|
||||
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("disableOldAndroidAttachmentMetricsWorkarounds");
|
||||
return method(javaProvider_);
|
||||
}
|
||||
|
||||
bool disableTextLayoutManagerCacheAndroid() override {
|
||||
static const auto method =
|
||||
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("disableTextLayoutManagerCacheAndroid");
|
||||
@@ -123,6 +123,12 @@ 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");
|
||||
@@ -165,6 +171,12 @@ class ReactNativeFeatureFlagsJavaProvider
|
||||
return method(javaProvider_);
|
||||
}
|
||||
|
||||
bool enableImmediateUpdateModeForContentOffsetChanges() override {
|
||||
static const auto method =
|
||||
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableImmediateUpdateModeForContentOffsetChanges");
|
||||
return method(javaProvider_);
|
||||
}
|
||||
|
||||
bool enableInteropViewManagerClassLookUpOptimizationIOS() override {
|
||||
static const auto method =
|
||||
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableInteropViewManagerClassLookUpOptimizationIOS");
|
||||
@@ -189,12 +201,6 @@ 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");
|
||||
@@ -237,12 +243,6 @@ class ReactNativeFeatureFlagsJavaProvider
|
||||
return method(javaProvider_);
|
||||
}
|
||||
|
||||
bool enableSynchronousStateUpdates() override {
|
||||
static const auto method =
|
||||
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableSynchronousStateUpdates");
|
||||
return method(javaProvider_);
|
||||
}
|
||||
|
||||
bool enableViewCulling() override {
|
||||
static const auto method =
|
||||
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableViewCulling");
|
||||
@@ -315,6 +315,24 @@ class ReactNativeFeatureFlagsJavaProvider
|
||||
return method(javaProvider_);
|
||||
}
|
||||
|
||||
bool preventShadowTreeCommitExhaustionWithLocking() override {
|
||||
static const auto method =
|
||||
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("preventShadowTreeCommitExhaustionWithLocking");
|
||||
return method(javaProvider_);
|
||||
}
|
||||
|
||||
bool releaseImageDataWhenConsumed() override {
|
||||
static const auto method =
|
||||
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("releaseImageDataWhenConsumed");
|
||||
return method(javaProvider_);
|
||||
}
|
||||
|
||||
bool skipActivityIdentityAssertionOnHostPause() override {
|
||||
static const auto method =
|
||||
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("skipActivityIdentityAssertionOnHostPause");
|
||||
return method(javaProvider_);
|
||||
}
|
||||
|
||||
bool traceTurboModulePromiseRejectionsOnAndroid() override {
|
||||
static const auto method =
|
||||
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("traceTurboModulePromiseRejectionsOnAndroid");
|
||||
@@ -339,6 +357,18 @@ class ReactNativeFeatureFlagsJavaProvider
|
||||
return method(javaProvider_);
|
||||
}
|
||||
|
||||
bool useNativeEqualsInNativeReadableArrayAndroid() override {
|
||||
static const auto method =
|
||||
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("useNativeEqualsInNativeReadableArrayAndroid");
|
||||
return method(javaProvider_);
|
||||
}
|
||||
|
||||
bool useNativeTransformHelperAndroid() override {
|
||||
static const auto method =
|
||||
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("useNativeTransformHelperAndroid");
|
||||
return method(javaProvider_);
|
||||
}
|
||||
|
||||
bool useNativeViewConfigsInBridgelessMode() override {
|
||||
static const auto method =
|
||||
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("useNativeViewConfigsInBridgelessMode");
|
||||
@@ -400,16 +430,16 @@ 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();
|
||||
}
|
||||
|
||||
bool JReactNativeFeatureFlagsCxxInterop::disableOldAndroidAttachmentMetricsWorkarounds(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
|
||||
return ReactNativeFeatureFlags::disableOldAndroidAttachmentMetricsWorkarounds();
|
||||
}
|
||||
|
||||
bool JReactNativeFeatureFlagsCxxInterop::disableTextLayoutManagerCacheAndroid(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
|
||||
return ReactNativeFeatureFlags::disableTextLayoutManagerCacheAndroid();
|
||||
@@ -455,6 +485,11 @@ 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();
|
||||
@@ -490,6 +525,11 @@ bool JReactNativeFeatureFlagsCxxInterop::enableIOSViewClipToPaddingBox(
|
||||
return ReactNativeFeatureFlags::enableIOSViewClipToPaddingBox();
|
||||
}
|
||||
|
||||
bool JReactNativeFeatureFlagsCxxInterop::enableImmediateUpdateModeForContentOffsetChanges(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
|
||||
return ReactNativeFeatureFlags::enableImmediateUpdateModeForContentOffsetChanges();
|
||||
}
|
||||
|
||||
bool JReactNativeFeatureFlagsCxxInterop::enableInteropViewManagerClassLookUpOptimizationIOS(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
|
||||
return ReactNativeFeatureFlags::enableInteropViewManagerClassLookUpOptimizationIOS();
|
||||
@@ -510,11 +550,6 @@ 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();
|
||||
@@ -550,11 +585,6 @@ bool JReactNativeFeatureFlagsCxxInterop::enableResourceTimingAPI(
|
||||
return ReactNativeFeatureFlags::enableResourceTimingAPI();
|
||||
}
|
||||
|
||||
bool JReactNativeFeatureFlagsCxxInterop::enableSynchronousStateUpdates(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
|
||||
return ReactNativeFeatureFlags::enableSynchronousStateUpdates();
|
||||
}
|
||||
|
||||
bool JReactNativeFeatureFlagsCxxInterop::enableViewCulling(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
|
||||
return ReactNativeFeatureFlags::enableViewCulling();
|
||||
@@ -615,6 +645,21 @@ double JReactNativeFeatureFlagsCxxInterop::preparedTextCacheSize(
|
||||
return ReactNativeFeatureFlags::preparedTextCacheSize();
|
||||
}
|
||||
|
||||
bool JReactNativeFeatureFlagsCxxInterop::preventShadowTreeCommitExhaustionWithLocking(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
|
||||
return ReactNativeFeatureFlags::preventShadowTreeCommitExhaustionWithLocking();
|
||||
}
|
||||
|
||||
bool JReactNativeFeatureFlagsCxxInterop::releaseImageDataWhenConsumed(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
|
||||
return ReactNativeFeatureFlags::releaseImageDataWhenConsumed();
|
||||
}
|
||||
|
||||
bool JReactNativeFeatureFlagsCxxInterop::skipActivityIdentityAssertionOnHostPause(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
|
||||
return ReactNativeFeatureFlags::skipActivityIdentityAssertionOnHostPause();
|
||||
}
|
||||
|
||||
bool JReactNativeFeatureFlagsCxxInterop::traceTurboModulePromiseRejectionsOnAndroid(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
|
||||
return ReactNativeFeatureFlags::traceTurboModulePromiseRejectionsOnAndroid();
|
||||
@@ -635,6 +680,16 @@ bool JReactNativeFeatureFlagsCxxInterop::useFabricInterop(
|
||||
return ReactNativeFeatureFlags::useFabricInterop();
|
||||
}
|
||||
|
||||
bool JReactNativeFeatureFlagsCxxInterop::useNativeEqualsInNativeReadableArrayAndroid(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
|
||||
return ReactNativeFeatureFlags::useNativeEqualsInNativeReadableArrayAndroid();
|
||||
}
|
||||
|
||||
bool JReactNativeFeatureFlagsCxxInterop::useNativeTransformHelperAndroid(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
|
||||
return ReactNativeFeatureFlags::useNativeTransformHelperAndroid();
|
||||
}
|
||||
|
||||
bool JReactNativeFeatureFlagsCxxInterop::useNativeViewConfigsInBridgelessMode(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
|
||||
return ReactNativeFeatureFlags::useNativeViewConfigsInBridgelessMode();
|
||||
@@ -710,12 +765,12 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
|
||||
makeNativeMethod(
|
||||
"cxxNativeAnimatedRemoveJsSync",
|
||||
JReactNativeFeatureFlagsCxxInterop::cxxNativeAnimatedRemoveJsSync),
|
||||
makeNativeMethod(
|
||||
"disableMainQueueSyncDispatchIOS",
|
||||
JReactNativeFeatureFlagsCxxInterop::disableMainQueueSyncDispatchIOS),
|
||||
makeNativeMethod(
|
||||
"disableMountItemReorderingAndroid",
|
||||
JReactNativeFeatureFlagsCxxInterop::disableMountItemReorderingAndroid),
|
||||
makeNativeMethod(
|
||||
"disableOldAndroidAttachmentMetricsWorkarounds",
|
||||
JReactNativeFeatureFlagsCxxInterop::disableOldAndroidAttachmentMetricsWorkarounds),
|
||||
makeNativeMethod(
|
||||
"disableTextLayoutManagerCacheAndroid",
|
||||
JReactNativeFeatureFlagsCxxInterop::disableTextLayoutManagerCacheAndroid),
|
||||
@@ -743,6 +798,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
|
||||
makeNativeMethod(
|
||||
"enableDoubleMeasurementFixAndroid",
|
||||
JReactNativeFeatureFlagsCxxInterop::enableDoubleMeasurementFixAndroid),
|
||||
makeNativeMethod(
|
||||
"enableEagerMainQueueModulesOnIOS",
|
||||
JReactNativeFeatureFlagsCxxInterop::enableEagerMainQueueModulesOnIOS),
|
||||
makeNativeMethod(
|
||||
"enableEagerRootViewAttachment",
|
||||
JReactNativeFeatureFlagsCxxInterop::enableEagerRootViewAttachment),
|
||||
@@ -764,6 +822,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
|
||||
makeNativeMethod(
|
||||
"enableIOSViewClipToPaddingBox",
|
||||
JReactNativeFeatureFlagsCxxInterop::enableIOSViewClipToPaddingBox),
|
||||
makeNativeMethod(
|
||||
"enableImmediateUpdateModeForContentOffsetChanges",
|
||||
JReactNativeFeatureFlagsCxxInterop::enableImmediateUpdateModeForContentOffsetChanges),
|
||||
makeNativeMethod(
|
||||
"enableInteropViewManagerClassLookUpOptimizationIOS",
|
||||
JReactNativeFeatureFlagsCxxInterop::enableInteropViewManagerClassLookUpOptimizationIOS),
|
||||
@@ -776,9 +837,6 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
|
||||
makeNativeMethod(
|
||||
"enableMainQueueCoordinatorOnIOS",
|
||||
JReactNativeFeatureFlagsCxxInterop::enableMainQueueCoordinatorOnIOS),
|
||||
makeNativeMethod(
|
||||
"enableMainQueueModulesOnIOS",
|
||||
JReactNativeFeatureFlagsCxxInterop::enableMainQueueModulesOnIOS),
|
||||
makeNativeMethod(
|
||||
"enableModuleArgumentNSNullConversionIOS",
|
||||
JReactNativeFeatureFlagsCxxInterop::enableModuleArgumentNSNullConversionIOS),
|
||||
@@ -800,9 +858,6 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
|
||||
makeNativeMethod(
|
||||
"enableResourceTimingAPI",
|
||||
JReactNativeFeatureFlagsCxxInterop::enableResourceTimingAPI),
|
||||
makeNativeMethod(
|
||||
"enableSynchronousStateUpdates",
|
||||
JReactNativeFeatureFlagsCxxInterop::enableSynchronousStateUpdates),
|
||||
makeNativeMethod(
|
||||
"enableViewCulling",
|
||||
JReactNativeFeatureFlagsCxxInterop::enableViewCulling),
|
||||
@@ -839,6 +894,15 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
|
||||
makeNativeMethod(
|
||||
"preparedTextCacheSize",
|
||||
JReactNativeFeatureFlagsCxxInterop::preparedTextCacheSize),
|
||||
makeNativeMethod(
|
||||
"preventShadowTreeCommitExhaustionWithLocking",
|
||||
JReactNativeFeatureFlagsCxxInterop::preventShadowTreeCommitExhaustionWithLocking),
|
||||
makeNativeMethod(
|
||||
"releaseImageDataWhenConsumed",
|
||||
JReactNativeFeatureFlagsCxxInterop::releaseImageDataWhenConsumed),
|
||||
makeNativeMethod(
|
||||
"skipActivityIdentityAssertionOnHostPause",
|
||||
JReactNativeFeatureFlagsCxxInterop::skipActivityIdentityAssertionOnHostPause),
|
||||
makeNativeMethod(
|
||||
"traceTurboModulePromiseRejectionsOnAndroid",
|
||||
JReactNativeFeatureFlagsCxxInterop::traceTurboModulePromiseRejectionsOnAndroid),
|
||||
@@ -851,6 +915,12 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
|
||||
makeNativeMethod(
|
||||
"useFabricInterop",
|
||||
JReactNativeFeatureFlagsCxxInterop::useFabricInterop),
|
||||
makeNativeMethod(
|
||||
"useNativeEqualsInNativeReadableArrayAndroid",
|
||||
JReactNativeFeatureFlagsCxxInterop::useNativeEqualsInNativeReadableArrayAndroid),
|
||||
makeNativeMethod(
|
||||
"useNativeTransformHelperAndroid",
|
||||
JReactNativeFeatureFlagsCxxInterop::useNativeTransformHelperAndroid),
|
||||
makeNativeMethod(
|
||||
"useNativeViewConfigsInBridgelessMode",
|
||||
JReactNativeFeatureFlagsCxxInterop::useNativeViewConfigsInBridgelessMode),
|
||||
|
||||
+24
-9
@@ -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<<a8d656adc624995ca1e6720829889cb8>>
|
||||
* @generated SignedSource<<8c1da07c0b7d2053f7fdaac4326c3ac1>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -39,10 +39,10 @@ class JReactNativeFeatureFlagsCxxInterop
|
||||
static bool cxxNativeAnimatedRemoveJsSync(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
static bool disableMainQueueSyncDispatchIOS(
|
||||
static bool disableMountItemReorderingAndroid(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
static bool disableMountItemReorderingAndroid(
|
||||
static bool disableOldAndroidAttachmentMetricsWorkarounds(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
static bool disableTextLayoutManagerCacheAndroid(
|
||||
@@ -72,6 +72,9 @@ 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>);
|
||||
|
||||
@@ -93,6 +96,9 @@ class JReactNativeFeatureFlagsCxxInterop
|
||||
static bool enableIOSViewClipToPaddingBox(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
static bool enableImmediateUpdateModeForContentOffsetChanges(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
static bool enableInteropViewManagerClassLookUpOptimizationIOS(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
@@ -105,9 +111,6 @@ 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>);
|
||||
|
||||
@@ -129,9 +132,6 @@ class JReactNativeFeatureFlagsCxxInterop
|
||||
static bool enableResourceTimingAPI(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
static bool enableSynchronousStateUpdates(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
static bool enableViewCulling(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
@@ -168,6 +168,15 @@ class JReactNativeFeatureFlagsCxxInterop
|
||||
static double preparedTextCacheSize(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
static bool preventShadowTreeCommitExhaustionWithLocking(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
static bool releaseImageDataWhenConsumed(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
static bool skipActivityIdentityAssertionOnHostPause(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
static bool traceTurboModulePromiseRejectionsOnAndroid(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
@@ -180,6 +189,12 @@ class JReactNativeFeatureFlagsCxxInterop
|
||||
static bool useFabricInterop(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
static bool useNativeEqualsInNativeReadableArrayAndroid(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
static bool useNativeTransformHelperAndroid(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
static bool useNativeViewConfigsInBridgelessMode(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ add_library(
|
||||
OnLoad-common.cpp
|
||||
ReadableNativeArray.cpp
|
||||
ReadableNativeMap.cpp
|
||||
TransformHelper.cpp
|
||||
WritableNativeArray.cpp
|
||||
WritableNativeMap.cpp
|
||||
)
|
||||
@@ -52,6 +53,7 @@ add_library(
|
||||
OBJECT
|
||||
CatalystInstanceImpl.cpp
|
||||
InspectorNetworkRequestListener.cpp
|
||||
InspectorNetworkReporter.cpp
|
||||
JExecutor.cpp
|
||||
JInspector.cpp
|
||||
JMessageQueueThread.cpp
|
||||
@@ -80,8 +82,10 @@ target_link_libraries(reactnativejni
|
||||
fbjni
|
||||
folly_runtime
|
||||
glog_init
|
||||
jsinspector_network
|
||||
logger
|
||||
react_cxxreact
|
||||
react_featureflags
|
||||
react_renderer_runtimescheduler
|
||||
reactnativejni_common
|
||||
runtimeexecutor
|
||||
|
||||
+187
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "InspectorNetworkReporter.h"
|
||||
|
||||
#include <jsinspector-modern/network/NetworkReporter.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
|
||||
#include <unordered_map>
|
||||
#endif
|
||||
|
||||
using namespace facebook::jni;
|
||||
using namespace facebook::react::jsinspector_modern;
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
namespace {
|
||||
|
||||
Headers convertJavaMapToHeaders(
|
||||
jni::alias_ref<jni::JMap<jstring, jstring>> headers) {
|
||||
Headers responseHeaders;
|
||||
|
||||
for (auto it : *headers) {
|
||||
auto key = it.first->toStdString();
|
||||
auto value = it.second->toStdString();
|
||||
responseHeaders[key] = value;
|
||||
}
|
||||
|
||||
return responseHeaders;
|
||||
}
|
||||
|
||||
std::string limitRequestBodySize(std::string requestBody) {
|
||||
const size_t maxBodySize = 1024 * 1024; // 1MB
|
||||
auto bodyLength = requestBody.size();
|
||||
auto bytesToRead = std::min(bodyLength, maxBodySize);
|
||||
|
||||
requestBody.resize(bytesToRead);
|
||||
|
||||
if (bytesToRead < bodyLength) {
|
||||
requestBody += "\n... [truncated, showing " + std::to_string(bytesToRead) +
|
||||
" of " + std::to_string(bodyLength) + " bytes]";
|
||||
}
|
||||
|
||||
return requestBody;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
|
||||
|
||||
// Dictionary to buffer incremental response bodies (CDP debugging active only)
|
||||
static std::unordered_map<int, std::string> responseBuffers;
|
||||
|
||||
#endif
|
||||
|
||||
/* static */ void InspectorNetworkReporter::reportRequestStart(
|
||||
const jni::alias_ref<jclass> /*unused*/,
|
||||
jint requestId,
|
||||
jni::alias_ref<jstring> requestUrl,
|
||||
jni::alias_ref<jstring> requestMethod,
|
||||
jni::alias_ref<jni::JMap<jstring, jstring>> requestHeaders,
|
||||
jni::alias_ref<jstring> requestBody,
|
||||
jlong encodedDataLength) {
|
||||
RequestInfo requestInfo;
|
||||
requestInfo.url = requestUrl->toStdString();
|
||||
requestInfo.httpMethod = requestMethod->toStdString();
|
||||
requestInfo.headers = convertJavaMapToHeaders(requestHeaders);
|
||||
requestInfo.httpBody = limitRequestBodySize(requestBody->toStdString());
|
||||
|
||||
NetworkReporter::getInstance().reportRequestStart(
|
||||
std::to_string(requestId), requestInfo, encodedDataLength, std::nullopt);
|
||||
}
|
||||
|
||||
/* static */ void InspectorNetworkReporter::reportConnectionTiming(
|
||||
jni::alias_ref<jclass> /*unused*/,
|
||||
jint requestId,
|
||||
jni::alias_ref<jni::JMap<jstring, jstring>> headers) {
|
||||
NetworkReporter::getInstance().reportConnectionTiming(
|
||||
std::to_string(requestId), convertJavaMapToHeaders(headers));
|
||||
}
|
||||
|
||||
/* static */ void InspectorNetworkReporter::reportResponseStart(
|
||||
jni::alias_ref<jclass> /*unused*/,
|
||||
jint requestId,
|
||||
jni::alias_ref<jstring> requestUrl,
|
||||
jint responseStatus,
|
||||
jni::alias_ref<jni::JMap<jstring, jstring>> responseHeaders,
|
||||
jlong encodedDataLength) {
|
||||
ResponseInfo responseInfo;
|
||||
responseInfo.url = requestUrl->toStdString();
|
||||
responseInfo.statusCode = responseStatus;
|
||||
responseInfo.headers = convertJavaMapToHeaders(responseHeaders);
|
||||
|
||||
NetworkReporter::getInstance().reportResponseStart(
|
||||
std::to_string(requestId),
|
||||
responseInfo,
|
||||
static_cast<std::int64_t>(encodedDataLength));
|
||||
}
|
||||
|
||||
/* static */ void InspectorNetworkReporter::reportDataReceived(
|
||||
jni::alias_ref<jclass> /*unused*/,
|
||||
jint requestId,
|
||||
jint dataLength) {
|
||||
NetworkReporter::getInstance().reportDataReceived(
|
||||
std::to_string(requestId), dataLength, std::nullopt);
|
||||
}
|
||||
|
||||
/* static */ void InspectorNetworkReporter::reportResponseEnd(
|
||||
jni::alias_ref<jclass> /*unused*/,
|
||||
jint requestId,
|
||||
jlong encodedDataLength) {
|
||||
NetworkReporter::getInstance().reportResponseEnd(
|
||||
std::to_string(requestId), static_cast<std::int64_t>(encodedDataLength));
|
||||
|
||||
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
|
||||
// Debug build: Check for buffered response body and flush to NetworkReporter
|
||||
auto buffer = responseBuffers[requestId];
|
||||
if (!buffer.empty()) {
|
||||
NetworkReporter::getInstance().storeResponseBody(
|
||||
std::to_string(requestId), buffer, false);
|
||||
responseBuffers.erase(requestId);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* static */ void InspectorNetworkReporter::maybeStoreResponseBody(
|
||||
jni::alias_ref<jclass> /*unused*/,
|
||||
jint requestId,
|
||||
jni::alias_ref<jstring> body,
|
||||
jboolean base64Encoded) {
|
||||
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
|
||||
// Debug build: Process response body and report to NetworkReporter
|
||||
auto& networkReporter = NetworkReporter::getInstance();
|
||||
if (!networkReporter.isDebuggingEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
networkReporter.storeResponseBody(
|
||||
std::to_string(requestId), body->toStdString(), base64Encoded != 0u);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* static */ void InspectorNetworkReporter::maybeStoreResponseBodyIncremental(
|
||||
jni::alias_ref<jclass> /*unused*/,
|
||||
jint requestId,
|
||||
jni::alias_ref<jstring> data) {
|
||||
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
|
||||
// Debug build: Buffer incremental response body contents
|
||||
auto& networkReporter = NetworkReporter::getInstance();
|
||||
if (!networkReporter.isDebuggingEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto& buffer = responseBuffers[requestId];
|
||||
buffer += data->toStdString();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* static */ void InspectorNetworkReporter::registerNatives() {
|
||||
javaClassLocal()->registerNatives({
|
||||
makeNativeMethod(
|
||||
"reportRequestStart", InspectorNetworkReporter::reportRequestStart),
|
||||
makeNativeMethod(
|
||||
"reportResponseStart", InspectorNetworkReporter::reportResponseStart),
|
||||
makeNativeMethod(
|
||||
"reportConnectionTiming",
|
||||
InspectorNetworkReporter::reportConnectionTiming),
|
||||
makeNativeMethod(
|
||||
"reportDataReceived", InspectorNetworkReporter::reportDataReceived),
|
||||
makeNativeMethod(
|
||||
"reportResponseEnd", InspectorNetworkReporter::reportResponseEnd),
|
||||
makeNativeMethod(
|
||||
"maybeStoreResponseBody",
|
||||
InspectorNetworkReporter::maybeStoreResponseBody),
|
||||
makeNativeMethod(
|
||||
"maybeStoreResponseBodyIncremental",
|
||||
InspectorNetworkReporter::maybeStoreResponseBodyIncremental),
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace facebook::react
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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 <fbjni/fbjni.h>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
class InspectorNetworkReporter
|
||||
: public jni::HybridClass<InspectorNetworkReporter> {
|
||||
public:
|
||||
static constexpr auto kJavaDescriptor =
|
||||
"Lcom/facebook/react/modules/network/InspectorNetworkReporter;";
|
||||
|
||||
static void reportRequestStart(
|
||||
jni::alias_ref<jclass> /*unused*/,
|
||||
jint requestId,
|
||||
jni::alias_ref<jstring> requestUrl,
|
||||
jni::alias_ref<jstring> requestMethod,
|
||||
jni::alias_ref<jni::JMap<jstring, jstring>> requestHeaders,
|
||||
jni::alias_ref<jstring> requestBody,
|
||||
jlong encodedDataLength);
|
||||
|
||||
static void reportConnectionTiming(
|
||||
jni::alias_ref<jclass> /*unused*/,
|
||||
jint requestId,
|
||||
jni::alias_ref<jni::JMap<jstring, jstring>> headers);
|
||||
|
||||
static void reportResponseStart(
|
||||
jni::alias_ref<jclass> /*unused*/,
|
||||
jint requestId,
|
||||
jni::alias_ref<jstring> requestUrl,
|
||||
jint responseStatus,
|
||||
jni::alias_ref<jni::JMap<jstring, jstring>> responseHeaders,
|
||||
jlong encodedDataLength);
|
||||
|
||||
static void reportDataReceived(
|
||||
jni::alias_ref<jclass> /*unused*/,
|
||||
jint requestId,
|
||||
jint dataLength);
|
||||
|
||||
static void reportResponseEnd(
|
||||
jni::alias_ref<jclass> /*unused*/,
|
||||
jint requestId,
|
||||
jlong encodedDataLength);
|
||||
|
||||
static void maybeStoreResponseBody(
|
||||
jni::alias_ref<jclass> /*unused*/,
|
||||
jint requestId,
|
||||
jni::alias_ref<jstring> body,
|
||||
jboolean base64Encoded);
|
||||
|
||||
static void maybeStoreResponseBodyIncremental(
|
||||
jni::alias_ref<jclass> /*unused*/,
|
||||
jint requestId,
|
||||
jni::alias_ref<jstring> data);
|
||||
|
||||
static void registerNatives();
|
||||
|
||||
private:
|
||||
InspectorNetworkReporter() = delete;
|
||||
};
|
||||
|
||||
} // namespace facebook::react
|
||||
@@ -21,6 +21,10 @@ class NativeArray : public jni::HybridClass<NativeArray> {
|
||||
|
||||
jni::local_ref<jstring> toString();
|
||||
|
||||
const folly::dynamic& getArray() const {
|
||||
return array_;
|
||||
}
|
||||
|
||||
RN_EXPORT folly::dynamic consume();
|
||||
|
||||
// Whether this array has been added to another array or map and no longer
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "JReactMarker.h"
|
||||
#include "NativeArray.h"
|
||||
#include "NativeMap.h"
|
||||
#include "TransformHelper.h"
|
||||
#include "WritableNativeArray.h"
|
||||
#include "WritableNativeMap.h"
|
||||
|
||||
@@ -27,6 +28,7 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
|
||||
ReadableNativeMap::registerNatives();
|
||||
WritableNativeArray::registerNatives();
|
||||
WritableNativeMap::registerNatives();
|
||||
TransformHelper::registerNatives();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <glog/logging.h>
|
||||
|
||||
#include <fb/glog_init.h>
|
||||
@@ -14,6 +12,7 @@
|
||||
|
||||
#include "CatalystInstanceImpl.h"
|
||||
#include "CxxModuleWrapperBase.h"
|
||||
#include "InspectorNetworkReporter.h"
|
||||
#include "InspectorNetworkRequestListener.h"
|
||||
#include "JInspector.h"
|
||||
#include "JavaScriptExecutorHolder.h"
|
||||
@@ -46,6 +45,7 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
|
||||
JInspector::registerNatives();
|
||||
ReactInstanceManagerInspectorTarget::registerNatives();
|
||||
InspectorNetworkRequestListener::registerNatives();
|
||||
InspectorNetworkReporter::registerNatives();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -40,10 +40,16 @@ local_ref<JArrayClass<jobject>> ReadableNativeArray::importTypeArray() {
|
||||
return jarray;
|
||||
}
|
||||
|
||||
bool ReadableNativeArray::equals(
|
||||
jni::alias_ref<ReadableNativeArray::javaobject> other) {
|
||||
return array_ == other->cthis()->array_;
|
||||
}
|
||||
|
||||
void ReadableNativeArray::registerNatives() {
|
||||
registerHybrid({
|
||||
makeNativeMethod("importArray", ReadableNativeArray::importArray),
|
||||
makeNativeMethod("importTypeArray", ReadableNativeArray::importTypeArray),
|
||||
makeNativeMethod("nativeEquals", ReadableNativeArray::equals),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ class ReadableNativeArray
|
||||
static void mapException(std::exception_ptr ex);
|
||||
static void registerNatives();
|
||||
|
||||
bool equals(jni::alias_ref<ReadableNativeArray::javaobject> other);
|
||||
jni::local_ref<jni::JArrayClass<jobject>> importArray();
|
||||
jni::local_ref<jni::JArrayClass<jobject>> importTypeArray();
|
||||
};
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "TransformHelper.h"
|
||||
|
||||
#include <react/renderer/components/view/BaseViewProps.h>
|
||||
#include <react/renderer/components/view/conversions.h>
|
||||
|
||||
#include "NativeArray.h"
|
||||
|
||||
using namespace facebook::jni;
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
namespace {
|
||||
void processTransform(
|
||||
jni::alias_ref<jclass> /*unused*/,
|
||||
NativeArray* jTransforms,
|
||||
jni::alias_ref<jni::JArrayDouble> jResult,
|
||||
float viewWidth,
|
||||
float viewHeight,
|
||||
NativeArray* jTransformOrigin) {
|
||||
// Assuming parsing transforms doesn't require a real PropsParserContext
|
||||
static ContextContainer contextContainer;
|
||||
static PropsParserContext context(0, contextContainer);
|
||||
|
||||
RawValue transformValue(jTransforms->getArray());
|
||||
Transform transform;
|
||||
fromRawValue(context, transformValue, transform);
|
||||
|
||||
TransformOrigin transformOrigin;
|
||||
if (jTransformOrigin != nullptr) {
|
||||
RawValue transformOriginValue(jTransformOrigin->getArray());
|
||||
fromRawValue(context, transformOriginValue, transformOrigin);
|
||||
}
|
||||
|
||||
auto result = BaseViewProps::resolveTransform(
|
||||
Size(viewWidth, viewHeight), transform, transformOrigin);
|
||||
|
||||
// Convert from matrix of floats to double matrix
|
||||
constexpr size_t MatrixSize = std::tuple_size_v<decltype(result.matrix)>;
|
||||
std::array<double, MatrixSize> doubleTransform{};
|
||||
std::copy(
|
||||
result.matrix.begin(), result.matrix.end(), doubleTransform.begin());
|
||||
jResult->setRegion(0, MatrixSize, doubleTransform.data());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void TransformHelper::registerNatives() {
|
||||
javaClassLocal()->registerNatives({
|
||||
makeNativeMethod("nativeProcessTransform", processTransform),
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace facebook::react
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* 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 <fbjni/fbjni.h>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
class TransformHelper : public jni::JavaClass<TransformHelper> {
|
||||
public:
|
||||
static auto constexpr* kJavaDescriptor =
|
||||
"Lcom/facebook/react/uimanager/TransformHelper;";
|
||||
|
||||
static void registerNatives();
|
||||
};
|
||||
|
||||
} // namespace facebook::react
|
||||
+62
-21
@@ -11,9 +11,17 @@ import com.facebook.react.bridge.Arguments
|
||||
import com.facebook.react.bridge.ReactApplicationContext
|
||||
import com.facebook.react.bridge.WritableArray
|
||||
import com.facebook.react.bridge.WritableMap
|
||||
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags
|
||||
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlagsDefaults
|
||||
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlagsForTests
|
||||
import com.facebook.testutils.shadows.ShadowArguments
|
||||
import java.net.SocketTimeoutException
|
||||
import okhttp3.Headers
|
||||
import okhttp3.Protocol
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
@@ -27,12 +35,23 @@ import org.robolectric.annotation.Config
|
||||
|
||||
@Config(shadows = [ShadowArguments::class])
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
class ResponseUtilTest {
|
||||
class NetworkEventUtilTest {
|
||||
private lateinit var reactContext: ReactApplicationContext
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
reactContext = mock()
|
||||
|
||||
ReactNativeFeatureFlagsForTests.setUp()
|
||||
ReactNativeFeatureFlags.override(
|
||||
object : ReactNativeFeatureFlagsDefaults() {
|
||||
override fun enableNetworkEventReporting(): Boolean = false
|
||||
})
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
ReactNativeFeatureFlags.dangerouslyReset()
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -41,7 +60,7 @@ class ResponseUtilTest {
|
||||
val progress = 100L
|
||||
val total = 1000L
|
||||
|
||||
ResponseUtil.onDataSend(reactContext, requestId, progress, total)
|
||||
NetworkEventUtil.onDataSend(reactContext, requestId, progress, total)
|
||||
|
||||
val eventNameCaptor = ArgumentCaptor.forClass(String::class.java)
|
||||
val eventArgumentsCaptor = ArgumentCaptor.forClass(WritableArray::class.java)
|
||||
@@ -64,7 +83,7 @@ class ResponseUtilTest {
|
||||
val progress = 100L
|
||||
val total = 1000L
|
||||
|
||||
ResponseUtil.onIncrementalDataReceived(reactContext, requestId, data, progress, total)
|
||||
NetworkEventUtil.onIncrementalDataReceived(reactContext, requestId, data, progress, total)
|
||||
|
||||
val eventNameCaptor = ArgumentCaptor.forClass(String::class.java)
|
||||
val eventArgumentsCaptor = ArgumentCaptor.forClass(WritableArray::class.java)
|
||||
@@ -87,7 +106,7 @@ class ResponseUtilTest {
|
||||
val progress = 500L
|
||||
val total = 1000L
|
||||
|
||||
ResponseUtil.onDataReceivedProgress(reactContext, requestId, progress, total)
|
||||
NetworkEventUtil.onDataReceivedProgress(reactContext, requestId, progress, total)
|
||||
|
||||
val eventNameCaptor = ArgumentCaptor.forClass(String::class.java)
|
||||
val eventArgumentsCaptor = ArgumentCaptor.forClass(WritableArray::class.java)
|
||||
@@ -108,7 +127,7 @@ class ResponseUtilTest {
|
||||
val requestId = 1
|
||||
val data = "response data"
|
||||
|
||||
ResponseUtil.onDataReceived(reactContext, requestId, data)
|
||||
NetworkEventUtil.onDataReceived(reactContext, requestId, data, "string")
|
||||
|
||||
val eventNameCaptor = ArgumentCaptor.forClass(String::class.java)
|
||||
val eventArgumentsCaptor = ArgumentCaptor.forClass(WritableArray::class.java)
|
||||
@@ -128,7 +147,7 @@ class ResponseUtilTest {
|
||||
val requestId = 1
|
||||
val data: WritableMap = Arguments.createMap().apply { putString("key", "value") }
|
||||
|
||||
ResponseUtil.onDataReceived(reactContext, requestId, data)
|
||||
NetworkEventUtil.onDataReceived(reactContext, requestId, data, ByteArray(0))
|
||||
|
||||
val eventNameCaptor = ArgumentCaptor.forClass(String::class.java)
|
||||
val eventArgumentsCaptor = ArgumentCaptor.forClass(WritableArray::class.java)
|
||||
@@ -149,7 +168,7 @@ class ResponseUtilTest {
|
||||
val error = "An error occurred"
|
||||
val e: Throwable? = null
|
||||
|
||||
ResponseUtil.onRequestError(reactContext, requestId, error, e)
|
||||
NetworkEventUtil.onRequestError(reactContext, requestId, error, e)
|
||||
|
||||
val eventNameCaptor = ArgumentCaptor.forClass(String::class.java)
|
||||
val eventArgumentsCaptor = ArgumentCaptor.forClass(WritableArray::class.java)
|
||||
@@ -170,7 +189,7 @@ class ResponseUtilTest {
|
||||
val error = "Timeout error"
|
||||
val e: Throwable = SocketTimeoutException()
|
||||
|
||||
ResponseUtil.onRequestError(reactContext, requestId, error, e)
|
||||
NetworkEventUtil.onRequestError(reactContext, requestId, error, e)
|
||||
|
||||
val eventNameCaptor = ArgumentCaptor.forClass(String::class.java)
|
||||
val eventArgumentsCaptor = ArgumentCaptor.forClass(WritableArray::class.java)
|
||||
@@ -190,7 +209,7 @@ class ResponseUtilTest {
|
||||
fun testOnRequestSuccess() {
|
||||
val requestId = 1
|
||||
|
||||
ResponseUtil.onRequestSuccess(reactContext, requestId)
|
||||
NetworkEventUtil.onRequestSuccess(reactContext, requestId, 128)
|
||||
|
||||
val eventNameCaptor = ArgumentCaptor.forClass(String::class.java)
|
||||
val eventArgumentsCaptor = ArgumentCaptor.forClass(WritableArray::class.java)
|
||||
@@ -209,11 +228,19 @@ class ResponseUtilTest {
|
||||
fun testOnResponseReceived() {
|
||||
val requestId = 1
|
||||
val statusCode = 200
|
||||
val headers: WritableMap =
|
||||
Arguments.createMap().apply { putString("Content-Type", "application/json") }
|
||||
val headers = Headers.Builder().add("Content-Type", "application/json").build()
|
||||
val url = "http://example.com"
|
||||
|
||||
ResponseUtil.onResponseReceived(reactContext, requestId, statusCode, headers, url)
|
||||
val request = Request.Builder().url(url).build()
|
||||
val response =
|
||||
Response.Builder()
|
||||
.protocol(Protocol.HTTP_1_1)
|
||||
.request(request)
|
||||
.headers(headers)
|
||||
.code(statusCode)
|
||||
.message("OK")
|
||||
.build()
|
||||
NetworkEventUtil.onResponseReceived(reactContext, requestId, url, response)
|
||||
|
||||
val eventNameCaptor = ArgumentCaptor.forClass(String::class.java)
|
||||
val eventArgumentsCaptor = ArgumentCaptor.forClass(WritableArray::class.java)
|
||||
@@ -222,24 +249,38 @@ class ResponseUtilTest {
|
||||
|
||||
assertThat(eventNameCaptor.value).isEqualTo("didReceiveNetworkResponse")
|
||||
|
||||
val expectedHeadersMap: WritableMap =
|
||||
Arguments.createMap().apply { putString("Content-Type", "application/json") }
|
||||
|
||||
val args = eventArgumentsCaptor.value
|
||||
assertThat(args.size()).isEqualTo(4)
|
||||
assertThat(args.getInt(0)).isEqualTo(requestId)
|
||||
assertThat(args.getInt(1)).isEqualTo(statusCode)
|
||||
assertThat(args.getMap(2)).isEqualTo(headers)
|
||||
assertThat(args.getMap(2)).isEqualTo(expectedHeadersMap)
|
||||
assertThat(args.getString(3)).isEqualTo(url)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testNullReactContext() {
|
||||
ResponseUtil.onDataSend(null, 1, 100, 1000)
|
||||
ResponseUtil.onIncrementalDataReceived(null, 1, "data", 100, 1000)
|
||||
ResponseUtil.onDataReceivedProgress(null, 1, 100, 1000)
|
||||
ResponseUtil.onDataReceived(null, 1, "data")
|
||||
ResponseUtil.onDataReceived(null, 1, Arguments.createMap())
|
||||
ResponseUtil.onRequestError(null, 1, "error", null)
|
||||
ResponseUtil.onRequestSuccess(null, 1)
|
||||
ResponseUtil.onResponseReceived(null, 1, 200, Arguments.createMap(), "http://example.com")
|
||||
val url = "http://example.com"
|
||||
val request = Request.Builder().url(url).build()
|
||||
val response =
|
||||
Response.Builder()
|
||||
.protocol(Protocol.HTTP_1_1)
|
||||
.request(request)
|
||||
.headers(Headers.Builder().build())
|
||||
.code(200)
|
||||
.message("OK")
|
||||
.build()
|
||||
|
||||
NetworkEventUtil.onDataSend(null, 1, 100, 1000)
|
||||
NetworkEventUtil.onIncrementalDataReceived(null, 1, "data", 100, 1000)
|
||||
NetworkEventUtil.onDataReceivedProgress(null, 1, 100, 1000)
|
||||
NetworkEventUtil.onDataReceived(null, 1, "data", "string")
|
||||
NetworkEventUtil.onDataReceived(null, 1, Arguments.createMap(), ByteArray(0))
|
||||
NetworkEventUtil.onRequestError(null, 1, "error", null)
|
||||
NetworkEventUtil.onRequestSuccess(null, 1, 0)
|
||||
NetworkEventUtil.onResponseReceived(null, 1, url, response)
|
||||
|
||||
verify(reactContext, never()).emitDeviceEvent(any<String>(), any())
|
||||
}
|
||||
+9
@@ -15,6 +15,9 @@ import com.facebook.react.bridge.JavaOnlyMap
|
||||
import com.facebook.react.bridge.ReactApplicationContext
|
||||
import com.facebook.react.bridge.WritableArray
|
||||
import com.facebook.react.common.network.OkHttpCallUtil
|
||||
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags
|
||||
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlagsDefaults
|
||||
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlagsForTests
|
||||
import com.facebook.testutils.shadows.ShadowArguments
|
||||
import java.io.InputStream
|
||||
import java.nio.charset.StandardCharsets
|
||||
@@ -72,6 +75,12 @@ class NetworkingModuleTest {
|
||||
context = mock()
|
||||
whenever(context.hasActiveReactInstance()).thenReturn(true)
|
||||
|
||||
ReactNativeFeatureFlagsForTests.setUp()
|
||||
ReactNativeFeatureFlags.override(
|
||||
object : ReactNativeFeatureFlagsDefaults() {
|
||||
override fun enableNetworkEventReporting(): Boolean = false
|
||||
})
|
||||
|
||||
networkingModule = NetworkingModule(context, "", httpClient, null)
|
||||
|
||||
okHttpCallUtil = mockStatic(OkHttpCallUtil::class.java)
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace {
|
||||
|
||||
// basename_r isn't in all iOS SDKs, so use this simple version instead.
|
||||
std::string simpleBasename(const std::string& path) {
|
||||
size_t pos = path.rfind("/");
|
||||
size_t pos = path.rfind('/');
|
||||
return (pos != std::string::npos) ? path.substr(pos) : path;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ target_link_libraries(jsinspector
|
||||
jsinspector_tracing
|
||||
react_featureflags
|
||||
runtimeexecutor
|
||||
reactperflogger
|
||||
)
|
||||
target_compile_reactnative_options(jsinspector PRIVATE)
|
||||
target_compile_options(jsinspector PRIVATE
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <jsinspector-modern/RuntimeTarget.h>
|
||||
#include <jsinspector-modern/tracing/PerformanceTracer.h>
|
||||
|
||||
#include <reactperflogger/ReactPerfettoLogger.h>
|
||||
#include <concepts>
|
||||
#include <deque>
|
||||
#include <string>
|
||||
@@ -19,6 +20,20 @@ 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
|
||||
@@ -376,7 +391,8 @@ void consoleTimeStamp(
|
||||
const jsi::Value* arguments,
|
||||
size_t argumentsCount) {
|
||||
auto& performanceTracer = tracing::PerformanceTracer::getInstance();
|
||||
if (!performanceTracer.isTracing() || argumentsCount == 0) {
|
||||
if ((!performanceTracer.isTracing() && !ReactPerfettoLogger::isTracing()) ||
|
||||
argumentsCount == 0) {
|
||||
// If not tracing, just early return to avoid the cost of parsing.
|
||||
return;
|
||||
}
|
||||
@@ -444,8 +460,22 @@ void consoleTimeStamp(
|
||||
}
|
||||
}
|
||||
|
||||
performanceTracer.reportTimeStamp(
|
||||
label, start, end, trackName, trackGroup, color);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#include "HttpUtils.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace facebook::react::jsinspector_modern {
|
||||
|
||||
std::string httpReasonPhrase(uint16_t status) {
|
||||
@@ -147,8 +149,14 @@ std::string httpReasonPhrase(uint16_t status) {
|
||||
std::string mimeTypeFromHeaders(const Headers& headers) {
|
||||
std::string mimeType = "application/octet-stream";
|
||||
|
||||
if (headers.find("Content-Type") != headers.end()) {
|
||||
mimeType = headers.at("Content-Type");
|
||||
for (const auto& [name, value] : headers) {
|
||||
std::string lowerName = name;
|
||||
std::transform(
|
||||
lowerName.begin(), lowerName.end(), lowerName.begin(), ::tolower);
|
||||
if (lowerName == "content-type") {
|
||||
mimeType = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return mimeType;
|
||||
|
||||
@@ -1,21 +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 <string>
|
||||
|
||||
namespace facebook::react::jsinspector_modern {
|
||||
|
||||
/**
|
||||
* https://developer.chrome.com/docs/devtools/performance/extension?utm_source=devtools#devtools_object
|
||||
*/
|
||||
struct DevToolsTrackEntryPayload {
|
||||
std::string track;
|
||||
};
|
||||
|
||||
} // namespace facebook::react::jsinspector_modern
|
||||
@@ -113,7 +113,8 @@ void PerformanceTracer::collectEvents(
|
||||
|
||||
void PerformanceTracer::reportMark(
|
||||
const std::string_view& name,
|
||||
HighResTimeStamp start) {
|
||||
HighResTimeStamp start,
|
||||
folly::dynamic&& detail) {
|
||||
if (!tracingAtomic_) {
|
||||
return;
|
||||
}
|
||||
@@ -123,6 +124,13 @@ void PerformanceTracer::reportMark(
|
||||
return;
|
||||
}
|
||||
|
||||
folly::dynamic eventArgs = folly::dynamic::object();
|
||||
if (detail != nullptr) {
|
||||
eventArgs = folly::dynamic::object(
|
||||
"data",
|
||||
folly::dynamic::object("detail", folly::toJson(std::move(detail))));
|
||||
}
|
||||
|
||||
buffer_.emplace_back(TraceEvent{
|
||||
.name = std::string(name),
|
||||
.cat = "blink.user_timing",
|
||||
@@ -130,6 +138,7 @@ void PerformanceTracer::reportMark(
|
||||
.ts = start,
|
||||
.pid = processId_,
|
||||
.tid = oscompat::getCurrentThreadId(),
|
||||
.args = eventArgs,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -137,18 +146,15 @@ void PerformanceTracer::reportMeasure(
|
||||
const std::string_view& name,
|
||||
HighResTimeStamp start,
|
||||
HighResDuration duration,
|
||||
const std::optional<DevToolsTrackEntryPayload>& trackMetadata) {
|
||||
folly::dynamic&& detail) {
|
||||
if (!tracingAtomic_) {
|
||||
return;
|
||||
}
|
||||
|
||||
folly::dynamic beginEventArgs = folly::dynamic::object();
|
||||
if (trackMetadata.has_value()) {
|
||||
folly::dynamic devtoolsObject = folly::dynamic::object(
|
||||
"devtools",
|
||||
folly::dynamic::object("track", trackMetadata.value().track));
|
||||
if (detail != nullptr) {
|
||||
beginEventArgs =
|
||||
folly::dynamic::object("detail", folly::toJson(devtoolsObject));
|
||||
folly::dynamic::object("detail", folly::toJson(std::move(detail)));
|
||||
}
|
||||
|
||||
auto currentThreadId = oscompat::getCurrentThreadId();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user