mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Compare commits
181
Commits
@@ -37,11 +37,6 @@ ADD scripts /app/scripts
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN scripts/buck/buck_fetch.sh
|
||||
|
||||
RUN buck build packages/react-native/ReactAndroid/src/main/java/com/facebook/react
|
||||
RUN buck build packages/react-native/ReactAndroid/src/main/java/com/facebook/react/shell
|
||||
|
||||
ADD . /app
|
||||
|
||||
RUN yarn
|
||||
|
||||
+36
-66
@@ -46,7 +46,7 @@ references:
|
||||
# Dependency Anchors
|
||||
# -------------------------
|
||||
dependency_versions:
|
||||
xcode_version: &xcode_version "14.2.0"
|
||||
xcode_version: &xcode_version "14.3.0"
|
||||
nodelts_image: &nodelts_image "cimg/node:18.12.1"
|
||||
nodeprevlts_image: &nodeprevlts_image "cimg/node:16.18.1"
|
||||
|
||||
@@ -62,7 +62,8 @@ references:
|
||||
hermes_workspace_cache_key: &hermes_workspace_cache_key v4-hermes-{{ .Environment.CIRCLE_JOB }}-{{ checksum "/tmp/hermes/hermesversion" }}
|
||||
hermes_workspace_debug_cache_key: &hermes_workspace_debug_cache_key v2-hermes-{{ .Environment.CIRCLE_JOB }}-debug-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
|
||||
hermes_workspace_release_cache_key: &hermes_workspace_release_cache_key v2-hermes-{{ .Environment.CIRCLE_JOB }}-release-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
|
||||
hermes_windows_cache_key: &hermes_windows_cache_key v3-hermes-{{ .Environment.CIRCLE_JOB }}-{{ checksum "tmp/hermes/hermesversion" }}
|
||||
hermes_linux_cache_key: &hermes_linux_cache_key v1-hermes-{{ .Environment.CIRCLE_JOB }}-linux-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
|
||||
hermes_windows_cache_key: &hermes_windows_cache_key v2-hermes-{{ .Environment.CIRCLE_JOB }}-windows-{{ checksum "/Users/circleci/project/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
|
||||
hermes_tarball_debug_cache_key: &hermes_tarball_debug_cache_key v4-hermes-tarball-debug-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
|
||||
hermes_tarball_release_cache_key: &hermes_tarball_release_cache_key v3-hermes-tarball-release-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
|
||||
pods_cache_key: &pods_cache_key v8-pods-{{ .Environment.CIRCLE_JOB }}-{{ checksum "packages/rn-tester/Podfile.lock.bak" }}-{{ checksum "packages/rn-tester/Podfile" }}
|
||||
@@ -314,11 +315,24 @@ commands:
|
||||
- run:
|
||||
name: Get React Native version
|
||||
command: |
|
||||
VERSION=$( grep '"version"' packages/react-native/package.json | cut -d '"' -f 4 | head -1)
|
||||
VERSION=$(cat packages/react-native/package.json | jq -r '.version')
|
||||
# Save the react native version we are building in a file so we can use that file as part of the cache key.
|
||||
echo "$VERSION" > /tmp/react-native-version
|
||||
echo "React Native Version is $(cat /tmp/react-native-version)"
|
||||
echo "Hermes commit is $(cat /tmp/hermes/hermesversion)"
|
||||
HERMES_VERSION="$(cat /tmp/hermes/hermesversion)"
|
||||
echo "Hermes commit is $HERMES_VERSION"
|
||||
|
||||
get_react_native_version_windows:
|
||||
steps:
|
||||
- run:
|
||||
name: Get React Native version on Windows
|
||||
command: |
|
||||
$VERSION=cat packages/react-native/package.json | jq -r '.version'
|
||||
# Save the react native version we are building in a file so we can use that file as part of the cache key.
|
||||
echo "$VERSION" > /tmp/react-native-version
|
||||
echo "React Native Version is $(cat /tmp/react-native-version)"
|
||||
$HERMES_VERSION=cat C:\Users\circleci\project\tmp\hermes\hermesversion
|
||||
echo "Hermes commit is $HERMES_VERSION"
|
||||
|
||||
with_hermes_tarball_cache_span:
|
||||
parameters:
|
||||
@@ -620,7 +634,7 @@ jobs:
|
||||
- run:
|
||||
name: Run Ruby Tests
|
||||
command: |
|
||||
cd scripts
|
||||
cd packages/react-native/scripts
|
||||
sh run_ruby_tests.sh
|
||||
- run_yarn
|
||||
- *attach_hermes_workspace
|
||||
@@ -719,60 +733,6 @@ jobs:
|
||||
- store_test_results:
|
||||
path: ./reports/junit
|
||||
|
||||
# -------------------------
|
||||
# JOBS: Test Buck
|
||||
# -------------------------
|
||||
test_buck:
|
||||
executor: reactnativeandroid
|
||||
environment:
|
||||
KOTLIN_HOME=packages/react-native/third-party/kotlin
|
||||
steps:
|
||||
- checkout
|
||||
- setup_artifacts
|
||||
- run_yarn
|
||||
|
||||
- run:
|
||||
name: Download Dependencies Using Buck
|
||||
command: ./scripts/buck/buck_fetch.sh
|
||||
|
||||
- run:
|
||||
name: Build & Test React Native using Buck
|
||||
command: |
|
||||
buck build packages/react-native/ReactAndroid/src/main/java/com/facebook/react
|
||||
buck build packages/react-native/ReactAndroid/src/main/java/com/facebook/react/shell
|
||||
|
||||
- run:
|
||||
name: Run Tests - Android Unit Tests with Buck
|
||||
command: buck test packages/react-native/ReactAndroid/src/test/... --config build.threads=$BUILD_THREADS --xml ./reports/buck/all-results-raw.xml
|
||||
|
||||
- run:
|
||||
name: Build JavaScript Bundle for instrumentation tests
|
||||
working_directory: ~/react-native/packages/react-native
|
||||
command: node cli.js bundle --max-workers 2 --platform android --dev true --entry-file ReactAndroid/src/androidTest/js/TestBundle.js --bundle-output ReactAndroid/src/androidTest/assets/AndroidTestBundle.js
|
||||
|
||||
- run:
|
||||
name: Build Tests - Android Instrumentation Tests with Buck
|
||||
# Here, just build the instrumentation tests. There is a known issue with installing the APK to android-21+ emulator.
|
||||
command: |
|
||||
if [[ ! -e packages/react-native/ReactAndroid/src/androidTest/assets/AndroidTestBundle.js ]]; then
|
||||
echo "JavaScript bundle missing, cannot run instrumentation tests. Verify Build JavaScript Bundle step completed successfully."; exit 1;
|
||||
fi
|
||||
source scripts/android-setup.sh && NO_BUCKD=1 scripts/retry3 timeout 300 buck build packages/react-native/ReactAndroid/src/androidTest/buck-runner:instrumentation-tests --config build.threads=$BUILD_THREADS
|
||||
|
||||
- run:
|
||||
name: Collect Test Results
|
||||
command: |
|
||||
find . -type f -regex ".*/build/test-results/debug/.*xml" -exec cp {} ./reports/build/ \;
|
||||
find . -type f -regex ".*/outputs/androidTest-results/connected/.*xml" -exec cp {} ./reports/outputs/ \;
|
||||
find . -type f -regex ".*/buck-out/gen/packages/react-native/ReactAndroid/src/test/.*/.*xml" -exec cp {} ./reports/buck/ \;
|
||||
if [ -f ~/react-native/reports/buck/all-results-raw.xml ]; then
|
||||
~/react-native/scripts/circleci/buckToJunit/buckToJunit.sh ~/react-native/reports/buck/all-results-raw.xml ~/react-native/reports/junit/results.xml
|
||||
fi
|
||||
when: always
|
||||
|
||||
- store_test_results:
|
||||
path: ./reports/junit
|
||||
|
||||
# -------------------------
|
||||
# JOBS: Test Android
|
||||
# -------------------------
|
||||
@@ -1086,9 +1046,15 @@ jobs:
|
||||
name: Enable Yarn with corepack
|
||||
command: corepack enable
|
||||
|
||||
# it looks like that, last week, envinfo released version 7.9.0 which does not works
|
||||
# with Windows. I have opened an issue here: https://github.com/tabrindle/envinfo/issues/238
|
||||
# TODO: T156811874 - Revert this to npx envinfo@latest when the issue is addressed
|
||||
- run:
|
||||
name: Display Environment info
|
||||
command: npx envinfo@latest
|
||||
command: |
|
||||
npm install -g envinfo
|
||||
envinfo -v
|
||||
envinfo
|
||||
|
||||
- restore_cache:
|
||||
keys:
|
||||
@@ -1175,7 +1141,7 @@ jobs:
|
||||
- image: debian:11
|
||||
environment:
|
||||
- HERMES_WS_DIR: *hermes_workspace_root
|
||||
- HERMES_VERSION_FILE: "sdks/.hermesversion"
|
||||
- HERMES_VERSION_FILE: "packages/react-native/sdks/.hermesversion"
|
||||
- BUILD_FROM_SOURCE: true
|
||||
steps:
|
||||
- run:
|
||||
@@ -1194,8 +1160,10 @@ jobs:
|
||||
mkdir -p "/tmp/hermes" "/tmp/hermes/download" "/tmp/hermes/hermes"
|
||||
|
||||
if [ -f "$HERMES_VERSION_FILE" ]; then
|
||||
echo "Hermes version file found. Using the latest commit"
|
||||
cat $HERMES_VERSION_FILE > /tmp/hermes/hermesversion
|
||||
else
|
||||
echo "No hermes version file found. Using the latest commit"
|
||||
HERMES_TAG_SHA=$(git ls-remote https://github.com/facebook/hermes main | cut -f 1 | tr -d '[:space:]')
|
||||
echo $HERMES_TAG_SHA > /tmp/hermes/hermesversion
|
||||
fi
|
||||
@@ -1226,17 +1194,18 @@ jobs:
|
||||
docker:
|
||||
- image: debian:bullseye
|
||||
resource_class: "xlarge"
|
||||
working_directory: /root
|
||||
steps:
|
||||
- checkout_code_with_cache
|
||||
- run:
|
||||
name: Install dependencies
|
||||
command: |
|
||||
apt update
|
||||
apt install -y git openssh-client cmake build-essential \
|
||||
libreadline-dev libicu-dev zip python3
|
||||
libreadline-dev libicu-dev jq zip python3
|
||||
- *attach_hermes_workspace
|
||||
- get_react_native_version
|
||||
- restore_cache:
|
||||
key: *hermes_workspace_cache_key
|
||||
key: *hermes_linux_cache_key
|
||||
- run:
|
||||
name: Set up workspace
|
||||
command: |
|
||||
@@ -1255,7 +1224,7 @@ jobs:
|
||||
cp /tmp/hermes/build/bin/hermesc /tmp/hermes/linux64-bin/.
|
||||
fi
|
||||
- save_cache:
|
||||
key: *hermes_workspace_cache_key
|
||||
key: *hermes_linux_cache_key
|
||||
paths:
|
||||
- /tmp/hermes/linux64-bin/
|
||||
- /tmp/hermes/hermes/destroot/
|
||||
@@ -1376,7 +1345,9 @@ jobs:
|
||||
- MSBUILD_DIR: 'C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin'
|
||||
- CMAKE_DIR: 'C:\Program Files\CMake\bin'
|
||||
steps:
|
||||
- checkout_code_with_cache
|
||||
- *attach_hermes_workspace
|
||||
- get_react_native_version_windows
|
||||
- restore_cache:
|
||||
key: *hermes_windows_cache_key
|
||||
- run:
|
||||
@@ -1694,7 +1665,6 @@ workflows:
|
||||
architecture: ["NewArch", "OldArch"]
|
||||
jsengine: ["Hermes", "JSC"]
|
||||
flavor: ["Debug", "Release"]
|
||||
- test_buck
|
||||
- test_ios_template:
|
||||
requires:
|
||||
- build_npm_package
|
||||
|
||||
+9
-9
@@ -3,22 +3,22 @@ GEM
|
||||
specs:
|
||||
CFPropertyList (3.0.6)
|
||||
rexml
|
||||
activesupport (7.0.4.2)
|
||||
activesupport (7.0.6)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
i18n (>= 1.6, < 2)
|
||||
minitest (>= 5.1)
|
||||
tzinfo (~> 2.0)
|
||||
addressable (2.8.1)
|
||||
addressable (2.8.4)
|
||||
public_suffix (>= 2.0.2, < 6.0)
|
||||
algoliasearch (1.27.5)
|
||||
httpclient (~> 2.8, >= 2.8.3)
|
||||
json (>= 1.5.1)
|
||||
atomos (0.1.3)
|
||||
claide (1.1.0)
|
||||
cocoapods (1.12.0)
|
||||
cocoapods (1.12.1)
|
||||
addressable (~> 2.8)
|
||||
claide (>= 1.0.2, < 2.0)
|
||||
cocoapods-core (= 1.12.0)
|
||||
cocoapods-core (= 1.12.1)
|
||||
cocoapods-deintegrate (>= 1.0.3, < 2.0)
|
||||
cocoapods-downloader (>= 1.6.0, < 2.0)
|
||||
cocoapods-plugins (>= 1.0.0, < 2.0)
|
||||
@@ -33,7 +33,7 @@ GEM
|
||||
nap (~> 1.0)
|
||||
ruby-macho (>= 2.3.0, < 3.0)
|
||||
xcodeproj (>= 1.21.0, < 2.0)
|
||||
cocoapods-core (1.12.0)
|
||||
cocoapods-core (1.12.1)
|
||||
activesupport (>= 5.0, < 8)
|
||||
addressable (~> 2.8)
|
||||
algoliasearch (~> 1.0)
|
||||
@@ -62,10 +62,10 @@ GEM
|
||||
fuzzy_match (2.0.4)
|
||||
gh_inspector (1.1.3)
|
||||
httpclient (2.8.3)
|
||||
i18n (1.12.0)
|
||||
i18n (1.14.1)
|
||||
concurrent-ruby (~> 1.0)
|
||||
json (2.6.3)
|
||||
minitest (5.18.0)
|
||||
minitest (5.18.1)
|
||||
molinillo (0.8.0)
|
||||
nanaimo (0.3.0)
|
||||
nap (1.1.0)
|
||||
@@ -93,7 +93,7 @@ DEPENDENCIES
|
||||
cocoapods (~> 1.12)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.2.0p0
|
||||
ruby 3.0.6p216
|
||||
|
||||
BUNDLED WITH
|
||||
2.4.7
|
||||
2.4.13
|
||||
|
||||
+8
-8
@@ -40,8 +40,7 @@
|
||||
"test-ios": "./scripts/objc-test.sh test",
|
||||
"test-typescript": "dtslint packages/react-native/types",
|
||||
"test-typescript-offline": "dtslint --localTs node_modules/typescript/lib packages/react-native/types",
|
||||
"bump-all-updated-packages": "node ./scripts/monorepo/bump-all-updated-packages",
|
||||
"align-package-versions": "node ./scripts/monorepo/align-package-versions.js"
|
||||
"bump-all-updated-packages": "node ./scripts/monorepo/bump-all-updated-packages"
|
||||
},
|
||||
"workspaces": [
|
||||
"packages/*"
|
||||
@@ -51,16 +50,17 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.20.0",
|
||||
"@babel/eslint-parser": "^7.19.0",
|
||||
"@babel/eslint-parser": "^7.20.0",
|
||||
"@babel/generator": "^7.20.0",
|
||||
"@babel/plugin-transform-regenerator": "^7.0.0",
|
||||
"@babel/plugin-transform-regenerator": "^7.20.0",
|
||||
"@definitelytyped/dtslint": "^0.0.127",
|
||||
"@jest/create-cache-key-function": "^29.2.1",
|
||||
"@reactions/component": "^2.0.2",
|
||||
"@react-native/metro-config": "^0.72.9",
|
||||
"@types/react": "^18.0.18",
|
||||
"@typescript-eslint/parser": "^5.30.5",
|
||||
"async": "^3.2.2",
|
||||
"babel-plugin-transform-flow-enums":"^0.0.2",
|
||||
"babel-plugin-transform-flow-enums": "^0.0.2",
|
||||
"clang-format": "^1.8.0",
|
||||
"connect": "^3.6.5",
|
||||
"coveralls": "^3.1.1",
|
||||
@@ -84,9 +84,9 @@
|
||||
"jest": "^29.2.1",
|
||||
"jest-junit": "^10.0.0",
|
||||
"jscodeshift": "^0.14.0",
|
||||
"metro-babel-register": "0.75.1",
|
||||
"metro-memory-fs": "0.75.1",
|
||||
"metro-react-native-babel-transformer": "0.75.1",
|
||||
"metro-babel-register": "0.76.7",
|
||||
"metro-memory-fs": "0.76.7",
|
||||
"metro-react-native-babel-transformer": "0.76.7",
|
||||
"mkdirp": "^0.5.1",
|
||||
"mock-fs": "^5.1.4",
|
||||
"prettier": "^2.4.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/eslint-config",
|
||||
"version": "0.72.1",
|
||||
"version": "0.72.2",
|
||||
"description": "ESLint config for React Native",
|
||||
"main": "index.js",
|
||||
"license": "MIT",
|
||||
@@ -12,7 +12,7 @@
|
||||
"homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/eslint-config-react-native-community#readme",
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.20.0",
|
||||
"@babel/eslint-parser": "^7.19.0",
|
||||
"@babel/eslint-parser": "^7.20.0",
|
||||
"@react-native/eslint-plugin": "^0.72.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.30.5",
|
||||
"@typescript-eslint/parser": "^5.30.5",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/eslint-plugin-specs",
|
||||
"version": "0.72.2",
|
||||
"version": "0.72.4",
|
||||
"description": "ESLint rules to validate NativeModule and Component Specs",
|
||||
"main": "index.js",
|
||||
"repository": {
|
||||
@@ -14,11 +14,11 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.20.0",
|
||||
"@babel/eslint-parser": "^7.19.0",
|
||||
"@babel/plugin-transform-flow-strip-types": "^7.0.0",
|
||||
"@babel/preset-flow": "^7.18.0",
|
||||
"@babel/eslint-parser": "^7.20.0",
|
||||
"@babel/plugin-transform-flow-strip-types": "^7.20.0",
|
||||
"@babel/preset-flow": "^7.20.0",
|
||||
"@react-native/codegen": "*",
|
||||
"flow-parser": "^0.185.0",
|
||||
"flow-parser": "^0.206.0",
|
||||
"make-dir": "^2.1.0",
|
||||
"pirates": "^4.0.1",
|
||||
"source-map-support": "0.5.0"
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
"yargs": "^17.6.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.19.0",
|
||||
"@babel/cli": "^7.20.0",
|
||||
"@babel/core": "^7.20.0",
|
||||
"@babel/preset-env": "^7.20.0",
|
||||
"@babel/preset-flow": "^7.18.0",
|
||||
"@babel/preset-flow": "^7.20.0",
|
||||
"jest": "^29.2.1"
|
||||
},
|
||||
"jest": {
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
* @noformat
|
||||
*/
|
||||
|
||||
/*:: import type {ConfigT} from 'metro-config'; */
|
||||
|
||||
const {getDefaultConfig: getBaseConfig, mergeConfig} = require('metro-config');
|
||||
|
||||
const INTERNAL_CALLSITES_REGEX = new RegExp(
|
||||
[
|
||||
'/Libraries/Renderer/implementations/.+\\.js$',
|
||||
'/Libraries/BatchedBridge/MessageQueue\\.js$',
|
||||
'/Libraries/YellowBox/.+\\.js$',
|
||||
'/Libraries/LogBox/.+\\.js$',
|
||||
'/Libraries/Core/Timers/.+\\.js$',
|
||||
'/Libraries/WebSocket/.+\\.js$',
|
||||
'/Libraries/vendor/.+\\.js$',
|
||||
'/node_modules/react-devtools-core/.+\\.js$',
|
||||
'/node_modules/react-refresh/.+\\.js$',
|
||||
'/node_modules/scheduler/.+\\.js$',
|
||||
'/node_modules/event-target-shim/.+\\.js$',
|
||||
'/node_modules/invariant/.+\\.js$',
|
||||
'/node_modules/react-native/index.js$',
|
||||
'/metro-runtime/.+\\.js$',
|
||||
'^\\[native code\\]$',
|
||||
].join('|'),
|
||||
);
|
||||
|
||||
/**
|
||||
* Get the base Metro configuration for a React Native project.
|
||||
*/
|
||||
|
||||
function getDefaultConfig(
|
||||
projectRoot /*: string */
|
||||
) /*: ConfigT */ {
|
||||
const config = {
|
||||
resolver: {
|
||||
resolverMainFields: ['react-native', 'browser', 'main'],
|
||||
platforms: ['android', 'ios'],
|
||||
unstable_conditionNames: ['require', 'import', 'react-native'],
|
||||
},
|
||||
serializer: {
|
||||
// Note: This option is overridden in cli-plugin-metro (getOverrideConfig)
|
||||
getModulesRunBeforeMainModule: () => [
|
||||
require.resolve('react-native/Libraries/Core/InitializeCore'),
|
||||
],
|
||||
getPolyfills: () => require('@react-native/js-polyfills')(),
|
||||
},
|
||||
server: {
|
||||
port: Number(process.env.RCT_METRO_PORT) || 8081,
|
||||
},
|
||||
symbolicator: {
|
||||
customizeFrame: (frame /*: $ReadOnly<{file: ?string, ...}>*/) => {
|
||||
const collapse = Boolean(
|
||||
frame.file && INTERNAL_CALLSITES_REGEX.test(frame.file),
|
||||
);
|
||||
return {collapse};
|
||||
},
|
||||
},
|
||||
transformer: {
|
||||
allowOptionalDependencies: true,
|
||||
assetRegistryPath: 'react-native/Libraries/Image/AssetRegistry',
|
||||
asyncRequireModulePath: require.resolve(
|
||||
'metro-runtime/src/modules/asyncRequire',
|
||||
),
|
||||
babelTransformerPath: require.resolve(
|
||||
'metro-react-native-babel-transformer',
|
||||
),
|
||||
getTransformOptions: async () => ({
|
||||
transform: {
|
||||
experimentalImportSupport: false,
|
||||
inlineRequires: true,
|
||||
},
|
||||
}),
|
||||
},
|
||||
watchFolders: [],
|
||||
};
|
||||
|
||||
// Set global hook so that the CLI can detect when this config has been loaded
|
||||
global.__REACT_NATIVE_METRO_CONFIG_LOADED = true;
|
||||
|
||||
return mergeConfig(
|
||||
getBaseConfig.getDefaultValues(projectRoot),
|
||||
config,
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = {getDefaultConfig, mergeConfig};
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "@react-native/metro-config",
|
||||
"version": "0.72.9",
|
||||
"description": "Metro configuration for React Native.",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git@github.com:facebook/react-native.git",
|
||||
"directory": "packages/metro-config"
|
||||
},
|
||||
"license": "MIT",
|
||||
"exports": "./index.js",
|
||||
"dependencies": {
|
||||
"@react-native/js-polyfills": "^0.72.1",
|
||||
"metro-config": "0.76.7",
|
||||
"metro-react-native-babel-transformer": "0.76.7",
|
||||
"metro-runtime": "0.76.7"
|
||||
}
|
||||
}
|
||||
+16
-16
@@ -193,7 +193,7 @@ enum NativeEnumTurboModuleStatusRegularEnum { Active, Paused, Off };
|
||||
|
||||
template <>
|
||||
struct Bridging<NativeEnumTurboModuleStatusRegularEnum> {
|
||||
static NativeEnumTurboModuleStatusRegularEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue, const std::shared_ptr<CallInvoker> &jsInvoker) {
|
||||
static NativeEnumTurboModuleStatusRegularEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue) {
|
||||
std::string value = rawValue.utf8(rt);
|
||||
if (value == \\"Active\\") {
|
||||
return NativeEnumTurboModuleStatusRegularEnum::Active;
|
||||
@@ -206,7 +206,7 @@ struct Bridging<NativeEnumTurboModuleStatusRegularEnum> {
|
||||
}
|
||||
}
|
||||
|
||||
static jsi::String toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusRegularEnum value, const std::shared_ptr<CallInvoker> &jsInvoker) {
|
||||
static jsi::String toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusRegularEnum value) {
|
||||
if (value == NativeEnumTurboModuleStatusRegularEnum::Active) {
|
||||
return bridging::toJs(rt, \\"Active\\");
|
||||
} else if (value == NativeEnumTurboModuleStatusRegularEnum::Paused) {
|
||||
@@ -225,7 +225,7 @@ enum NativeEnumTurboModuleStatusStrEnum { Active, Paused, Off };
|
||||
|
||||
template <>
|
||||
struct Bridging<NativeEnumTurboModuleStatusStrEnum> {
|
||||
static NativeEnumTurboModuleStatusStrEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue, const std::shared_ptr<CallInvoker> &jsInvoker) {
|
||||
static NativeEnumTurboModuleStatusStrEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue) {
|
||||
std::string value = rawValue.utf8(rt);
|
||||
if (value == \\"active\\") {
|
||||
return NativeEnumTurboModuleStatusStrEnum::Active;
|
||||
@@ -238,7 +238,7 @@ struct Bridging<NativeEnumTurboModuleStatusStrEnum> {
|
||||
}
|
||||
}
|
||||
|
||||
static jsi::String toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusStrEnum value, const std::shared_ptr<CallInvoker> &jsInvoker) {
|
||||
static jsi::String toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusStrEnum value) {
|
||||
if (value == NativeEnumTurboModuleStatusStrEnum::Active) {
|
||||
return bridging::toJs(rt, \\"active\\");
|
||||
} else if (value == NativeEnumTurboModuleStatusStrEnum::Paused) {
|
||||
@@ -257,7 +257,7 @@ enum NativeEnumTurboModuleStatusNumEnum { Active, Paused, Off };
|
||||
|
||||
template <>
|
||||
struct Bridging<NativeEnumTurboModuleStatusNumEnum> {
|
||||
static NativeEnumTurboModuleStatusNumEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue, const std::shared_ptr<CallInvoker> &jsInvoker) {
|
||||
static NativeEnumTurboModuleStatusNumEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue) {
|
||||
double value = (double)rawValue.asNumber();
|
||||
if (value == 2) {
|
||||
return NativeEnumTurboModuleStatusNumEnum::Active;
|
||||
@@ -270,7 +270,7 @@ struct Bridging<NativeEnumTurboModuleStatusNumEnum> {
|
||||
}
|
||||
}
|
||||
|
||||
static jsi::Value toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusNumEnum value, const std::shared_ptr<CallInvoker> &jsInvoker) {
|
||||
static jsi::Value toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusNumEnum value) {
|
||||
if (value == NativeEnumTurboModuleStatusNumEnum::Active) {
|
||||
return bridging::toJs(rt, 2);
|
||||
} else if (value == NativeEnumTurboModuleStatusNumEnum::Paused) {
|
||||
@@ -289,7 +289,7 @@ enum NativeEnumTurboModuleStatusFractionEnum { Active, Paused, Off };
|
||||
|
||||
template <>
|
||||
struct Bridging<NativeEnumTurboModuleStatusFractionEnum> {
|
||||
static NativeEnumTurboModuleStatusFractionEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue, const std::shared_ptr<CallInvoker> &jsInvoker) {
|
||||
static NativeEnumTurboModuleStatusFractionEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue) {
|
||||
double value = (double)rawValue.asNumber();
|
||||
if (value == 0.2f) {
|
||||
return NativeEnumTurboModuleStatusFractionEnum::Active;
|
||||
@@ -302,7 +302,7 @@ struct Bridging<NativeEnumTurboModuleStatusFractionEnum> {
|
||||
}
|
||||
}
|
||||
|
||||
static jsi::Value toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusFractionEnum value, const std::shared_ptr<CallInvoker> &jsInvoker) {
|
||||
static jsi::Value toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusFractionEnum value) {
|
||||
if (value == NativeEnumTurboModuleStatusFractionEnum::Active) {
|
||||
return bridging::toJs(rt, 0.2f);
|
||||
} else if (value == NativeEnumTurboModuleStatusFractionEnum::Paused) {
|
||||
@@ -2136,7 +2136,7 @@ enum NativeEnumTurboModuleStatusRegularEnum { Active, Paused, Off };
|
||||
|
||||
template <>
|
||||
struct Bridging<NativeEnumTurboModuleStatusRegularEnum> {
|
||||
static NativeEnumTurboModuleStatusRegularEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue, const std::shared_ptr<CallInvoker> &jsInvoker) {
|
||||
static NativeEnumTurboModuleStatusRegularEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue) {
|
||||
std::string value = rawValue.utf8(rt);
|
||||
if (value == \\"Active\\") {
|
||||
return NativeEnumTurboModuleStatusRegularEnum::Active;
|
||||
@@ -2149,7 +2149,7 @@ struct Bridging<NativeEnumTurboModuleStatusRegularEnum> {
|
||||
}
|
||||
}
|
||||
|
||||
static jsi::String toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusRegularEnum value, const std::shared_ptr<CallInvoker> &jsInvoker) {
|
||||
static jsi::String toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusRegularEnum value) {
|
||||
if (value == NativeEnumTurboModuleStatusRegularEnum::Active) {
|
||||
return bridging::toJs(rt, \\"Active\\");
|
||||
} else if (value == NativeEnumTurboModuleStatusRegularEnum::Paused) {
|
||||
@@ -2168,7 +2168,7 @@ enum NativeEnumTurboModuleStatusStrEnum { Active, Paused, Off };
|
||||
|
||||
template <>
|
||||
struct Bridging<NativeEnumTurboModuleStatusStrEnum> {
|
||||
static NativeEnumTurboModuleStatusStrEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue, const std::shared_ptr<CallInvoker> &jsInvoker) {
|
||||
static NativeEnumTurboModuleStatusStrEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue) {
|
||||
std::string value = rawValue.utf8(rt);
|
||||
if (value == \\"active\\") {
|
||||
return NativeEnumTurboModuleStatusStrEnum::Active;
|
||||
@@ -2181,7 +2181,7 @@ struct Bridging<NativeEnumTurboModuleStatusStrEnum> {
|
||||
}
|
||||
}
|
||||
|
||||
static jsi::String toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusStrEnum value, const std::shared_ptr<CallInvoker> &jsInvoker) {
|
||||
static jsi::String toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusStrEnum value) {
|
||||
if (value == NativeEnumTurboModuleStatusStrEnum::Active) {
|
||||
return bridging::toJs(rt, \\"active\\");
|
||||
} else if (value == NativeEnumTurboModuleStatusStrEnum::Paused) {
|
||||
@@ -2200,7 +2200,7 @@ enum NativeEnumTurboModuleStatusNumEnum { Active, Paused, Off };
|
||||
|
||||
template <>
|
||||
struct Bridging<NativeEnumTurboModuleStatusNumEnum> {
|
||||
static NativeEnumTurboModuleStatusNumEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue, const std::shared_ptr<CallInvoker> &jsInvoker) {
|
||||
static NativeEnumTurboModuleStatusNumEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue) {
|
||||
double value = (double)rawValue.asNumber();
|
||||
if (value == 2) {
|
||||
return NativeEnumTurboModuleStatusNumEnum::Active;
|
||||
@@ -2213,7 +2213,7 @@ struct Bridging<NativeEnumTurboModuleStatusNumEnum> {
|
||||
}
|
||||
}
|
||||
|
||||
static jsi::Value toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusNumEnum value, const std::shared_ptr<CallInvoker> &jsInvoker) {
|
||||
static jsi::Value toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusNumEnum value) {
|
||||
if (value == NativeEnumTurboModuleStatusNumEnum::Active) {
|
||||
return bridging::toJs(rt, 2);
|
||||
} else if (value == NativeEnumTurboModuleStatusNumEnum::Paused) {
|
||||
@@ -2232,7 +2232,7 @@ enum NativeEnumTurboModuleStatusFractionEnum { Active, Paused, Off };
|
||||
|
||||
template <>
|
||||
struct Bridging<NativeEnumTurboModuleStatusFractionEnum> {
|
||||
static NativeEnumTurboModuleStatusFractionEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue, const std::shared_ptr<CallInvoker> &jsInvoker) {
|
||||
static NativeEnumTurboModuleStatusFractionEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue) {
|
||||
double value = (double)rawValue.asNumber();
|
||||
if (value == 0.2f) {
|
||||
return NativeEnumTurboModuleStatusFractionEnum::Active;
|
||||
@@ -2245,7 +2245,7 @@ struct Bridging<NativeEnumTurboModuleStatusFractionEnum> {
|
||||
}
|
||||
}
|
||||
|
||||
static jsi::Value toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusFractionEnum value, const std::shared_ptr<CallInvoker> &jsInvoker) {
|
||||
static jsi::Value toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusFractionEnum value) {
|
||||
if (value == NativeEnumTurboModuleStatusFractionEnum::Active) {
|
||||
return bridging::toJs(rt, 0.2f);
|
||||
} else if (value == NativeEnumTurboModuleStatusFractionEnum::Paused) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/codegen",
|
||||
"version": "0.72.3",
|
||||
"version": "0.72.6",
|
||||
"description": "⚛️ Code generation tools for React Native",
|
||||
"homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/react-native-codegen",
|
||||
"repository": {
|
||||
@@ -19,21 +19,21 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.20.0",
|
||||
"flow-parser": "^0.185.0",
|
||||
"flow-parser": "^0.206.0",
|
||||
"jscodeshift": "^0.14.0",
|
||||
"nullthrows": "^1.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.20.0",
|
||||
"@babel/plugin-proposal-class-properties": "^7.0.0",
|
||||
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0",
|
||||
"@babel/plugin-proposal-object-rest-spread": "^7.0.0",
|
||||
"@babel/plugin-proposal-optional-chaining": "^7.0.0",
|
||||
"@babel/plugin-syntax-dynamic-import": "^7.0.0",
|
||||
"@babel/plugin-transform-async-to-generator": "^7.0.0",
|
||||
"@babel/plugin-transform-destructuring": "^7.0.0",
|
||||
"@babel/plugin-transform-flow-strip-types": "^7.0.0",
|
||||
"@babel/preset-env": "^7.14.0",
|
||||
"@babel/plugin-proposal-class-properties": "^7.18.0",
|
||||
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.0",
|
||||
"@babel/plugin-proposal-object-rest-spread": "^7.20.0",
|
||||
"@babel/plugin-proposal-optional-chaining": "^7.20.0",
|
||||
"@babel/plugin-syntax-dynamic-import": "^7.8.0",
|
||||
"@babel/plugin-transform-async-to-generator": "^7.20.0",
|
||||
"@babel/plugin-transform-destructuring": "^7.20.0",
|
||||
"@babel/plugin-transform-flow-strip-types": "^7.20.0",
|
||||
"@babel/preset-env": "^7.20.0",
|
||||
"chalk": "^4.0.0",
|
||||
"glob": "^7.1.1",
|
||||
"invariant": "^2.2.4",
|
||||
|
||||
@@ -338,12 +338,12 @@ enum ${enumName} { ${values} };
|
||||
|
||||
template <>
|
||||
struct Bridging<${enumName}> {
|
||||
static ${enumName} fromJs(jsi::Runtime &rt, ${fromValue}, const std::shared_ptr<CallInvoker> &jsInvoker) {
|
||||
static ${enumName} fromJs(jsi::Runtime &rt, ${fromValue}) {
|
||||
${fromValueConversion}
|
||||
${fromCases}
|
||||
}
|
||||
|
||||
static ${toValue} toJs(jsi::Runtime &rt, ${enumName} value, const std::shared_ptr<CallInvoker> &jsInvoker) {
|
||||
static ${toValue} toJs(jsi::Runtime &rt, ${enumName} value) {
|
||||
${toCases}
|
||||
}
|
||||
};`;
|
||||
|
||||
+12
-12
@@ -211,7 +211,7 @@ enum SampleTurboModuleCxxNumEnum { ONE, TWO };
|
||||
|
||||
template <>
|
||||
struct Bridging<SampleTurboModuleCxxNumEnum> {
|
||||
static SampleTurboModuleCxxNumEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue, const std::shared_ptr<CallInvoker> &jsInvoker) {
|
||||
static SampleTurboModuleCxxNumEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue) {
|
||||
double value = (double)rawValue.asNumber();
|
||||
if (value == 1) {
|
||||
return SampleTurboModuleCxxNumEnum::ONE;
|
||||
@@ -222,7 +222,7 @@ struct Bridging<SampleTurboModuleCxxNumEnum> {
|
||||
}
|
||||
}
|
||||
|
||||
static jsi::Value toJs(jsi::Runtime &rt, SampleTurboModuleCxxNumEnum value, const std::shared_ptr<CallInvoker> &jsInvoker) {
|
||||
static jsi::Value toJs(jsi::Runtime &rt, SampleTurboModuleCxxNumEnum value) {
|
||||
if (value == SampleTurboModuleCxxNumEnum::ONE) {
|
||||
return bridging::toJs(rt, 1);
|
||||
} else if (value == SampleTurboModuleCxxNumEnum::TWO) {
|
||||
@@ -239,7 +239,7 @@ enum SampleTurboModuleCxxFloatEnum { POINT_ZERO, POINT_ONE, POINT_TWO };
|
||||
|
||||
template <>
|
||||
struct Bridging<SampleTurboModuleCxxFloatEnum> {
|
||||
static SampleTurboModuleCxxFloatEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue, const std::shared_ptr<CallInvoker> &jsInvoker) {
|
||||
static SampleTurboModuleCxxFloatEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue) {
|
||||
double value = (double)rawValue.asNumber();
|
||||
if (value == 0.0f) {
|
||||
return SampleTurboModuleCxxFloatEnum::POINT_ZERO;
|
||||
@@ -252,7 +252,7 @@ struct Bridging<SampleTurboModuleCxxFloatEnum> {
|
||||
}
|
||||
}
|
||||
|
||||
static jsi::Value toJs(jsi::Runtime &rt, SampleTurboModuleCxxFloatEnum value, const std::shared_ptr<CallInvoker> &jsInvoker) {
|
||||
static jsi::Value toJs(jsi::Runtime &rt, SampleTurboModuleCxxFloatEnum value) {
|
||||
if (value == SampleTurboModuleCxxFloatEnum::POINT_ZERO) {
|
||||
return bridging::toJs(rt, 0.0f);
|
||||
} else if (value == SampleTurboModuleCxxFloatEnum::POINT_ONE) {
|
||||
@@ -271,7 +271,7 @@ enum SampleTurboModuleCxxStringEnum { HELLO, GoodBye };
|
||||
|
||||
template <>
|
||||
struct Bridging<SampleTurboModuleCxxStringEnum> {
|
||||
static SampleTurboModuleCxxStringEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue, const std::shared_ptr<CallInvoker> &jsInvoker) {
|
||||
static SampleTurboModuleCxxStringEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue) {
|
||||
std::string value = rawValue.utf8(rt);
|
||||
if (value == \\"hello\\") {
|
||||
return SampleTurboModuleCxxStringEnum::HELLO;
|
||||
@@ -282,7 +282,7 @@ struct Bridging<SampleTurboModuleCxxStringEnum> {
|
||||
}
|
||||
}
|
||||
|
||||
static jsi::String toJs(jsi::Runtime &rt, SampleTurboModuleCxxStringEnum value, const std::shared_ptr<CallInvoker> &jsInvoker) {
|
||||
static jsi::String toJs(jsi::Runtime &rt, SampleTurboModuleCxxStringEnum value) {
|
||||
if (value == SampleTurboModuleCxxStringEnum::HELLO) {
|
||||
return bridging::toJs(rt, \\"hello\\");
|
||||
} else if (value == SampleTurboModuleCxxStringEnum::GoodBye) {
|
||||
@@ -1209,7 +1209,7 @@ enum SampleTurboModuleNumEnum { ONE, TWO };
|
||||
|
||||
template <>
|
||||
struct Bridging<SampleTurboModuleNumEnum> {
|
||||
static SampleTurboModuleNumEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue, const std::shared_ptr<CallInvoker> &jsInvoker) {
|
||||
static SampleTurboModuleNumEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue) {
|
||||
double value = (double)rawValue.asNumber();
|
||||
if (value == 1) {
|
||||
return SampleTurboModuleNumEnum::ONE;
|
||||
@@ -1220,7 +1220,7 @@ struct Bridging<SampleTurboModuleNumEnum> {
|
||||
}
|
||||
}
|
||||
|
||||
static jsi::Value toJs(jsi::Runtime &rt, SampleTurboModuleNumEnum value, const std::shared_ptr<CallInvoker> &jsInvoker) {
|
||||
static jsi::Value toJs(jsi::Runtime &rt, SampleTurboModuleNumEnum value) {
|
||||
if (value == SampleTurboModuleNumEnum::ONE) {
|
||||
return bridging::toJs(rt, 1);
|
||||
} else if (value == SampleTurboModuleNumEnum::TWO) {
|
||||
@@ -1237,7 +1237,7 @@ enum SampleTurboModuleFloatEnum { POINT_ZERO, POINT_ONE, POINT_TWO };
|
||||
|
||||
template <>
|
||||
struct Bridging<SampleTurboModuleFloatEnum> {
|
||||
static SampleTurboModuleFloatEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue, const std::shared_ptr<CallInvoker> &jsInvoker) {
|
||||
static SampleTurboModuleFloatEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue) {
|
||||
double value = (double)rawValue.asNumber();
|
||||
if (value == 0.0f) {
|
||||
return SampleTurboModuleFloatEnum::POINT_ZERO;
|
||||
@@ -1250,7 +1250,7 @@ struct Bridging<SampleTurboModuleFloatEnum> {
|
||||
}
|
||||
}
|
||||
|
||||
static jsi::Value toJs(jsi::Runtime &rt, SampleTurboModuleFloatEnum value, const std::shared_ptr<CallInvoker> &jsInvoker) {
|
||||
static jsi::Value toJs(jsi::Runtime &rt, SampleTurboModuleFloatEnum value) {
|
||||
if (value == SampleTurboModuleFloatEnum::POINT_ZERO) {
|
||||
return bridging::toJs(rt, 0.0f);
|
||||
} else if (value == SampleTurboModuleFloatEnum::POINT_ONE) {
|
||||
@@ -1269,7 +1269,7 @@ enum SampleTurboModuleStringEnum { HELLO, GoodBye };
|
||||
|
||||
template <>
|
||||
struct Bridging<SampleTurboModuleStringEnum> {
|
||||
static SampleTurboModuleStringEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue, const std::shared_ptr<CallInvoker> &jsInvoker) {
|
||||
static SampleTurboModuleStringEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue) {
|
||||
std::string value = rawValue.utf8(rt);
|
||||
if (value == \\"hello\\") {
|
||||
return SampleTurboModuleStringEnum::HELLO;
|
||||
@@ -1280,7 +1280,7 @@ struct Bridging<SampleTurboModuleStringEnum> {
|
||||
}
|
||||
}
|
||||
|
||||
static jsi::String toJs(jsi::Runtime &rt, SampleTurboModuleStringEnum value, const std::shared_ptr<CallInvoker> &jsInvoker) {
|
||||
static jsi::String toJs(jsi::Runtime &rt, SampleTurboModuleStringEnum value) {
|
||||
if (value == SampleTurboModuleStringEnum::HELLO) {
|
||||
return bridging::toJs(rt, \\"hello\\");
|
||||
} else if (value == SampleTurboModuleStringEnum::GoodBye) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/gradle-plugin",
|
||||
"version": "0.72.5",
|
||||
"version": "0.72.11",
|
||||
"description": "⚛️ Gradle Plugin for React Native",
|
||||
"homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/react-native-gradle-plugin",
|
||||
"repository": {
|
||||
|
||||
+9
-3
@@ -18,7 +18,8 @@ import com.facebook.react.utils.AgpConfiguratorUtils.configureDevPorts
|
||||
import com.facebook.react.utils.BackwardCompatUtils.configureBackwardCompatibilityReactMap
|
||||
import com.facebook.react.utils.DependencyUtils.configureDependencies
|
||||
import com.facebook.react.utils.DependencyUtils.configureRepositories
|
||||
import com.facebook.react.utils.DependencyUtils.readVersionString
|
||||
import com.facebook.react.utils.DependencyUtils.readVersionAndGroupStrings
|
||||
import com.facebook.react.utils.JdkConfiguratorUtils.configureJavaToolChains
|
||||
import com.facebook.react.utils.JsonUtils
|
||||
import com.facebook.react.utils.NdkConfiguratorUtils.configureReactNativeNdk
|
||||
import com.facebook.react.utils.ProjectUtils.needsCodegenFromPackageJson
|
||||
@@ -54,8 +55,10 @@ class ReactPlugin : Plugin<Project> {
|
||||
project.afterEvaluate {
|
||||
val reactNativeDir = extension.reactNativeDir.get().asFile
|
||||
val propertiesFile = File(reactNativeDir, "ReactAndroid/gradle.properties")
|
||||
val versionString = readVersionString(propertiesFile)
|
||||
configureDependencies(project, versionString)
|
||||
val versionAndGroupStrings = readVersionAndGroupStrings(propertiesFile)
|
||||
val versionString = versionAndGroupStrings.first
|
||||
val groupString = versionAndGroupStrings.second
|
||||
configureDependencies(project, versionString, groupString)
|
||||
configureRepositories(project, reactNativeDir)
|
||||
}
|
||||
|
||||
@@ -76,6 +79,9 @@ class ReactPlugin : Plugin<Project> {
|
||||
project.pluginManager.withPlugin("com.android.library") {
|
||||
configureCodegen(project, extension, rootExtension, isLibrary = true)
|
||||
}
|
||||
|
||||
// App and Library Configurations
|
||||
configureJavaToolChains(project)
|
||||
}
|
||||
|
||||
private fun checkJvmVersion(project: Project) {
|
||||
|
||||
+1
@@ -174,6 +174,7 @@ abstract class BundleHermesCTask : DefaultTask() {
|
||||
return windowsAwareCommandLine(
|
||||
hermesCommand,
|
||||
"-emit-binary",
|
||||
"-max-diagnostic-width=80",
|
||||
"-out",
|
||||
bytecodeFile.cliPath(rootFile),
|
||||
bundleFile.cliPath(rootFile),
|
||||
|
||||
+32
-12
@@ -13,6 +13,8 @@ import java.util.*
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.repositories.MavenArtifactRepository
|
||||
|
||||
internal const val DEFAULT_GROUP_STRING = "com.facebook.react"
|
||||
|
||||
internal object DependencyUtils {
|
||||
|
||||
/**
|
||||
@@ -46,7 +48,11 @@ internal object DependencyUtils {
|
||||
* - Forcing the react-android/hermes-android version to the one specified in the package.json
|
||||
* - Substituting `react-native` with `react-android` and `hermes-engine` with `hermes-android`.
|
||||
*/
|
||||
fun configureDependencies(project: Project, versionString: String) {
|
||||
fun configureDependencies(
|
||||
project: Project,
|
||||
versionString: String,
|
||||
groupString: String = DEFAULT_GROUP_STRING
|
||||
) {
|
||||
if (versionString.isBlank()) return
|
||||
project.rootProject.allprojects { eachProject ->
|
||||
eachProject.configurations.all { configuration ->
|
||||
@@ -56,32 +62,46 @@ internal object DependencyUtils {
|
||||
// implementation("com.facebook.react:react-native:+") and resolve the right dependency.
|
||||
configuration.resolutionStrategy.dependencySubstitution {
|
||||
it.substitute(it.module("com.facebook.react:react-native"))
|
||||
.using(it.module("com.facebook.react:react-android:${versionString}"))
|
||||
.using(it.module("${groupString}:react-android:${versionString}"))
|
||||
.because(
|
||||
"The react-native artifact was deprecated in favor of react-android due to https://github.com/facebook/react-native/issues/35210.")
|
||||
it.substitute(it.module("com.facebook.react:hermes-engine"))
|
||||
.using(it.module("com.facebook.react:hermes-android:${versionString}"))
|
||||
.using(it.module("${groupString}:hermes-android:${versionString}"))
|
||||
.because(
|
||||
"The hermes-engine artifact was deprecated in favor of hermes-android due to https://github.com/facebook/react-native/issues/35210.")
|
||||
if (groupString != DEFAULT_GROUP_STRING) {
|
||||
it.substitute(it.module("com.facebook.react:react-android"))
|
||||
.using(it.module("${groupString}:react-android:${versionString}"))
|
||||
.because(
|
||||
"The react-android dependency was modified to use the correct Maven group.")
|
||||
it.substitute(it.module("com.facebook.react:hermes-android"))
|
||||
.using(it.module("${groupString}:hermes-android:${versionString}"))
|
||||
.because(
|
||||
"The hermes-android dependency was modified to use the correct Maven group.")
|
||||
}
|
||||
}
|
||||
configuration.resolutionStrategy.force(
|
||||
"com.facebook.react:react-android:${versionString}",
|
||||
"com.facebook.react:hermes-android:${versionString}",
|
||||
"${groupString}:react-android:${versionString}",
|
||||
"${groupString}:hermes-android:${versionString}",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun readVersionString(propertiesFile: File): String {
|
||||
fun readVersionAndGroupStrings(propertiesFile: File): Pair<String, String> {
|
||||
val reactAndroidProperties = Properties()
|
||||
propertiesFile.inputStream().use { reactAndroidProperties.load(it) }
|
||||
val versionString = reactAndroidProperties["VERSION_NAME"] as? String ?: ""
|
||||
val versionStringFromFile = reactAndroidProperties["VERSION_NAME"] as? String ?: ""
|
||||
// If on a nightly, we need to fetch the -SNAPSHOT artifact from Sonatype.
|
||||
return if (versionString.startsWith("0.0.0")) {
|
||||
"$versionString-SNAPSHOT"
|
||||
} else {
|
||||
versionString
|
||||
}
|
||||
val versionString =
|
||||
if (versionStringFromFile.startsWith("0.0.0")) {
|
||||
"$versionStringFromFile-SNAPSHOT"
|
||||
} else {
|
||||
versionStringFromFile
|
||||
}
|
||||
// Returns Maven group for repos using different group for Maven artifacts
|
||||
val groupString = reactAndroidProperties["GROUP"] as? String ?: DEFAULT_GROUP_STRING
|
||||
return Pair(versionString, groupString)
|
||||
}
|
||||
|
||||
fun Project.mavenRepoFromUrl(url: String): MavenArtifactRepository =
|
||||
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.utils
|
||||
|
||||
import com.android.build.api.variant.AndroidComponentsExtension
|
||||
import com.facebook.react.utils.PropertyUtils.INTERNAL_DISABLE_JAVA_VERSION_ALIGNMENT
|
||||
import org.gradle.api.Action
|
||||
import org.gradle.api.JavaVersion
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.plugins.AppliedPlugin
|
||||
|
||||
internal object JdkConfiguratorUtils {
|
||||
/**
|
||||
* Function that takes care of configuring the JDK toolchain for all the projects projects. As we
|
||||
* do decide the JDK version based on the AGP version that RNGP brings over, here we can safely
|
||||
* configure the toolchain to 11.
|
||||
*/
|
||||
fun configureJavaToolChains(input: Project) {
|
||||
if (input.hasProperty(INTERNAL_DISABLE_JAVA_VERSION_ALIGNMENT)) {
|
||||
return
|
||||
}
|
||||
input.rootProject.allprojects { project ->
|
||||
val action =
|
||||
Action<AppliedPlugin> {
|
||||
project.extensions.getByType(AndroidComponentsExtension::class.java).finalizeDsl {
|
||||
ext ->
|
||||
ext.compileOptions.sourceCompatibility = JavaVersion.VERSION_11
|
||||
ext.compileOptions.targetCompatibility = JavaVersion.VERSION_11
|
||||
}
|
||||
}
|
||||
project.pluginManager.withPlugin("com.android.application", action)
|
||||
project.pluginManager.withPlugin("com.android.library", action)
|
||||
}
|
||||
// We set kotlin.jvm.target.validation.mode=warning on the root projects, as for projects
|
||||
// on Gradle 8+ and Kotlin 1.8+ this value is set to `error`. This will cause the build to
|
||||
// fail if the JDK version between compileKotlin and compileJava and jvmTarget are not
|
||||
// aligned. This won't be necessary anymore from React Native 0.73. More on this:
|
||||
// https://kotlinlang.org/docs/whatsnew18.html#obligatory-check-for-jvm-targets-of-related-kotlin-and-java-compile-tasks
|
||||
input.rootProject.extensions.extraProperties.set("kotlin.jvm.target.validation.mode", "warning")
|
||||
}
|
||||
}
|
||||
+9
-3
@@ -40,16 +40,22 @@ internal object NdkConfiguratorUtils {
|
||||
// Parameters should be provided in an additive manner (do not override what
|
||||
// the user provided, but allow for sensible defaults).
|
||||
val cmakeArgs = ext.defaultConfig.externalNativeBuild.cmake.arguments
|
||||
if ("-DPROJECT_BUILD_DIR" !in cmakeArgs) {
|
||||
if (cmakeArgs.none { it.startsWith("-DPROJECT_BUILD_DIR") }) {
|
||||
cmakeArgs.add("-DPROJECT_BUILD_DIR=${project.buildDir}")
|
||||
}
|
||||
if ("-DREACT_ANDROID_DIR" !in cmakeArgs) {
|
||||
if (cmakeArgs.none { it.startsWith("-DREACT_ANDROID_DIR") }) {
|
||||
cmakeArgs.add(
|
||||
"-DREACT_ANDROID_DIR=${extension.reactNativeDir.file("ReactAndroid").get().asFile}")
|
||||
}
|
||||
if ("-DANDROID_STL" !in cmakeArgs) {
|
||||
if (cmakeArgs.none { it.startsWith("-DANDROID_STL") }) {
|
||||
cmakeArgs.add("-DANDROID_STL=c++_shared")
|
||||
}
|
||||
// Due to the new NDK toolchain file, the C++ flags gets overridden between compilation
|
||||
// units. This is causing some libraries to don't be compiled with -DANDROID and other
|
||||
// crucial flags. This can be revisited once we bump to NDK 25/26
|
||||
if (cmakeArgs.none { it.startsWith("-DANDROID_USE_LEGACY_TOOLCHAIN_FILE") }) {
|
||||
cmakeArgs.add("-DANDROID_USE_LEGACY_TOOLCHAIN_FILE=ON")
|
||||
}
|
||||
|
||||
val architectures = project.getReactNativeArchitectures()
|
||||
// abiFilters are split ABI are not compatible each other, so we set the abiFilters
|
||||
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* 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.utils
|
||||
|
||||
/** Collection of all the Gradle Propreties that are accepted by React Native Gradle Plugin. */
|
||||
object PropertyUtils {
|
||||
|
||||
/**
|
||||
* Internal Property that acts as a killswitch to configure the JDK version and align it for app
|
||||
* and all the libraries.
|
||||
*/
|
||||
const val INTERNAL_DISABLE_JAVA_VERSION_ALIGNMENT = "react.internal.disableJavaVersionAlignment"
|
||||
}
|
||||
+12
-10
@@ -341,11 +341,12 @@ class BundleHermesCTaskTest {
|
||||
|
||||
assertEquals(customHermesc, hermesCommand[0])
|
||||
assertEquals("-emit-binary", hermesCommand[1])
|
||||
assertEquals("-out", hermesCommand[2])
|
||||
assertEquals(bytecodeFile.absolutePath, hermesCommand[3])
|
||||
assertEquals(bundleFile.absolutePath, hermesCommand[4])
|
||||
assertEquals("my-custom-hermes-flag", hermesCommand[5])
|
||||
assertEquals(6, hermesCommand.size)
|
||||
assertEquals("-max-diagnostic-width=80", hermesCommand[2])
|
||||
assertEquals("-out", hermesCommand[3])
|
||||
assertEquals(bytecodeFile.absolutePath, hermesCommand[4])
|
||||
assertEquals(bundleFile.absolutePath, hermesCommand[5])
|
||||
assertEquals("my-custom-hermes-flag", hermesCommand[6])
|
||||
assertEquals(7, hermesCommand.size)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -366,11 +367,12 @@ class BundleHermesCTaskTest {
|
||||
assertEquals("/c", hermesCommand[1])
|
||||
assertEquals(customHermesc, hermesCommand[2])
|
||||
assertEquals("-emit-binary", hermesCommand[3])
|
||||
assertEquals("-out", hermesCommand[4])
|
||||
assertEquals(bytecodeFile.relativeTo(tempFolder.root).path, hermesCommand[5])
|
||||
assertEquals(bundleFile.relativeTo(tempFolder.root).path, hermesCommand[6])
|
||||
assertEquals("my-custom-hermes-flag", hermesCommand[7])
|
||||
assertEquals(8, hermesCommand.size)
|
||||
assertEquals("-max-diagnostic-width=80", hermesCommand[4])
|
||||
assertEquals("-out", hermesCommand[5])
|
||||
assertEquals(bytecodeFile.relativeTo(tempFolder.root).path, hermesCommand[6])
|
||||
assertEquals(bundleFile.relativeTo(tempFolder.root).path, hermesCommand[7])
|
||||
assertEquals("my-custom-hermes-flag", hermesCommand[8])
|
||||
assertEquals(9, hermesCommand.size)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+56
-5
@@ -12,7 +12,7 @@ import com.facebook.react.utils.DependencyUtils.configureDependencies
|
||||
import com.facebook.react.utils.DependencyUtils.configureRepositories
|
||||
import com.facebook.react.utils.DependencyUtils.mavenRepoFromURI
|
||||
import com.facebook.react.utils.DependencyUtils.mavenRepoFromUrl
|
||||
import com.facebook.react.utils.DependencyUtils.readVersionString
|
||||
import com.facebook.react.utils.DependencyUtils.readVersionAndGroupStrings
|
||||
import java.net.URI
|
||||
import org.gradle.api.artifacts.repositories.MavenArtifactRepository
|
||||
import org.gradle.testfixtures.ProjectBuilder
|
||||
@@ -226,6 +226,24 @@ class DependencyUtilsTest {
|
||||
assertTrue(libForcedModules.any { it.toString() == "com.facebook.react:hermes-android:1.2.3" })
|
||||
}
|
||||
|
||||
@Test
|
||||
fun configureDependencies_withVersionStringAndGroupString_appliesOnAllProjects() {
|
||||
val rootProject = ProjectBuilder.builder().build()
|
||||
val appProject = ProjectBuilder.builder().withName("app").withParent(rootProject).build()
|
||||
val libProject = ProjectBuilder.builder().withName("lib").withParent(rootProject).build()
|
||||
appProject.plugins.apply("com.android.application")
|
||||
libProject.plugins.apply("com.android.library")
|
||||
|
||||
configureDependencies(appProject, "1.2.3", "io.github.test")
|
||||
|
||||
val appForcedModules = appProject.configurations.first().resolutionStrategy.forcedModules
|
||||
val libForcedModules = libProject.configurations.first().resolutionStrategy.forcedModules
|
||||
assertTrue(appForcedModules.any { it.toString() == "io.github.test:react-android:1.2.3" })
|
||||
assertTrue(appForcedModules.any { it.toString() == "io.github.test:hermes-android:1.2.3" })
|
||||
assertTrue(libForcedModules.any { it.toString() == "io.github.test:react-android:1.2.3" })
|
||||
assertTrue(libForcedModules.any { it.toString() == "io.github.test:hermes-android:1.2.3" })
|
||||
}
|
||||
|
||||
@Test
|
||||
fun readVersionString_withCorrectVersionString_returnsIt() {
|
||||
val propertiesFile =
|
||||
@@ -238,7 +256,7 @@ class DependencyUtilsTest {
|
||||
.trimIndent())
|
||||
}
|
||||
|
||||
val versionString = readVersionString(propertiesFile)
|
||||
val versionString = readVersionAndGroupStrings(propertiesFile).first
|
||||
|
||||
assertEquals("1000.0.0", versionString)
|
||||
}
|
||||
@@ -255,7 +273,7 @@ class DependencyUtilsTest {
|
||||
.trimIndent())
|
||||
}
|
||||
|
||||
val versionString = readVersionString(propertiesFile)
|
||||
val versionString = readVersionAndGroupStrings(propertiesFile).first
|
||||
|
||||
assertEquals("0.0.0-20221101-2019-cfe811ab1-SNAPSHOT", versionString)
|
||||
}
|
||||
@@ -271,7 +289,7 @@ class DependencyUtilsTest {
|
||||
.trimIndent())
|
||||
}
|
||||
|
||||
val versionString = readVersionString(propertiesFile)
|
||||
val versionString = readVersionAndGroupStrings(propertiesFile).first
|
||||
assertEquals("", versionString)
|
||||
}
|
||||
|
||||
@@ -287,10 +305,43 @@ class DependencyUtilsTest {
|
||||
.trimIndent())
|
||||
}
|
||||
|
||||
val versionString = readVersionString(propertiesFile)
|
||||
val versionString = readVersionAndGroupStrings(propertiesFile).first
|
||||
assertEquals("", versionString)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun readGroupString_withCorrectGroupString_returnsIt() {
|
||||
val propertiesFile =
|
||||
tempFolder.newFile("gradle.properties").apply {
|
||||
writeText(
|
||||
"""
|
||||
GROUP=io.github.test
|
||||
ANOTHER_PROPERTY=true
|
||||
"""
|
||||
.trimIndent())
|
||||
}
|
||||
|
||||
val groupString = readVersionAndGroupStrings(propertiesFile).second
|
||||
|
||||
assertEquals("io.github.test", groupString)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun readGroupString_withEmptyGroupString_returnsDefault() {
|
||||
val propertiesFile =
|
||||
tempFolder.newFile("gradle.properties").apply {
|
||||
writeText(
|
||||
"""
|
||||
ANOTHER_PROPERTY=true
|
||||
"""
|
||||
.trimIndent())
|
||||
}
|
||||
|
||||
val groupString = readVersionAndGroupStrings(propertiesFile).second
|
||||
|
||||
assertEquals("com.facebook.react", groupString)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun mavenRepoFromUrl_worksCorrectly() {
|
||||
val process = createProject()
|
||||
|
||||
@@ -94,6 +94,11 @@
|
||||
*/
|
||||
- (UIViewController *)createRootViewController;
|
||||
|
||||
/// This method controls whether the App will use RuntimeScheduler. Only applicable in the legacy architecture.
|
||||
///
|
||||
/// @return: `YES` to use RuntimeScheduler, `NO` to use JavaScript scheduler. The default value is `YES`.
|
||||
- (BOOL)runtimeSchedulerEnabled;
|
||||
|
||||
#if RCT_NEW_ARCH_ENABLED
|
||||
|
||||
/// The TurboModule manager
|
||||
|
||||
@@ -6,33 +6,41 @@
|
||||
*/
|
||||
|
||||
#import "RCTAppDelegate.h"
|
||||
#import <React/RCTCxxBridgeDelegate.h>
|
||||
#import <React/RCTRootView.h>
|
||||
#import <React/RCTRuntimeExecutorFromBridge.h>
|
||||
#import <react/renderer/runtimescheduler/RuntimeScheduler.h>
|
||||
|
||||
#import "RCTAppSetupUtils.h"
|
||||
|
||||
#if RCT_NEW_ARCH_ENABLED
|
||||
#import <React/CoreModulesPlugins.h>
|
||||
#import <React/RCTCxxBridgeDelegate.h>
|
||||
#import <React/RCTComponentViewFactory.h>
|
||||
#import <React/RCTComponentViewProtocol.h>
|
||||
#import <React/RCTFabricSurfaceHostingProxyRootView.h>
|
||||
#import <React/RCTLegacyViewManagerInteropComponentView.h>
|
||||
#import <React/RCTSurfacePresenter.h>
|
||||
#import <React/RCTSurfacePresenterBridgeAdapter.h>
|
||||
#import <ReactCommon/RCTTurboModuleManager.h>
|
||||
#import <react/config/ReactNativeConfig.h>
|
||||
#import <react/renderer/runtimescheduler/RuntimeScheduler.h>
|
||||
#import <react/renderer/runtimescheduler/RuntimeSchedulerCallInvoker.h>
|
||||
#import "RCTLegacyInteropComponents.h"
|
||||
|
||||
static NSString *const kRNConcurrentRoot = @"concurrentRoot";
|
||||
|
||||
@interface RCTAppDelegate () <RCTTurboModuleManagerDelegate, RCTCxxBridgeDelegate> {
|
||||
@interface RCTAppDelegate () <RCTTurboModuleManagerDelegate> {
|
||||
std::shared_ptr<const facebook::react::ReactNativeConfig> _reactNativeConfig;
|
||||
facebook::react::ContextContainer::Shared _contextContainer;
|
||||
std::shared_ptr<facebook::react::RuntimeScheduler> _runtimeScheduler;
|
||||
}
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
||||
@interface RCTAppDelegate () <RCTCxxBridgeDelegate> {
|
||||
std::shared_ptr<facebook::react::RuntimeScheduler> _runtimeScheduler;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation RCTAppDelegate
|
||||
|
||||
#if RCT_NEW_ARCH_ENABLED
|
||||
@@ -126,21 +134,34 @@ static NSString *const kRNConcurrentRoot = @"concurrentRoot";
|
||||
return [UIViewController new];
|
||||
}
|
||||
|
||||
#if RCT_NEW_ARCH_ENABLED
|
||||
- (BOOL)runtimeSchedulerEnabled
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
#pragma mark - RCTCxxBridgeDelegate
|
||||
- (std::unique_ptr<facebook::react::JSExecutorFactory>)jsExecutorFactoryForBridge:(RCTBridge *)bridge
|
||||
{
|
||||
_runtimeScheduler = _runtimeScheduler =
|
||||
std::make_shared<facebook::react::RuntimeScheduler>(RCTRuntimeExecutorFromBridge(bridge));
|
||||
#if RCT_NEW_ARCH_ENABLED
|
||||
_runtimeScheduler = std::make_shared<facebook::react::RuntimeScheduler>(RCTRuntimeExecutorFromBridge(bridge));
|
||||
std::shared_ptr<facebook::react::CallInvoker> callInvoker =
|
||||
std::make_shared<facebook::react::RuntimeSchedulerCallInvoker>(_runtimeScheduler);
|
||||
self.turboModuleManager = [[RCTTurboModuleManager alloc] initWithBridge:bridge delegate:self jsInvoker:callInvoker];
|
||||
_contextContainer->erase("RuntimeScheduler");
|
||||
_contextContainer->insert("RuntimeScheduler", _runtimeScheduler);
|
||||
return RCTAppSetupDefaultJsExecutorFactory(bridge, _turboModuleManager, _runtimeScheduler);
|
||||
return RCTAppSetupDefaultJsExecutorFactory(bridge, self.turboModuleManager, _runtimeScheduler);
|
||||
#else
|
||||
if (self.runtimeSchedulerEnabled) {
|
||||
_runtimeScheduler = std::make_shared<facebook::react::RuntimeScheduler>(RCTRuntimeExecutorFromBridge(bridge));
|
||||
}
|
||||
return RCTAppSetupJsExecutorFactoryForOldArch(bridge, _runtimeScheduler);
|
||||
#endif
|
||||
}
|
||||
|
||||
#pragma mark RCTTurboModuleManagerDelegate
|
||||
|
||||
#if RCT_NEW_ARCH_ENABLED
|
||||
|
||||
#pragma mark - RCTTurboModuleManagerDelegate
|
||||
|
||||
- (Class)getModuleClassFromName:(const char *)name
|
||||
{
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#if RCT_NEW_ARCH_ENABLED
|
||||
#import <memory>
|
||||
|
||||
#ifndef RCT_USE_HERMES
|
||||
#if __has_include(<reacthermes/HermesExecutorFactory.h>)
|
||||
@@ -27,21 +27,27 @@
|
||||
#import <React/JSCExecutorFactory.h>
|
||||
#endif
|
||||
|
||||
#if RCT_NEW_ARCH_ENABLED
|
||||
#import <ReactCommon/RCTTurboModuleManager.h>
|
||||
#endif
|
||||
|
||||
#if RCT_NEW_ARCH_ENABLED
|
||||
// Forward declaration to decrease compilation coupling
|
||||
namespace facebook::react {
|
||||
class RuntimeScheduler;
|
||||
}
|
||||
|
||||
#if RCT_NEW_ARCH_ENABLED
|
||||
RCT_EXTERN id<RCTTurboModule> RCTAppSetupDefaultModuleFromClass(Class moduleClass);
|
||||
|
||||
std::unique_ptr<facebook::react::JSExecutorFactory> RCTAppSetupDefaultJsExecutorFactory(
|
||||
RCTBridge *bridge,
|
||||
RCTTurboModuleManager *turboModuleManager,
|
||||
std::shared_ptr<facebook::react::RuntimeScheduler> const &runtimeScheduler);
|
||||
|
||||
#else
|
||||
std::unique_ptr<facebook::react::JSExecutorFactory> RCTAppSetupJsExecutorFactoryForOldArch(
|
||||
RCTBridge *bridge,
|
||||
std::shared_ptr<facebook::react::RuntimeScheduler> const &runtimeScheduler);
|
||||
#endif
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
@@ -7,6 +7,10 @@
|
||||
|
||||
#import "RCTAppSetupUtils.h"
|
||||
|
||||
#import <React/RCTJSIExecutorRuntimeInstaller.h>
|
||||
#import <react/renderer/runtimescheduler/RuntimeScheduler.h>
|
||||
#import <react/renderer/runtimescheduler/RuntimeSchedulerBinding.h>
|
||||
|
||||
#if RCT_NEW_ARCH_ENABLED
|
||||
// Turbo Module
|
||||
#import <React/CoreModulesPlugins.h>
|
||||
@@ -15,7 +19,6 @@
|
||||
#import <React/RCTGIFImageDecoder.h>
|
||||
#import <React/RCTHTTPRequestHandler.h>
|
||||
#import <React/RCTImageLoader.h>
|
||||
#import <React/RCTJSIExecutorRuntimeInstaller.h>
|
||||
#import <React/RCTLocalAssetImageLoader.h>
|
||||
#import <React/RCTNetworking.h>
|
||||
|
||||
@@ -135,4 +138,25 @@ std::unique_ptr<facebook::react::JSExecutorFactory> RCTAppSetupDefaultJsExecutor
|
||||
}));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
std::unique_ptr<facebook::react::JSExecutorFactory> RCTAppSetupJsExecutorFactoryForOldArch(
|
||||
RCTBridge *bridge,
|
||||
std::shared_ptr<facebook::react::RuntimeScheduler> const &runtimeScheduler)
|
||||
{
|
||||
#if RCT_USE_HERMES
|
||||
return std::make_unique<facebook::react::HermesExecutorFactory>(
|
||||
#else
|
||||
return std::make_unique<facebook::react::JSCExecutorFactory>(
|
||||
#endif
|
||||
facebook::react::RCTJSIExecutorRuntimeInstaller([bridge, runtimeScheduler](facebook::jsi::Runtime &runtime) {
|
||||
if (!bridge) {
|
||||
return;
|
||||
}
|
||||
if (runtimeScheduler) {
|
||||
facebook::react::RuntimeSchedulerBinding::createAndInstallIfNeeded(runtime, runtimeScheduler);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -47,6 +47,9 @@ header_search_paths = [
|
||||
"$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core",
|
||||
"$(PODS_CONFIGURATION_BUILD_DIR)/React-NativeModulesApple/React_NativeModulesApple.framework/Headers",
|
||||
"$(PODS_CONFIGURATION_BUILD_DIR)/React-RCTFabric/RCTFabric.framework/Headers/",
|
||||
"$(PODS_CONFIGURATION_BUILD_DIR)/React-utils/React_utils.framework/Headers/",
|
||||
"$(PODS_CONFIGURATION_BUILD_DIR)/React-debug/React_debug.framework/Headers/",
|
||||
"$(PODS_CONFIGURATION_BUILD_DIR)/React-runtimescheduler/React_runtimescheduler.framework/Headers/",
|
||||
] : []).map{|p| "\"#{p}\""}.join(" ")
|
||||
|
||||
Pod::Spec.new do |s|
|
||||
@@ -75,15 +78,29 @@ Pod::Spec.new do |s|
|
||||
s.dependency "RCTRequired"
|
||||
s.dependency "RCTTypeSafety"
|
||||
s.dependency "ReactCommon/turbomodule/core"
|
||||
s.dependency "React-RCTNetwork"
|
||||
s.dependency "React-RCTImage"
|
||||
s.dependency "React-NativeModulesApple"
|
||||
s.dependency "React-CoreModules"
|
||||
s.dependency "React-runtimescheduler"
|
||||
|
||||
if ENV['USE_HERMES'] == nil || ENV['USE_HERMES'] == "1"
|
||||
s.dependency "React-hermes"
|
||||
else
|
||||
s.dependency "React-jsc"
|
||||
end
|
||||
|
||||
if is_new_arch_enabled
|
||||
s.dependency "React-RCTFabric"
|
||||
s.dependency "React-graphics"
|
||||
s.dependency "React-utils"
|
||||
s.dependency "React-debug"
|
||||
|
||||
s.script_phases = {
|
||||
:name => "Generate Legacy Components Interop",
|
||||
:script => "
|
||||
. ${PODS_ROOT}/../.xcode.env
|
||||
WITH_ENVIRONMENT=\"$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh\"
|
||||
source $WITH_ENVIRONMENT
|
||||
${NODE_BINARY} ${REACT_NATIVE_PATH}/scripts/codegen/generate-legacy-interop-components.js -p #{ENV['APP_PATH']} -o ${REACT_NATIVE_PATH}/Libraries/AppDelegate
|
||||
",
|
||||
:execution_position => :before_compile,
|
||||
|
||||
-1
@@ -692,7 +692,6 @@ export const __INTERNAL_VIEW_CONFIG: PartialViewConfig = {
|
||||
fontStyle: true,
|
||||
textShadowOffset: true,
|
||||
selectionColor: {process: require('../../StyleSheet/processColor').default},
|
||||
selection: true,
|
||||
placeholderTextColor: {
|
||||
process: require('../../StyleSheet/processColor').default,
|
||||
},
|
||||
|
||||
+121
-86
@@ -289,92 +289,6 @@ export interface TextInputIOSProps {
|
||||
* @see https://reactnative.dev/docs/textinput#props
|
||||
*/
|
||||
export interface TextInputAndroidProps {
|
||||
/**
|
||||
* Specifies autocomplete hints for the system, so it can provide autofill. On Android, the system will always attempt to offer autofill by using heuristics to identify the type of content.
|
||||
* To disable autocomplete, set `autoComplete` to `off`.
|
||||
*
|
||||
* *Android Only*
|
||||
*
|
||||
* Possible values for `autoComplete` are:
|
||||
*
|
||||
* - `birthdate-day`
|
||||
* - `birthdate-full`
|
||||
* - `birthdate-month`
|
||||
* - `birthdate-year`
|
||||
* - `cc-csc`
|
||||
* - `cc-exp`
|
||||
* - `cc-exp-day`
|
||||
* - `cc-exp-month`
|
||||
* - `cc-exp-year`
|
||||
* - `cc-number`
|
||||
* - `email`
|
||||
* - `gender`
|
||||
* - `name`
|
||||
* - `name-family`
|
||||
* - `name-given`
|
||||
* - `name-middle`
|
||||
* - `name-middle-initial`
|
||||
* - `name-prefix`
|
||||
* - `name-suffix`
|
||||
* - `password`
|
||||
* - `password-new`
|
||||
* - `postal-address`
|
||||
* - `postal-address-country`
|
||||
* - `postal-address-extended`
|
||||
* - `postal-address-extended-postal-code`
|
||||
* - `postal-address-locality`
|
||||
* - `postal-address-region`
|
||||
* - `postal-code`
|
||||
* - `street-address`
|
||||
* - `sms-otp`
|
||||
* - `tel`
|
||||
* - `tel-country-code`
|
||||
* - `tel-national`
|
||||
* - `tel-device`
|
||||
* - `username`
|
||||
* - `username-new`
|
||||
* - `off`
|
||||
*/
|
||||
autoComplete?:
|
||||
| 'birthdate-day'
|
||||
| 'birthdate-full'
|
||||
| 'birthdate-month'
|
||||
| 'birthdate-year'
|
||||
| 'cc-csc'
|
||||
| 'cc-exp'
|
||||
| 'cc-exp-day'
|
||||
| 'cc-exp-month'
|
||||
| 'cc-exp-year'
|
||||
| 'cc-number'
|
||||
| 'email'
|
||||
| 'gender'
|
||||
| 'name'
|
||||
| 'name-family'
|
||||
| 'name-given'
|
||||
| 'name-middle'
|
||||
| 'name-middle-initial'
|
||||
| 'name-prefix'
|
||||
| 'name-suffix'
|
||||
| 'password'
|
||||
| 'password-new'
|
||||
| 'postal-address'
|
||||
| 'postal-address-country'
|
||||
| 'postal-address-extended'
|
||||
| 'postal-address-extended-postal-code'
|
||||
| 'postal-address-locality'
|
||||
| 'postal-address-region'
|
||||
| 'postal-code'
|
||||
| 'street-address'
|
||||
| 'sms-otp'
|
||||
| 'tel'
|
||||
| 'tel-country-code'
|
||||
| 'tel-national'
|
||||
| 'tel-device'
|
||||
| 'username'
|
||||
| 'username-new'
|
||||
| 'off'
|
||||
| undefined;
|
||||
|
||||
/**
|
||||
* When provided it will set the color of the cursor (or "caret") in the component.
|
||||
* Unlike the behavior of `selectionColor` the cursor color will be set independently
|
||||
@@ -558,6 +472,127 @@ export interface TextInputProps
|
||||
*/
|
||||
autoCapitalize?: 'none' | 'sentences' | 'words' | 'characters' | undefined;
|
||||
|
||||
/**
|
||||
* Specifies autocomplete hints for the system, so it can provide autofill.
|
||||
* On Android, the system will always attempt to offer autofill by using heuristics to identify the type of content.
|
||||
* To disable autocomplete, set autoComplete to off.
|
||||
*
|
||||
* The following values work across platforms:
|
||||
*
|
||||
* - `additional-name`
|
||||
* - `address-line1`
|
||||
* - `address-line2`
|
||||
* - `cc-number`
|
||||
* - `country`
|
||||
* - `current-password`
|
||||
* - `email`
|
||||
* - `family-name`
|
||||
* - `given-name`
|
||||
* - `honorific-prefix`
|
||||
* - `honorific-suffix`
|
||||
* - `name`
|
||||
* - `new-password`
|
||||
* - `off`
|
||||
* - `one-time-code`
|
||||
* - `postal-code`
|
||||
* - `street-address`
|
||||
* - `tel`
|
||||
* - `username`
|
||||
*
|
||||
* The following values work on iOS only:
|
||||
*
|
||||
* - `nickname`
|
||||
* - `organization`
|
||||
* - `organization-title`
|
||||
* - `url`
|
||||
*
|
||||
* The following values work on Android only:
|
||||
*
|
||||
* - `birthdate-day`
|
||||
* - `birthdate-full`
|
||||
* - `birthdate-month`
|
||||
* - `birthdate-year`
|
||||
* - `cc-csc`
|
||||
* - `cc-exp`
|
||||
* - `cc-exp-day`
|
||||
* - `cc-exp-month`
|
||||
* - `cc-exp-year`
|
||||
* - `gender`
|
||||
* - `name-family`
|
||||
* - `name-given`
|
||||
* - `name-middle`
|
||||
* - `name-middle-initial`
|
||||
* - `name-prefix`
|
||||
* - `name-suffix`
|
||||
* - `password`
|
||||
* - `password-new`
|
||||
* - `postal-address`
|
||||
* - `postal-address-country`
|
||||
* - `postal-address-extended`
|
||||
* - `postal-address-extended-postal-code`
|
||||
* - `postal-address-locality`
|
||||
* - `postal-address-region`
|
||||
* - `sms-otp`
|
||||
* - `tel-country-code`
|
||||
* - `tel-national`
|
||||
* - `tel-device`
|
||||
* - `username-new`
|
||||
*/
|
||||
autoComplete?:
|
||||
| 'additional-name'
|
||||
| 'address-line1'
|
||||
| 'address-line2'
|
||||
| 'birthdate-day'
|
||||
| 'birthdate-full'
|
||||
| 'birthdate-month'
|
||||
| 'birthdate-year'
|
||||
| 'cc-csc'
|
||||
| 'cc-exp'
|
||||
| 'cc-exp-day'
|
||||
| 'cc-exp-month'
|
||||
| 'cc-exp-year'
|
||||
| 'cc-number'
|
||||
| 'country'
|
||||
| 'current-password'
|
||||
| 'email'
|
||||
| 'family-name'
|
||||
| 'gender'
|
||||
| 'given-name'
|
||||
| 'honorific-prefix'
|
||||
| 'honorific-suffix'
|
||||
| 'name'
|
||||
| 'name-family'
|
||||
| 'name-given'
|
||||
| 'name-middle'
|
||||
| 'name-middle-initial'
|
||||
| 'name-prefix'
|
||||
| 'name-suffix'
|
||||
| 'new-password'
|
||||
| 'nickname'
|
||||
| 'one-time-code'
|
||||
| 'organization'
|
||||
| 'organization-title'
|
||||
| 'password'
|
||||
| 'password-new'
|
||||
| 'postal-address'
|
||||
| 'postal-address-country'
|
||||
| 'postal-address-extended'
|
||||
| 'postal-address-extended-postal-code'
|
||||
| 'postal-address-locality'
|
||||
| 'postal-address-region'
|
||||
| 'postal-code'
|
||||
| 'street-address'
|
||||
| 'sms-otp'
|
||||
| 'tel'
|
||||
| 'tel-country-code'
|
||||
| 'tel-national'
|
||||
| 'tel-device'
|
||||
| 'url'
|
||||
| 'username'
|
||||
| 'username-new'
|
||||
| 'off'
|
||||
| undefined;
|
||||
|
||||
/**
|
||||
* If false, disables auto-correct.
|
||||
* The default value is true.
|
||||
|
||||
@@ -196,36 +196,6 @@ export type enterKeyHintType =
|
||||
type PasswordRules = string;
|
||||
|
||||
type IOSProps = $ReadOnly<{|
|
||||
/**
|
||||
* Give the keyboard and the system information about the
|
||||
* expected semantic meaning for the content that users enter.
|
||||
* @platform ios
|
||||
*/
|
||||
autoComplete?: ?(
|
||||
| 'address-line1'
|
||||
| 'address-line2'
|
||||
| 'cc-number'
|
||||
| 'current-password'
|
||||
| 'country'
|
||||
| 'email'
|
||||
| 'name'
|
||||
| 'additional-name'
|
||||
| 'family-name'
|
||||
| 'given-name'
|
||||
| 'nickname'
|
||||
| 'honorific-prefix'
|
||||
| 'honorific-suffix'
|
||||
| 'new-password'
|
||||
| 'off'
|
||||
| 'one-time-code'
|
||||
| 'organization'
|
||||
| 'organization-title'
|
||||
| 'postal-code'
|
||||
| 'street-address'
|
||||
| 'tel'
|
||||
| 'url'
|
||||
| 'username'
|
||||
),
|
||||
/**
|
||||
* When the clear button should appear on the right side of the text view.
|
||||
* This property is supported only for single-line TextInput component.
|
||||
@@ -328,111 +298,6 @@ type IOSProps = $ReadOnly<{|
|
||||
|}>;
|
||||
|
||||
type AndroidProps = $ReadOnly<{|
|
||||
/**
|
||||
* Specifies autocomplete hints for the system, so it can provide autofill. On Android, the system will always attempt to offer autofill by using heuristics to identify the type of content.
|
||||
* To disable autocomplete, set `autoComplete` to `off`.
|
||||
*
|
||||
* *Android Only*
|
||||
*
|
||||
* Possible values for `autoComplete` are:
|
||||
*
|
||||
* - `birthdate-day`
|
||||
* - `birthdate-full`
|
||||
* - `birthdate-month`
|
||||
* - `birthdate-year`
|
||||
* - `cc-csc`
|
||||
* - `cc-exp`
|
||||
* - `cc-exp-day`
|
||||
* - `cc-exp-month`
|
||||
* - `cc-exp-year`
|
||||
* - `cc-number`
|
||||
* - `email`
|
||||
* - `gender`
|
||||
* - `name`
|
||||
* - `name-family`
|
||||
* - `name-given`
|
||||
* - `name-middle`
|
||||
* - `name-middle-initial`
|
||||
* - `name-prefix`
|
||||
* - `name-suffix`
|
||||
* - `password`
|
||||
* - `password-new`
|
||||
* - `postal-address`
|
||||
* - `postal-address-country`
|
||||
* - `postal-address-extended`
|
||||
* - `postal-address-extended-postal-code`
|
||||
* - `postal-address-locality`
|
||||
* - `postal-address-region`
|
||||
* - `postal-code`
|
||||
* - `street-address`
|
||||
* - `sms-otp`
|
||||
* - `tel`
|
||||
* - `tel-country-code`
|
||||
* - `tel-national`
|
||||
* - `tel-device`
|
||||
* - `username`
|
||||
* - `username-new`
|
||||
* - `off`
|
||||
*
|
||||
* @platform android
|
||||
*/
|
||||
autoComplete?: ?(
|
||||
| 'birthdate-day'
|
||||
| 'birthdate-full'
|
||||
| 'birthdate-month'
|
||||
| 'birthdate-year'
|
||||
| 'cc-csc'
|
||||
| 'cc-exp'
|
||||
| 'cc-exp-day'
|
||||
| 'cc-exp-month'
|
||||
| 'cc-exp-year'
|
||||
| 'cc-number'
|
||||
| 'email'
|
||||
| 'gender'
|
||||
| 'name'
|
||||
| 'name-family'
|
||||
| 'name-given'
|
||||
| 'name-middle'
|
||||
| 'name-middle-initial'
|
||||
| 'name-prefix'
|
||||
| 'name-suffix'
|
||||
| 'password'
|
||||
| 'password-new'
|
||||
| 'postal-address'
|
||||
| 'postal-address-country'
|
||||
| 'postal-address-extended'
|
||||
| 'postal-address-extended-postal-code'
|
||||
| 'postal-address-locality'
|
||||
| 'postal-address-region'
|
||||
| 'postal-code'
|
||||
| 'street-address'
|
||||
| 'sms-otp'
|
||||
| 'tel'
|
||||
| 'tel-country-code'
|
||||
| 'tel-national'
|
||||
| 'tel-device'
|
||||
| 'username'
|
||||
| 'username-new'
|
||||
| 'off'
|
||||
// additional HTML autocomplete values
|
||||
| 'address-line1'
|
||||
| 'address-line2'
|
||||
| 'bday'
|
||||
| 'bday-day'
|
||||
| 'bday-month'
|
||||
| 'bday-year'
|
||||
| 'country'
|
||||
| 'current-password'
|
||||
| 'honorific-prefix'
|
||||
| 'honorific-suffix'
|
||||
| 'additional-name'
|
||||
| 'family-name'
|
||||
| 'given-name'
|
||||
| 'new-password'
|
||||
| 'one-time-code'
|
||||
| 'sex'
|
||||
),
|
||||
|
||||
/**
|
||||
* When provided it will set the color of the cursor (or "caret") in the component.
|
||||
* Unlike the behavior of `selectionColor` the cursor color will be set independently
|
||||
@@ -533,6 +398,127 @@ export type Props = $ReadOnly<{|
|
||||
*/
|
||||
autoCapitalize?: ?AutoCapitalize,
|
||||
|
||||
/**
|
||||
* Specifies autocomplete hints for the system, so it can provide autofill.
|
||||
* On Android, the system will always attempt to offer autofill by using heuristics to identify the type of content.
|
||||
* To disable autocomplete, set autoComplete to off.
|
||||
*
|
||||
* The following values work across platforms:
|
||||
*
|
||||
* - `additional-name`
|
||||
* - `address-line1`
|
||||
* - `address-line2`
|
||||
* - `cc-number`
|
||||
* - `country`
|
||||
* - `current-password`
|
||||
* - `email`
|
||||
* - `family-name`
|
||||
* - `given-name`
|
||||
* - `honorific-prefix`
|
||||
* - `honorific-suffix`
|
||||
* - `name`
|
||||
* - `new-password`
|
||||
* - `off`
|
||||
* - `one-time-code`
|
||||
* - `postal-code`
|
||||
* - `street-address`
|
||||
* - `tel`
|
||||
* - `username`
|
||||
*
|
||||
* The following values work on iOS only:
|
||||
*
|
||||
* - `nickname`
|
||||
* - `organization`
|
||||
* - `organization-title`
|
||||
* - `url`
|
||||
*
|
||||
* The following values work on Android only:
|
||||
*
|
||||
* - `birthdate-day`
|
||||
* - `birthdate-full`
|
||||
* - `birthdate-month`
|
||||
* - `birthdate-year`
|
||||
* - `cc-csc`
|
||||
* - `cc-exp`
|
||||
* - `cc-exp-day`
|
||||
* - `cc-exp-month`
|
||||
* - `cc-exp-year`
|
||||
* - `gender`
|
||||
* - `name-family`
|
||||
* - `name-given`
|
||||
* - `name-middle`
|
||||
* - `name-middle-initial`
|
||||
* - `name-prefix`
|
||||
* - `name-suffix`
|
||||
* - `password`
|
||||
* - `password-new`
|
||||
* - `postal-address`
|
||||
* - `postal-address-country`
|
||||
* - `postal-address-extended`
|
||||
* - `postal-address-extended-postal-code`
|
||||
* - `postal-address-locality`
|
||||
* - `postal-address-region`
|
||||
* - `sms-otp`
|
||||
* - `tel-country-code`
|
||||
* - `tel-national`
|
||||
* - `tel-device`
|
||||
* - `username-new`
|
||||
*/
|
||||
autoComplete?: ?(
|
||||
| 'additional-name'
|
||||
| 'address-line1'
|
||||
| 'address-line2'
|
||||
| 'birthdate-day'
|
||||
| 'birthdate-full'
|
||||
| 'birthdate-month'
|
||||
| 'birthdate-year'
|
||||
| 'cc-csc'
|
||||
| 'cc-exp'
|
||||
| 'cc-exp-day'
|
||||
| 'cc-exp-month'
|
||||
| 'cc-exp-year'
|
||||
| 'cc-number'
|
||||
| 'country'
|
||||
| 'current-password'
|
||||
| 'email'
|
||||
| 'family-name'
|
||||
| 'gender'
|
||||
| 'given-name'
|
||||
| 'honorific-prefix'
|
||||
| 'honorific-suffix'
|
||||
| 'name'
|
||||
| 'name-family'
|
||||
| 'name-given'
|
||||
| 'name-middle'
|
||||
| 'name-middle-initial'
|
||||
| 'name-prefix'
|
||||
| 'name-suffix'
|
||||
| 'new-password'
|
||||
| 'nickname'
|
||||
| 'one-time-code'
|
||||
| 'organization'
|
||||
| 'organization-title'
|
||||
| 'password'
|
||||
| 'password-new'
|
||||
| 'postal-address'
|
||||
| 'postal-address-country'
|
||||
| 'postal-address-extended'
|
||||
| 'postal-address-extended-postal-code'
|
||||
| 'postal-address-locality'
|
||||
| 'postal-address-region'
|
||||
| 'postal-code'
|
||||
| 'street-address'
|
||||
| 'sms-otp'
|
||||
| 'tel'
|
||||
| 'tel-country-code'
|
||||
| 'tel-national'
|
||||
| 'tel-device'
|
||||
| 'url'
|
||||
| 'username'
|
||||
| 'username-new'
|
||||
| 'off'
|
||||
),
|
||||
|
||||
/**
|
||||
* If `false`, disables auto-correct. The default value is `true`.
|
||||
*/
|
||||
|
||||
+126
-155
@@ -234,36 +234,6 @@ export type enterKeyHintType =
|
||||
type PasswordRules = string;
|
||||
|
||||
type IOSProps = $ReadOnly<{|
|
||||
/**
|
||||
* Give the keyboard and the system information about the
|
||||
* expected semantic meaning for the content that users enter.
|
||||
* @platform ios
|
||||
*/
|
||||
autoComplete?: ?(
|
||||
| 'address-line1'
|
||||
| 'address-line2'
|
||||
| 'cc-number'
|
||||
| 'current-password'
|
||||
| 'country'
|
||||
| 'email'
|
||||
| 'name'
|
||||
| 'additional-name'
|
||||
| 'family-name'
|
||||
| 'given-name'
|
||||
| 'nickname'
|
||||
| 'honorific-prefix'
|
||||
| 'honorific-suffix'
|
||||
| 'new-password'
|
||||
| 'off'
|
||||
| 'one-time-code'
|
||||
| 'organization'
|
||||
| 'organization-title'
|
||||
| 'postal-code'
|
||||
| 'street-address'
|
||||
| 'tel'
|
||||
| 'url'
|
||||
| 'username'
|
||||
),
|
||||
/**
|
||||
* When the clear button should appear on the right side of the text view.
|
||||
* This property is supported only for single-line TextInput component.
|
||||
@@ -369,111 +339,6 @@ type IOSProps = $ReadOnly<{|
|
||||
|}>;
|
||||
|
||||
type AndroidProps = $ReadOnly<{|
|
||||
/**
|
||||
* Specifies autocomplete hints for the system, so it can provide autofill. On Android, the system will always attempt to offer autofill by using heuristics to identify the type of content.
|
||||
* To disable autocomplete, set `autoComplete` to `off`.
|
||||
*
|
||||
* *Android Only*
|
||||
*
|
||||
* Possible values for `autoComplete` are:
|
||||
*
|
||||
* - `birthdate-day`
|
||||
* - `birthdate-full`
|
||||
* - `birthdate-month`
|
||||
* - `birthdate-year`
|
||||
* - `cc-csc`
|
||||
* - `cc-exp`
|
||||
* - `cc-exp-day`
|
||||
* - `cc-exp-month`
|
||||
* - `cc-exp-year`
|
||||
* - `cc-number`
|
||||
* - `email`
|
||||
* - `gender`
|
||||
* - `name`
|
||||
* - `name-family`
|
||||
* - `name-given`
|
||||
* - `name-middle`
|
||||
* - `name-middle-initial`
|
||||
* - `name-prefix`
|
||||
* - `name-suffix`
|
||||
* - `password`
|
||||
* - `password-new`
|
||||
* - `postal-address`
|
||||
* - `postal-address-country`
|
||||
* - `postal-address-extended`
|
||||
* - `postal-address-extended-postal-code`
|
||||
* - `postal-address-locality`
|
||||
* - `postal-address-region`
|
||||
* - `postal-code`
|
||||
* - `street-address`
|
||||
* - `sms-otp`
|
||||
* - `tel`
|
||||
* - `tel-country-code`
|
||||
* - `tel-national`
|
||||
* - `tel-device`
|
||||
* - `username`
|
||||
* - `username-new`
|
||||
* - `off`
|
||||
*
|
||||
* @platform android
|
||||
*/
|
||||
autoComplete?: ?(
|
||||
| 'birthdate-day'
|
||||
| 'birthdate-full'
|
||||
| 'birthdate-month'
|
||||
| 'birthdate-year'
|
||||
| 'cc-csc'
|
||||
| 'cc-exp'
|
||||
| 'cc-exp-day'
|
||||
| 'cc-exp-month'
|
||||
| 'cc-exp-year'
|
||||
| 'cc-number'
|
||||
| 'email'
|
||||
| 'gender'
|
||||
| 'name'
|
||||
| 'name-family'
|
||||
| 'name-given'
|
||||
| 'name-middle'
|
||||
| 'name-middle-initial'
|
||||
| 'name-prefix'
|
||||
| 'name-suffix'
|
||||
| 'password'
|
||||
| 'password-new'
|
||||
| 'postal-address'
|
||||
| 'postal-address-country'
|
||||
| 'postal-address-extended'
|
||||
| 'postal-address-extended-postal-code'
|
||||
| 'postal-address-locality'
|
||||
| 'postal-address-region'
|
||||
| 'postal-code'
|
||||
| 'street-address'
|
||||
| 'sms-otp'
|
||||
| 'tel'
|
||||
| 'tel-country-code'
|
||||
| 'tel-national'
|
||||
| 'tel-device'
|
||||
| 'username'
|
||||
| 'username-new'
|
||||
| 'off'
|
||||
// additional HTML autocomplete values
|
||||
| 'address-line1'
|
||||
| 'address-line2'
|
||||
| 'bday'
|
||||
| 'bday-day'
|
||||
| 'bday-month'
|
||||
| 'bday-year'
|
||||
| 'country'
|
||||
| 'current-password'
|
||||
| 'honorific-prefix'
|
||||
| 'honorific-suffix'
|
||||
| 'additional-name'
|
||||
| 'family-name'
|
||||
| 'given-name'
|
||||
| 'new-password'
|
||||
| 'one-time-code'
|
||||
| 'sex'
|
||||
),
|
||||
|
||||
/**
|
||||
* When provided it will set the color of the cursor (or "caret") in the component.
|
||||
* Unlike the behavior of `selectionColor` the cursor color will be set independently
|
||||
@@ -574,6 +439,127 @@ export type Props = $ReadOnly<{|
|
||||
*/
|
||||
autoCapitalize?: ?AutoCapitalize,
|
||||
|
||||
/**
|
||||
* Specifies autocomplete hints for the system, so it can provide autofill.
|
||||
* On Android, the system will always attempt to offer autofill by using heuristics to identify the type of content.
|
||||
* To disable autocomplete, set autoComplete to off.
|
||||
*
|
||||
* The following values work across platforms:
|
||||
*
|
||||
* - `additional-name`
|
||||
* - `address-line1`
|
||||
* - `address-line2`
|
||||
* - `cc-number`
|
||||
* - `country`
|
||||
* - `current-password`
|
||||
* - `email`
|
||||
* - `family-name`
|
||||
* - `given-name`
|
||||
* - `honorific-prefix`
|
||||
* - `honorific-suffix`
|
||||
* - `name`
|
||||
* - `new-password`
|
||||
* - `off`
|
||||
* - `one-time-code`
|
||||
* - `postal-code`
|
||||
* - `street-address`
|
||||
* - `tel`
|
||||
* - `username`
|
||||
*
|
||||
* The following values work on iOS only:
|
||||
*
|
||||
* - `nickname`
|
||||
* - `organization`
|
||||
* - `organization-title`
|
||||
* - `url`
|
||||
*
|
||||
* The following values work on Android only:
|
||||
*
|
||||
* - `birthdate-day`
|
||||
* - `birthdate-full`
|
||||
* - `birthdate-month`
|
||||
* - `birthdate-year`
|
||||
* - `cc-csc`
|
||||
* - `cc-exp`
|
||||
* - `cc-exp-day`
|
||||
* - `cc-exp-month`
|
||||
* - `cc-exp-year`
|
||||
* - `gender`
|
||||
* - `name-family`
|
||||
* - `name-given`
|
||||
* - `name-middle`
|
||||
* - `name-middle-initial`
|
||||
* - `name-prefix`
|
||||
* - `name-suffix`
|
||||
* - `password`
|
||||
* - `password-new`
|
||||
* - `postal-address`
|
||||
* - `postal-address-country`
|
||||
* - `postal-address-extended`
|
||||
* - `postal-address-extended-postal-code`
|
||||
* - `postal-address-locality`
|
||||
* - `postal-address-region`
|
||||
* - `sms-otp`
|
||||
* - `tel-country-code`
|
||||
* - `tel-national`
|
||||
* - `tel-device`
|
||||
* - `username-new`
|
||||
*/
|
||||
autoComplete?: ?(
|
||||
| 'additional-name'
|
||||
| 'address-line1'
|
||||
| 'address-line2'
|
||||
| 'birthdate-day'
|
||||
| 'birthdate-full'
|
||||
| 'birthdate-month'
|
||||
| 'birthdate-year'
|
||||
| 'cc-csc'
|
||||
| 'cc-exp'
|
||||
| 'cc-exp-day'
|
||||
| 'cc-exp-month'
|
||||
| 'cc-exp-year'
|
||||
| 'cc-number'
|
||||
| 'country'
|
||||
| 'current-password'
|
||||
| 'email'
|
||||
| 'family-name'
|
||||
| 'gender'
|
||||
| 'given-name'
|
||||
| 'honorific-prefix'
|
||||
| 'honorific-suffix'
|
||||
| 'name'
|
||||
| 'name-family'
|
||||
| 'name-given'
|
||||
| 'name-middle'
|
||||
| 'name-middle-initial'
|
||||
| 'name-prefix'
|
||||
| 'name-suffix'
|
||||
| 'new-password'
|
||||
| 'nickname'
|
||||
| 'one-time-code'
|
||||
| 'organization'
|
||||
| 'organization-title'
|
||||
| 'password'
|
||||
| 'password-new'
|
||||
| 'postal-address'
|
||||
| 'postal-address-country'
|
||||
| 'postal-address-extended'
|
||||
| 'postal-address-extended-postal-code'
|
||||
| 'postal-address-locality'
|
||||
| 'postal-address-region'
|
||||
| 'postal-code'
|
||||
| 'street-address'
|
||||
| 'sms-otp'
|
||||
| 'tel'
|
||||
| 'tel-country-code'
|
||||
| 'tel-national'
|
||||
| 'tel-device'
|
||||
| 'url'
|
||||
| 'username'
|
||||
| 'username-new'
|
||||
| 'off'
|
||||
),
|
||||
|
||||
/**
|
||||
* If `false`, disables auto-correct. The default value is `true`.
|
||||
*/
|
||||
@@ -1080,27 +1066,19 @@ function InternalTextInput(props: Props): React.Node {
|
||||
accessibilityState,
|
||||
id,
|
||||
tabIndex,
|
||||
selection: propsSelection,
|
||||
...otherProps
|
||||
} = props;
|
||||
|
||||
const inputRef = useRef<null | React.ElementRef<HostComponent<mixed>>>(null);
|
||||
|
||||
// Android sends a "onTextChanged" event followed by a "onSelectionChanged" event, for
|
||||
// the same "most recent event count".
|
||||
// For controlled selection, that means that immediately after text is updated,
|
||||
// a controlled component will pass in the *previous* selection, even if the controlled
|
||||
// component didn't mean to modify the selection at all.
|
||||
// Therefore, we ignore selections and pass them through until the selection event has
|
||||
// been sent.
|
||||
// Note that this mitigation is NOT needed for Fabric.
|
||||
// discovered when upgrading react-hooks
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
let selection: ?Selection =
|
||||
props.selection == null
|
||||
const selection: ?Selection =
|
||||
propsSelection == null
|
||||
? null
|
||||
: {
|
||||
start: props.selection.start,
|
||||
end: props.selection.end ?? props.selection.start,
|
||||
start: propsSelection.start,
|
||||
end: propsSelection.end ?? propsSelection.start,
|
||||
};
|
||||
|
||||
const [mostRecentEventCount, setMostRecentEventCount] = useState<number>(0);
|
||||
@@ -1112,12 +1090,6 @@ function InternalTextInput(props: Props): React.Node {
|
||||
|}>({selection, mostRecentEventCount});
|
||||
|
||||
const lastNativeSelection = lastNativeSelectionState.selection;
|
||||
const lastNativeSelectionEventCount =
|
||||
lastNativeSelectionState.mostRecentEventCount;
|
||||
|
||||
if (lastNativeSelectionEventCount < mostRecentEventCount) {
|
||||
selection = null;
|
||||
}
|
||||
|
||||
let viewCommands;
|
||||
if (AndroidTextInputCommands) {
|
||||
@@ -1517,7 +1489,6 @@ function InternalTextInput(props: Props): React.Node {
|
||||
onScroll={_onScroll}
|
||||
onSelectionChange={_onSelectionChange}
|
||||
placeholder={placeholder}
|
||||
selection={selection}
|
||||
style={style}
|
||||
text={text}
|
||||
textBreakStrategy={props.textBreakStrategy}
|
||||
|
||||
@@ -46,13 +46,6 @@ const ReactNativeStyleAttributes: {[string]: AnyAttributeType, ...} = {
|
||||
flexWrap: true,
|
||||
gap: true,
|
||||
height: true,
|
||||
inset: true,
|
||||
insetBlock: true,
|
||||
insetBlockEnd: true,
|
||||
insetBlockStart: true,
|
||||
insetInline: true,
|
||||
insetInlineEnd: true,
|
||||
insetInlineStart: true,
|
||||
justifyContent: true,
|
||||
left: true,
|
||||
margin: true,
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
*/
|
||||
|
||||
exports.version = {
|
||||
major: 1000,
|
||||
minor: 0,
|
||||
patch: 0,
|
||||
major: 0,
|
||||
minor: 72,
|
||||
patch: 2,
|
||||
prerelease: null,
|
||||
};
|
||||
|
||||
@@ -39,8 +39,12 @@ exports.checkVersions = function checkVersions(): void {
|
||||
}
|
||||
};
|
||||
|
||||
// Note: in OSS, the prerelease version is usually 0.Y.0-rc.W, so it is a string and not a number
|
||||
// Then we need to keep supporting that object shape.
|
||||
function _formatVersion(
|
||||
version: (typeof Platform)['constants']['reactNativeVersion'],
|
||||
version:
|
||||
| (typeof Platform)['constants']['reactNativeVersion']
|
||||
| {major: number, minor: number, patch: number, prerelease: ?string},
|
||||
): string {
|
||||
return (
|
||||
`${version.major}.${version.minor}.${version.patch}` +
|
||||
|
||||
@@ -28,7 +28,10 @@ header_search_paths = [
|
||||
if ENV["USE_FRAMEWORKS"]
|
||||
header_search_paths = header_search_paths.concat([
|
||||
"\"$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\"",
|
||||
"\"$(PODS_CONFIGURATION_BUILD_DIR)/React-NativeModulesApple/React_NativeModulesApple.framework/Headers\""
|
||||
"\"$(PODS_CONFIGURATION_BUILD_DIR)/React-NativeModulesApple/React_NativeModulesApple.framework/Headers\"",
|
||||
"\"$(PODS_CONFIGURATION_BUILD_DIR)/React-NativeModulesApple/React_NativeModulesApple.framework/Headers/build/generated/ios\"",
|
||||
"\"$(PODS_CONFIGURATION_BUILD_DIR)/React-Codegen/React_Codegen.framework/Headers/build/generated/ios\"",
|
||||
"\"$(PODS_CONFIGURATION_BUILD_DIR)/React-Codegen/React_Codegen.framework/Headers\""
|
||||
])
|
||||
end
|
||||
|
||||
|
||||
@@ -111,6 +111,7 @@ exports[`FlatList renders all the bells and whistles 1`] = `
|
||||
<RCTRefreshControl />
|
||||
<View>
|
||||
<View
|
||||
collapsable={false}
|
||||
onLayout={[Function]}
|
||||
>
|
||||
<header />
|
||||
|
||||
@@ -243,6 +243,7 @@ exports[`SectionList renders all the bells and whistles 1`] = `
|
||||
<RCTRefreshControl />
|
||||
<View>
|
||||
<View
|
||||
collapsable={false}
|
||||
onLayout={[Function]}
|
||||
>
|
||||
<header
|
||||
|
||||
@@ -258,14 +258,6 @@ const validAttributesForNonEventProps = {
|
||||
top: true,
|
||||
bottom: true,
|
||||
|
||||
inset: true,
|
||||
insetBlock: true,
|
||||
insetBlockEnd: true,
|
||||
insetBlockStart: true,
|
||||
insetInline: true,
|
||||
insetInlineEnd: true,
|
||||
insetInlineStart: true,
|
||||
|
||||
position: true,
|
||||
|
||||
style: ReactNativeStyleAttributes,
|
||||
|
||||
@@ -236,14 +236,6 @@ const validAttributesForNonEventProps = {
|
||||
bottom: true,
|
||||
left: true,
|
||||
|
||||
inset: true,
|
||||
insetBlock: true,
|
||||
insetBlockEnd: true,
|
||||
insetBlockStart: true,
|
||||
insetInline: true,
|
||||
insetInlineEnd: true,
|
||||
insetInlineStart: true,
|
||||
|
||||
width: true,
|
||||
height: true,
|
||||
|
||||
|
||||
@@ -28,7 +28,11 @@ header_search_paths = [
|
||||
if ENV["USE_FRAMEWORKS"]
|
||||
header_search_paths = header_search_paths.concat([
|
||||
"\"$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\"",
|
||||
"\"$(PODS_CONFIGURATION_BUILD_DIR)/React-NativeModulesApple/React_NativeModulesApple.framework/Headers\""
|
||||
"\"$(PODS_CONFIGURATION_BUILD_DIR)/React-NativeModulesApple/React_NativeModulesApple.framework/Headers\"",
|
||||
"\"$(PODS_CONFIGURATION_BUILD_DIR)/React-NativeModulesApple/React_NativeModulesApple.framework/Headers/build/generated/ios\"",
|
||||
"\"$(PODS_CONFIGURATION_BUILD_DIR)/React-Codegen/React_Codegen.framework/Headers/build/generated/ios\"",
|
||||
"\"$(PODS_CONFIGURATION_BUILD_DIR)/React-Codegen/React_Codegen.framework/Headers\"",
|
||||
|
||||
])
|
||||
end
|
||||
|
||||
|
||||
@@ -75,7 +75,6 @@ const PERMISSIONS = Object.freeze({
|
||||
ANSWER_PHONE_CALLS: 'android.permission.ANSWER_PHONE_CALLS',
|
||||
READ_PHONE_NUMBERS: 'android.permission.READ_PHONE_NUMBERS',
|
||||
UWB_RANGING: 'android.permission.UWB_RANGING',
|
||||
POST_NOTIFICATION: 'android.permission.POST_NOTIFICATIONS', // Remove in 0.72
|
||||
POST_NOTIFICATIONS: 'android.permission.POST_NOTIFICATIONS',
|
||||
NEARBY_WIFI_DEVICES: 'android.permission.NEARBY_WIFI_DEVICES',
|
||||
});
|
||||
@@ -107,7 +106,6 @@ class PermissionsAndroid {
|
||||
CAMERA: string,
|
||||
GET_ACCOUNTS: string,
|
||||
NEARBY_WIFI_DEVICES: string,
|
||||
POST_NOTIFICATION: string, // Remove in 0.72
|
||||
POST_NOTIFICATIONS: string,
|
||||
PROCESS_OUTGOING_CALLS: string,
|
||||
READ_CALENDAR: string,
|
||||
|
||||
+27
-1
@@ -9,7 +9,6 @@
|
||||
*/
|
||||
|
||||
import type {RootTag} from '../Types/RootTagTypes';
|
||||
import type {Spec as FabricUIManagerSpec} from './FabricUIManager';
|
||||
import type {Spec} from './NativeUIManager';
|
||||
|
||||
import {getFabricUIManager} from './FabricUIManager';
|
||||
@@ -175,6 +174,33 @@ const UIManager = {
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
dispatchViewManagerCommand(
|
||||
reactTag: number,
|
||||
commandName: number | string,
|
||||
commandArgs: any[],
|
||||
) {
|
||||
if (isFabricReactTag(reactTag)) {
|
||||
const FabricUIManager = nullthrows(getFabricUIManager());
|
||||
const shadowNode =
|
||||
FabricUIManager.findShadowNodeByTag_DEPRECATED(reactTag);
|
||||
if (shadowNode) {
|
||||
// Transform the accidental CommandID into a CommandName which is the stringified number.
|
||||
// The interop layer knows how to convert this number into the right method name.
|
||||
// Stringify a string is a no-op, so it's safe.
|
||||
commandName = `${commandName}`;
|
||||
FabricUIManager.dispatchCommand(shadowNode, commandName, commandArgs);
|
||||
}
|
||||
} else {
|
||||
UIManagerImpl.dispatchViewManagerCommand(
|
||||
reactTag,
|
||||
// We have some legacy components that are actually already using strings. ¯\_(ツ)_/¯
|
||||
// $FlowFixMe[incompatible-call]
|
||||
commandName,
|
||||
commandArgs,
|
||||
);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = UIManager;
|
||||
|
||||
+26
-3
@@ -3419,6 +3419,23 @@ function mountSafeCallback_NOT_REALLY_SAFE(context, callback) {
|
||||
return callback.apply(context, arguments);
|
||||
};
|
||||
}
|
||||
function warnForStyleProps(props, validAttributes) {
|
||||
{
|
||||
for (var key in validAttributes.style) {
|
||||
if (!(validAttributes[key] || props[key] === undefined)) {
|
||||
error(
|
||||
"You are setting the style `{ %s" +
|
||||
": ... }` as a prop. You " +
|
||||
"should nest it in a style object. " +
|
||||
"E.g. `{ style: { %s" +
|
||||
": ... } }`",
|
||||
key,
|
||||
key
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Modules provided by RN:
|
||||
var emptyObject = {};
|
||||
@@ -5100,7 +5117,8 @@ var _nativeFabricUIManage = nativeFabricUIManager,
|
||||
FabricDefaultPriority = _nativeFabricUIManage.unstable_DefaultEventPriority,
|
||||
FabricDiscretePriority = _nativeFabricUIManage.unstable_DiscreteEventPriority,
|
||||
fabricGetCurrentEventPriority =
|
||||
_nativeFabricUIManage.unstable_getCurrentEventPriority;
|
||||
_nativeFabricUIManage.unstable_getCurrentEventPriority,
|
||||
_setNativeProps = _nativeFabricUIManage.setNativeProps;
|
||||
var getViewConfigForType =
|
||||
ReactNativePrivateInterface.ReactNativeViewConfigRegistry.get; // Counter for uniquely identifying views.
|
||||
// % 10 === 1 means it is a rootTag.
|
||||
@@ -5199,10 +5217,15 @@ var ReactFabricHostComponent = /*#__PURE__*/ (function() {
|
||||
|
||||
_proto.setNativeProps = function setNativeProps(nativeProps) {
|
||||
{
|
||||
error("Warning: setNativeProps is not currently supported in Fabric");
|
||||
warnForStyleProps(nativeProps, this.viewConfig.validAttributes);
|
||||
}
|
||||
|
||||
return;
|
||||
var updatePayload = create(nativeProps, this.viewConfig.validAttributes);
|
||||
var stateNode = this._internalInstanceHandle.stateNode;
|
||||
|
||||
if (stateNode != null && updatePayload != null) {
|
||||
_setNativeProps(stateNode.node, updatePayload);
|
||||
}
|
||||
}; // This API (addEventListener, removeEventListener) attempts to adhere to the
|
||||
// w3 Level2 Events spec as much as possible, treating HostComponent as a DOM node.
|
||||
//
|
||||
|
||||
+13
-1
@@ -1922,6 +1922,7 @@ var _nativeFabricUIManage = nativeFabricUIManager,
|
||||
FabricDiscretePriority = _nativeFabricUIManage.unstable_DiscreteEventPriority,
|
||||
fabricGetCurrentEventPriority =
|
||||
_nativeFabricUIManage.unstable_getCurrentEventPriority,
|
||||
_setNativeProps = _nativeFabricUIManage.setNativeProps,
|
||||
getViewConfigForType =
|
||||
ReactNativePrivateInterface.ReactNativeViewConfigRegistry.get,
|
||||
nextReactTag = 2;
|
||||
@@ -1979,7 +1980,18 @@ var ReactFabricHostComponent = (function() {
|
||||
);
|
||||
}
|
||||
};
|
||||
_proto.setNativeProps = function() {};
|
||||
_proto.setNativeProps = function(nativeProps) {
|
||||
nativeProps = diffProperties(
|
||||
null,
|
||||
emptyObject,
|
||||
nativeProps,
|
||||
this.viewConfig.validAttributes
|
||||
);
|
||||
var stateNode = this._internalInstanceHandle.stateNode;
|
||||
null != stateNode &&
|
||||
null != nativeProps &&
|
||||
_setNativeProps(stateNode.node, nativeProps);
|
||||
};
|
||||
_proto.addEventListener_unstable = function(eventType, listener, options) {
|
||||
if ("string" !== typeof eventType)
|
||||
throw Error("addEventListener_unstable eventType must be a string");
|
||||
|
||||
+13
-1
@@ -1981,6 +1981,7 @@ var _nativeFabricUIManage = nativeFabricUIManager,
|
||||
FabricDiscretePriority = _nativeFabricUIManage.unstable_DiscreteEventPriority,
|
||||
fabricGetCurrentEventPriority =
|
||||
_nativeFabricUIManage.unstable_getCurrentEventPriority,
|
||||
_setNativeProps = _nativeFabricUIManage.setNativeProps,
|
||||
getViewConfigForType =
|
||||
ReactNativePrivateInterface.ReactNativeViewConfigRegistry.get,
|
||||
nextReactTag = 2;
|
||||
@@ -2038,7 +2039,18 @@ var ReactFabricHostComponent = (function() {
|
||||
);
|
||||
}
|
||||
};
|
||||
_proto.setNativeProps = function() {};
|
||||
_proto.setNativeProps = function(nativeProps) {
|
||||
nativeProps = diffProperties(
|
||||
null,
|
||||
emptyObject,
|
||||
nativeProps,
|
||||
this.viewConfig.validAttributes
|
||||
);
|
||||
var stateNode = this._internalInstanceHandle.stateNode;
|
||||
null != stateNode &&
|
||||
null != nativeProps &&
|
||||
_setNativeProps(stateNode.node, nativeProps);
|
||||
};
|
||||
_proto.addEventListener_unstable = function(eventType, listener, options) {
|
||||
if ("string" !== typeof eventType)
|
||||
throw Error("addEventListener_unstable eventType must be a string");
|
||||
|
||||
@@ -28,7 +28,10 @@ header_search_paths = [
|
||||
if ENV["USE_FRAMEWORKS"]
|
||||
header_search_paths = header_search_paths.concat([
|
||||
"\"$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\"",
|
||||
"\"$(PODS_CONFIGURATION_BUILD_DIR)/React-NativeModulesApple/React_NativeModulesApple.framework/Headers\""
|
||||
"\"$(PODS_CONFIGURATION_BUILD_DIR)/React-NativeModulesApple/React_NativeModulesApple.framework/Headers\"",
|
||||
"\"$(PODS_CONFIGURATION_BUILD_DIR)/React-NativeModulesApple/React_NativeModulesApple.framework/Headers/build/generated/ios\"",
|
||||
"\"$(PODS_CONFIGURATION_BUILD_DIR)/React-Codegen/React_Codegen.framework/Headers/build/generated/ios\"",
|
||||
"\"$(PODS_CONFIGURATION_BUILD_DIR)/React-Codegen/React_Codegen.framework/Headers\"",
|
||||
])
|
||||
end
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ type FlexAlignType =
|
||||
| 'stretch'
|
||||
| 'baseline';
|
||||
|
||||
type DimensionValue =
|
||||
export type DimensionValue =
|
||||
| number
|
||||
| 'auto'
|
||||
| `${number}%`
|
||||
@@ -69,13 +69,6 @@ export interface FlexStyle {
|
||||
flexShrink?: number | undefined;
|
||||
flexWrap?: 'wrap' | 'nowrap' | 'wrap-reverse' | undefined;
|
||||
height?: DimensionValue | undefined;
|
||||
inset?: DimensionValue | undefined;
|
||||
insetBlock?: DimensionValue | undefined;
|
||||
insetBlockEnd?: DimensionValue | undefined;
|
||||
insetBlockStart?: DimensionValue | undefined;
|
||||
insetInline?: DimensionValue | undefined;
|
||||
insetInlineEnd?: DimensionValue | undefined;
|
||||
insetInlineStart?: DimensionValue | undefined;
|
||||
justifyContent?:
|
||||
| 'flex-start'
|
||||
| 'flex-end'
|
||||
@@ -86,15 +79,9 @@ export interface FlexStyle {
|
||||
| undefined;
|
||||
left?: DimensionValue | undefined;
|
||||
margin?: DimensionValue | undefined;
|
||||
marginBlock?: DimensionValue | undefined;
|
||||
marginBlockEnd?: DimensionValue | undefined;
|
||||
marginBlockStart?: DimensionValue | undefined;
|
||||
marginBottom?: DimensionValue | undefined;
|
||||
marginEnd?: DimensionValue | undefined;
|
||||
marginHorizontal?: DimensionValue | undefined;
|
||||
marginInline?: DimensionValue | undefined;
|
||||
marginInlineEnd?: DimensionValue | undefined;
|
||||
marginInlineStart?: DimensionValue | undefined;
|
||||
marginLeft?: DimensionValue | undefined;
|
||||
marginRight?: DimensionValue | undefined;
|
||||
marginStart?: DimensionValue | undefined;
|
||||
@@ -107,14 +94,8 @@ export interface FlexStyle {
|
||||
overflow?: 'visible' | 'hidden' | 'scroll' | undefined;
|
||||
padding?: DimensionValue | undefined;
|
||||
paddingBottom?: DimensionValue | undefined;
|
||||
paddingBlock?: DimensionValue | undefined;
|
||||
paddingBlockEnd?: DimensionValue | undefined;
|
||||
paddingBlockStart?: DimensionValue | undefined;
|
||||
paddingEnd?: DimensionValue | undefined;
|
||||
paddingHorizontal?: DimensionValue | undefined;
|
||||
paddingInline?: DimensionValue | undefined;
|
||||
paddingInlineEnd?: DimensionValue | undefined;
|
||||
paddingInlineStart?: DimensionValue | undefined;
|
||||
paddingLeft?: DimensionValue | undefined;
|
||||
paddingRight?: DimensionValue | undefined;
|
||||
paddingStart?: DimensionValue | undefined;
|
||||
|
||||
@@ -134,80 +134,6 @@ type ____LayoutStyle_Internal = $ReadOnly<{
|
||||
*/
|
||||
top?: DimensionValue,
|
||||
|
||||
/** `inset` is a shorthand that corresponds to the top, right, bottom, and/or left properties.
|
||||
*
|
||||
* It works similarly to `inset` in CSS, but in React Native you
|
||||
* must use points or percentages. Ems and other units are not supported.
|
||||
*
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/CSS/inset
|
||||
* for more details of how `inset` affects layout.
|
||||
*/
|
||||
inset?: DimensionValue,
|
||||
|
||||
/** `insetBlock` is a shorthand that corresponds to the `insetBlockStart` and `insetBlockEnd` properties.
|
||||
*
|
||||
* It works similarly to `inset-block` in CSS, but in React Native you
|
||||
* must use points or percentages. Ems and other units are not supported.
|
||||
*
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/CSS/inset-block
|
||||
* for more details of how `inset-block` affects layout.
|
||||
*/
|
||||
insetBlock?: DimensionValue,
|
||||
|
||||
/** `insetBlockEnd` is a logical property that sets the length that an
|
||||
* element is offset in the block direction from its ending edge.
|
||||
*
|
||||
* It works similarly to `inset-block-end` in CSS, but in React Native you
|
||||
* must use points or percentages. Ems and other units are not supported.
|
||||
*
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/CSS/inset-block-end
|
||||
* for more details of how `inset-block-end` affects layout.
|
||||
*/
|
||||
insetBlockEnd?: DimensionValue,
|
||||
|
||||
/** `insetBlockStart` is a logical property that sets the length that an
|
||||
* element is offset in the block direction from its starting edge.
|
||||
*
|
||||
* It works similarly to `inset-block-start` in CSS, but in React Native you
|
||||
* must use points or percentages. Ems and other units are not supported.
|
||||
*
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/CSS/inset-block-start
|
||||
* for more details of how `inset-block-start` affects layout.
|
||||
*/
|
||||
insetBlockStart?: DimensionValue,
|
||||
|
||||
/** `insetInline` is a shorthand that corresponds to the `insetInlineStart` and `insetInlineEnd` properties.
|
||||
*
|
||||
* It works similarly to `inset-inline` in CSS, but in React Native you
|
||||
* must use points or percentages. Ems and other units are not supported.
|
||||
*
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/CSS/inset-inline
|
||||
* for more details of how `inset-inline` affects layout.
|
||||
*/
|
||||
insetInline?: DimensionValue,
|
||||
|
||||
/** `insetInlineEnd` is a logical property that sets the length that an
|
||||
* element is offset in the starting inline direction.
|
||||
*
|
||||
* It works similarly to `inset-inline-end` in CSS, but in React Native you
|
||||
* must use points or percentages. Ems and other units are not supported.
|
||||
*
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/CSS/inset-inline-end
|
||||
* for more details of how `inset-inline-end` affects layout.
|
||||
*/
|
||||
insetInlineEnd?: DimensionValue,
|
||||
|
||||
/** `insetInlineStart` is a logical property that sets the length that an
|
||||
* element is offset in the starting inline direction.
|
||||
*
|
||||
* It works similarly to `inset-inline-start` in CSS, but in React Native you
|
||||
* must use points or percentages. Ems and other units are not supported.
|
||||
*
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/CSS/inset-inline-start
|
||||
* for more details of how `inset-inline-start` affects layout.
|
||||
*/
|
||||
insetInlineStart?: DimensionValue,
|
||||
|
||||
/** `minWidth` is the minimum width for this component, in logical pixels.
|
||||
*
|
||||
* It works similarly to `min-width` in CSS, but in React Native you
|
||||
|
||||
@@ -260,17 +260,17 @@ static void *TextFieldSelectionObservingContext = &TextFieldSelectionObservingCo
|
||||
_ignoreNextTextInputCall = NO;
|
||||
return;
|
||||
}
|
||||
_lastStringStateWasUpdatedWith = _backedTextInputView.attributedText;
|
||||
_textDidChangeIsComing = NO;
|
||||
[_backedTextInputView.textInputDelegate textInputDidChange];
|
||||
}
|
||||
|
||||
- (void)textViewDidChangeSelection:(__unused UITextView *)textView
|
||||
{
|
||||
if (![_lastStringStateWasUpdatedWith isEqual:_backedTextInputView.attributedText]) {
|
||||
if (_lastStringStateWasUpdatedWith && ![_lastStringStateWasUpdatedWith isEqual:_backedTextInputView.attributedText]) {
|
||||
[self textViewDidChange:_backedTextInputView];
|
||||
_ignoreNextTextInputCall = YES;
|
||||
}
|
||||
_lastStringStateWasUpdatedWith = _backedTextInputView.attributedText;
|
||||
[self textViewProbablyDidChangeSelection];
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,9 @@ header_search_paths = [
|
||||
if ENV["USE_FRAMEWORKS"]
|
||||
header_search_paths = header_search_paths.concat([
|
||||
"\"$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\"",
|
||||
"\"$(PODS_CONFIGURATION_BUILD_DIR)/React-NativeModulesApple/React_NativeModulesApple.framework/Headers\""
|
||||
"\"$(PODS_CONFIGURATION_BUILD_DIR)/React-NativeModulesApple/React_NativeModulesApple.framework/Headers\"",
|
||||
"\"$(PODS_CONFIGURATION_BUILD_DIR)/React-Codegen/React_Codegen.framework/Headers/build/generated/ios\"",
|
||||
"\"$(PODS_CONFIGURATION_BUILD_DIR)/React-Codegen/React_Codegen.framework/Headers\""
|
||||
])
|
||||
end
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ end
|
||||
|
||||
folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
|
||||
folly_version = '2021.07.22.00'
|
||||
socket_rocket_version = '0.6.0'
|
||||
socket_rocket_version = '0.6.1'
|
||||
boost_compiler_flags = '-Wno-documentation'
|
||||
|
||||
use_hermes = ENV['USE_HERMES'] == '1'
|
||||
@@ -126,11 +126,13 @@ Pod::Spec.new do |s|
|
||||
end
|
||||
|
||||
s.dependency "RCT-Folly", folly_version
|
||||
s.dependency "React-cxxreact", version
|
||||
s.dependency "React-perflogger", version
|
||||
s.dependency "React-jsi", version
|
||||
s.dependency "React-jsiexecutor", version
|
||||
s.dependency "React-cxxreact"
|
||||
s.dependency "React-perflogger"
|
||||
s.dependency "React-jsi"
|
||||
s.dependency "React-jsiexecutor"
|
||||
s.dependency "React-utils"
|
||||
s.dependency "SocketRocket", socket_rocket_version
|
||||
s.dependency "React-runtimeexecutor"
|
||||
s.dependency "Yoga"
|
||||
s.dependency "glog"
|
||||
|
||||
|
||||
@@ -312,7 +312,17 @@ static void attemptAsynchronousLoadOfBundleAtURL(
|
||||
return;
|
||||
}
|
||||
|
||||
RCTSource *source = RCTSourceCreate(scriptURL, data, data.length);
|
||||
// Prefer `Content-Location` as the canonical source URL, if given, or fall back to scriptURL.
|
||||
NSURL *sourceURL = scriptURL;
|
||||
NSString *contentLocationHeader = headers[@"Content-Location"];
|
||||
if (contentLocationHeader) {
|
||||
NSURL *contentLocationURL = [NSURL URLWithString:contentLocationHeader relativeToURL:scriptURL];
|
||||
if (contentLocationURL) {
|
||||
sourceURL = contentLocationURL;
|
||||
}
|
||||
}
|
||||
|
||||
RCTSource *source = RCTSourceCreate(sourceURL, data, data.length);
|
||||
parseHeaders(headers, source);
|
||||
onComplete(nil, source);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* 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 <Foundation/Foundation.h>
|
||||
#ifdef __cplusplus
|
||||
#import <ReactCommon/RuntimeExecutor.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class RCTBridge;
|
||||
|
||||
facebook::react::RuntimeExecutor RCTRuntimeExecutorFromBridge(RCTBridge *bridge);
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
#endif
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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 "RCTRuntimeExecutorFromBridge.h"
|
||||
#import <React/RCTAssert.h>
|
||||
#import <React/RCTBridge+Private.h>
|
||||
#import <cxxreact/MessageQueueThread.h>
|
||||
#import <react/utils/ManagedObjectWrapper.h>
|
||||
|
||||
using namespace facebook::react;
|
||||
|
||||
@interface RCTBridge ()
|
||||
- (std::shared_ptr<MessageQueueThread>)jsMessageThread;
|
||||
- (void)invokeAsync:(std::function<void()> &&)func;
|
||||
@end
|
||||
|
||||
RuntimeExecutor RCTRuntimeExecutorFromBridge(RCTBridge *bridge)
|
||||
{
|
||||
RCTAssert(bridge, @"RCTRuntimeExecutorFromBridge: Bridge must not be nil.");
|
||||
|
||||
auto bridgeWeakWrapper = wrapManagedObjectWeakly([bridge batchedBridge] ?: bridge);
|
||||
|
||||
RuntimeExecutor runtimeExecutor = [bridgeWeakWrapper](
|
||||
std::function<void(facebook::jsi::Runtime & runtime)> &&callback) {
|
||||
RCTBridge *bridge = unwrapManagedObjectWeakly(bridgeWeakWrapper);
|
||||
|
||||
RCTAssert(bridge, @"RCTRuntimeExecutorFromBridge: Bridge must not be nil at the moment of scheduling a call.");
|
||||
|
||||
[bridge invokeAsync:[bridgeWeakWrapper, callback = std::move(callback)]() {
|
||||
RCTCxxBridge *batchedBridge = (RCTCxxBridge *)unwrapManagedObjectWeakly(bridgeWeakWrapper);
|
||||
|
||||
RCTAssert(batchedBridge, @"RCTRuntimeExecutorFromBridge: Bridge must not be nil at the moment of invocation.");
|
||||
|
||||
if (!batchedBridge) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto runtime = (facebook::jsi::Runtime *)(batchedBridge.runtime);
|
||||
|
||||
RCTAssert(
|
||||
runtime, @"RCTRuntimeExecutorFromBridge: Bridge must have a valid jsi::Runtime at the moment of invocation.");
|
||||
|
||||
if (!runtime) {
|
||||
return;
|
||||
}
|
||||
|
||||
callback(*runtime);
|
||||
}];
|
||||
};
|
||||
|
||||
return runtimeExecutor;
|
||||
}
|
||||
@@ -21,9 +21,9 @@ NSDictionary* RCTGetReactNativeVersion(void)
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^(void){
|
||||
__rnVersion = @{
|
||||
RCTVersionMajor: @(1000),
|
||||
RCTVersionMinor: @(0),
|
||||
RCTVersionPatch: @(0),
|
||||
RCTVersionMajor: @(0),
|
||||
RCTVersionMinor: @(72),
|
||||
RCTVersionPatch: @(2),
|
||||
RCTVersionPrerelease: [NSNull null],
|
||||
};
|
||||
});
|
||||
|
||||
@@ -428,10 +428,10 @@ RCT_EXPORT_METHOD(show)
|
||||
? UIAlertControllerStyleActionSheet
|
||||
: UIAlertControllerStyleAlert;
|
||||
|
||||
NSString *debugMenuType = self.bridge ? @"Bridge" : @"Bridgeless";
|
||||
NSString *debugMenuTitle = [NSString stringWithFormat:@"React Native Debug Menu (%@)", debugMenuType];
|
||||
NSString *devMenuType = self.bridge ? @"Bridge" : @"Bridgeless";
|
||||
NSString *devMenuTitle = [NSString stringWithFormat:@"React Native Dev Menu (%@)", devMenuType];
|
||||
|
||||
_actionSheet = [UIAlertController alertControllerWithTitle:debugMenuTitle message:description preferredStyle:style];
|
||||
_actionSheet = [UIAlertController alertControllerWithTitle:devMenuTitle message:description preferredStyle:style];
|
||||
|
||||
NSArray<RCTDevMenuItem *> *items = [self _menuItemsToPresent];
|
||||
for (RCTDevMenuItem *item in items) {
|
||||
|
||||
@@ -18,7 +18,7 @@ end
|
||||
|
||||
folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
|
||||
folly_version = '2021.07.22.00'
|
||||
socket_rocket_version = '0.6.0'
|
||||
socket_rocket_version = '0.6.1'
|
||||
|
||||
header_search_paths = [
|
||||
"\"$(PODS_TARGET_SRCROOT)/React/CoreModules\"",
|
||||
|
||||
@@ -475,6 +475,7 @@ struct RCTInstanceCallback : public InstanceCallback {
|
||||
// Load the source asynchronously, then store it for later execution.
|
||||
dispatch_group_enter(prepareBridge);
|
||||
__block NSData *sourceCode;
|
||||
__block NSURL *sourceURL = self.bundleURL;
|
||||
|
||||
#if (RCT_DEV | RCT_ENABLE_LOADING_VIEW) && __has_include(<React/RCTDevLoadingViewProtocol.h>)
|
||||
{
|
||||
@@ -490,6 +491,9 @@ struct RCTInstanceCallback : public InstanceCallback {
|
||||
}
|
||||
|
||||
sourceCode = source.data;
|
||||
if (source.url) {
|
||||
sourceURL = source.url;
|
||||
}
|
||||
dispatch_group_leave(prepareBridge);
|
||||
}
|
||||
onProgress:^(RCTLoadingProgress *progressData) {
|
||||
@@ -504,7 +508,7 @@ struct RCTInstanceCallback : public InstanceCallback {
|
||||
dispatch_group_notify(prepareBridge, dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{
|
||||
RCTCxxBridge *strongSelf = weakSelf;
|
||||
if (sourceCode && strongSelf.loading) {
|
||||
[strongSelf executeSourceCode:sourceCode sync:NO];
|
||||
[strongSelf executeSourceCode:sourceCode withSourceURL:sourceURL sync:NO];
|
||||
}
|
||||
});
|
||||
RCT_PROFILE_END_EVENT(RCTProfileTagAlways, @"");
|
||||
@@ -1050,7 +1054,7 @@ struct RCTInstanceCallback : public InstanceCallback {
|
||||
[_displayLink registerModuleForFrameUpdates:module withModuleData:moduleData];
|
||||
}
|
||||
|
||||
- (void)executeSourceCode:(NSData *)sourceCode sync:(BOOL)sync
|
||||
- (void)executeSourceCode:(NSData *)sourceCode withSourceURL:(NSURL *)url sync:(BOOL)sync
|
||||
{
|
||||
// This will get called from whatever thread was actually executing JS.
|
||||
dispatch_block_t completion = ^{
|
||||
@@ -1075,12 +1079,13 @@ struct RCTInstanceCallback : public InstanceCallback {
|
||||
};
|
||||
|
||||
if (sync) {
|
||||
[self executeApplicationScriptSync:sourceCode url:self.bundleURL];
|
||||
[self executeApplicationScriptSync:sourceCode url:url];
|
||||
completion();
|
||||
} else {
|
||||
[self enqueueApplicationScript:sourceCode url:self.bundleURL onComplete:completion];
|
||||
[self enqueueApplicationScript:sourceCode url:url onComplete:completion];
|
||||
}
|
||||
|
||||
// Use the original request URL here - HMRClient uses this to derive the /hot URL and entry point.
|
||||
[self.devSettings setupHMRClientWithBundleURL:self.bundleURL];
|
||||
}
|
||||
|
||||
|
||||
+15
-1
@@ -14,6 +14,7 @@
|
||||
#import <react/renderer/components/image/ImageComponentDescriptor.h>
|
||||
#import <react/renderer/components/image/ImageEventEmitter.h>
|
||||
#import <react/renderer/components/image/ImageProps.h>
|
||||
#import <react/renderer/core/CoreFeatures.h>
|
||||
#import <react/renderer/imagemanager/ImageRequest.h>
|
||||
#import <react/renderer/imagemanager/RCTImagePrimitivesConversions.h>
|
||||
|
||||
@@ -97,8 +98,21 @@ using namespace facebook::react;
|
||||
- (void)_setStateAndResubscribeImageResponseObserver:(ImageShadowNode::ConcreteState::Shared const &)state
|
||||
{
|
||||
if (_state) {
|
||||
auto &observerCoordinator = _state->getData().getImageRequest().getObserverCoordinator();
|
||||
auto const &imageRequest = _state->getData().getImageRequest();
|
||||
auto &observerCoordinator = imageRequest.getObserverCoordinator();
|
||||
observerCoordinator.removeObserver(_imageResponseObserverProxy);
|
||||
if (CoreFeatures::cancelImageDownloadsOnRecycle) {
|
||||
// Cancelling image request because we are no longer observing it.
|
||||
// This is not 100% correct place to do this because we may want to
|
||||
// re-create RCTImageComponentView with the same image and if it
|
||||
// was cancelled before downloaded, download is not resumed.
|
||||
// This will only become issue if we decouple life cycle of a
|
||||
// ShadowNode from ComponentView, which is not something we do now.
|
||||
imageRequest.cancel();
|
||||
imageRequest.cancel();
|
||||
imageRequest.cancel();
|
||||
imageRequest.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
_state = state;
|
||||
|
||||
+3
-1
@@ -24,6 +24,7 @@
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[_coordinator removeViewFromRegistryWithTag:_tag];
|
||||
[_paperView removeFromSuperview];
|
||||
[_coordinator removeObserveForTag:_tag];
|
||||
}
|
||||
@@ -39,6 +40,7 @@
|
||||
weakSelf.eventInterceptor(eventName, event);
|
||||
}
|
||||
}];
|
||||
[_coordinator addViewToRegistry:_paperView withTag:_tag];
|
||||
}
|
||||
return _paperView;
|
||||
}
|
||||
@@ -50,7 +52,7 @@
|
||||
|
||||
- (void)handleCommand:(NSString *)commandName args:(NSArray *)args
|
||||
{
|
||||
[_coordinator handleCommand:commandName args:args reactTag:_tag];
|
||||
[_coordinator handleCommand:commandName args:args reactTag:_tag paperView:self.paperView];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#import <React/RCTAssert.h>
|
||||
#import <React/RCTConversions.h>
|
||||
#import <React/RCTLog.h>
|
||||
|
||||
#import <butter/map.h>
|
||||
#import <butter/set.h>
|
||||
@@ -105,16 +106,21 @@ static Class<RCTComponentViewProtocol> RCTComponentViewClassWithName(const char
|
||||
return YES;
|
||||
}
|
||||
|
||||
// Paper name: we prepare this variables to warn the user
|
||||
// when the component is registered in both Fabric and in the
|
||||
// interop layer, so they can remove that
|
||||
NSString *componentNameString = RCTNSStringFromString(name);
|
||||
BOOL isRegisteredInInteropLayer = [RCTLegacyViewManagerInteropComponentView isSupported:componentNameString];
|
||||
|
||||
// Fallback 1: Call provider function for component view class.
|
||||
Class<RCTComponentViewProtocol> klass = RCTComponentViewClassWithName(name.c_str());
|
||||
if (klass) {
|
||||
[self registerComponentViewClass:klass];
|
||||
[self registerComponentViewClass:klass andWarnIfNeeded:isRegisteredInInteropLayer];
|
||||
return YES;
|
||||
}
|
||||
|
||||
// Fallback 2: Try to use Paper Interop.
|
||||
NSString *componentNameString = RCTNSStringFromString(name);
|
||||
if ([RCTLegacyViewManagerInteropComponentView isSupported:componentNameString]) {
|
||||
if (isRegisteredInInteropLayer) {
|
||||
RCTLogNewArchitectureValidation(
|
||||
RCTNotAllowedInBridgeless,
|
||||
self,
|
||||
@@ -203,4 +209,17 @@ static Class<RCTComponentViewProtocol> RCTComponentViewClassWithName(const char
|
||||
return _providerRegistry.createComponentDescriptorRegistry(parameters);
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (void)registerComponentViewClass:(Class<RCTComponentViewProtocol>)componentViewClass
|
||||
andWarnIfNeeded:(BOOL)isRegisteredInInteropLayer
|
||||
{
|
||||
[self registerComponentViewClass:componentViewClass];
|
||||
if (isRegisteredInInteropLayer) {
|
||||
RCTLogWarn(
|
||||
@"Component with class %@ has been registered in both the New Architecture Renderer and in the Interop Layer.\nPlease remove it from the Interop Layer",
|
||||
componentViewClass);
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -285,6 +285,10 @@ static BackgroundExecutor RCTGetBackgroundExecutor()
|
||||
CoreFeatures::cacheNSTextStorage = true;
|
||||
}
|
||||
|
||||
if (reactNativeConfig && reactNativeConfig->getBool("react_fabric:cancel_image_downloads_on_recycle")) {
|
||||
CoreFeatures::cancelImageDownloadsOnRecycle = true;
|
||||
}
|
||||
|
||||
auto componentRegistryFactory =
|
||||
[factory = wrapManagedObject(_mountingManager.componentViewRegistry.componentViewFactory)](
|
||||
EventDispatcher::Weak const &eventDispatcher, ContextContainer::Shared const &contextContainer) {
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <ReactCommon/RuntimeExecutor.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <react/utils/ContextContainer.h>
|
||||
|
||||
@@ -15,8 +14,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@class RCTSurfacePresenter;
|
||||
@class RCTBridge;
|
||||
|
||||
facebook::react::RuntimeExecutor RCTRuntimeExecutorFromBridge(RCTBridge *bridge);
|
||||
|
||||
/*
|
||||
* Controls a life-cycle of a Surface Presenter based on Bridge's life-cycle.
|
||||
* We are moving away from using Bridge.
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#import <React/RCTConstants.h>
|
||||
#import <React/RCTImageLoader.h>
|
||||
#import <React/RCTImageLoaderWithAttributionProtocol.h>
|
||||
#import <React/RCTRuntimeExecutorFromBridge.h>
|
||||
#import <React/RCTSurfacePresenter.h>
|
||||
#import <React/RCTSurfacePresenterStub.h>
|
||||
|
||||
@@ -42,43 +43,6 @@ static ContextContainer::Shared RCTContextContainerFromBridge(RCTBridge *bridge)
|
||||
return contextContainer;
|
||||
}
|
||||
|
||||
RuntimeExecutor RCTRuntimeExecutorFromBridge(RCTBridge *bridge)
|
||||
{
|
||||
RCTAssert(bridge, @"RCTRuntimeExecutorFromBridge: Bridge must not be nil.");
|
||||
|
||||
auto bridgeWeakWrapper = wrapManagedObjectWeakly([bridge batchedBridge] ?: bridge);
|
||||
|
||||
RuntimeExecutor runtimeExecutor = [bridgeWeakWrapper](
|
||||
std::function<void(facebook::jsi::Runtime & runtime)> &&callback) {
|
||||
RCTBridge *bridge = unwrapManagedObjectWeakly(bridgeWeakWrapper);
|
||||
|
||||
RCTAssert(bridge, @"RCTRuntimeExecutorFromBridge: Bridge must not be nil at the moment of scheduling a call.");
|
||||
|
||||
[bridge invokeAsync:[bridgeWeakWrapper, callback = std::move(callback)]() {
|
||||
RCTCxxBridge *batchedBridge = (RCTCxxBridge *)unwrapManagedObjectWeakly(bridgeWeakWrapper);
|
||||
|
||||
RCTAssert(batchedBridge, @"RCTRuntimeExecutorFromBridge: Bridge must not be nil at the moment of invocation.");
|
||||
|
||||
if (!batchedBridge) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto runtime = (facebook::jsi::Runtime *)(batchedBridge.runtime);
|
||||
|
||||
RCTAssert(
|
||||
runtime, @"RCTRuntimeExecutorFromBridge: Bridge must have a valid jsi::Runtime at the moment of invocation.");
|
||||
|
||||
if (!runtime) {
|
||||
return;
|
||||
}
|
||||
|
||||
callback(*runtime);
|
||||
}];
|
||||
};
|
||||
|
||||
return runtimeExecutor;
|
||||
}
|
||||
|
||||
@implementation RCTSurfacePresenterBridgeAdapter {
|
||||
RCTSurfacePresenter *_Nullable _surfacePresenter;
|
||||
__weak RCTBridge *_bridge;
|
||||
|
||||
@@ -29,7 +29,6 @@ header_search_paths = [
|
||||
"\"$(PODS_ROOT)/Headers/Private/React-Core\"",
|
||||
"\"$(PODS_ROOT)/Headers/Public/React-Codegen\"",
|
||||
"\"${PODS_CONFIGURATION_BUILD_DIR}/React-Codegen/React_Codegen.framework/Headers\"",
|
||||
|
||||
]
|
||||
|
||||
if ENV['USE_FRAMEWORKS']
|
||||
@@ -41,6 +40,9 @@ if ENV['USE_FRAMEWORKS']
|
||||
header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios\""
|
||||
header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-ImageManager/React_ImageManager.framework/Headers\""
|
||||
header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTFabric/RCTFabric.framework/Headers\""
|
||||
header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-debug/React_debug.framework/Headers\""
|
||||
header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-utils/React_utils.framework/Headers\""
|
||||
header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-runtimescheduler/React_runtimescheduler.framework/Headers\""
|
||||
end
|
||||
|
||||
Pod::Spec.new do |s|
|
||||
@@ -72,6 +74,17 @@ Pod::Spec.new do |s|
|
||||
s.dependency "React-RCTImage", version
|
||||
s.dependency "React-ImageManager"
|
||||
s.dependency "RCT-Folly/Fabric", folly_version
|
||||
s.dependency "glog"
|
||||
s.dependency "Yoga"
|
||||
s.dependency "React-RCTText"
|
||||
s.dependency "React-utils"
|
||||
s.dependency "React-runtimescheduler"
|
||||
|
||||
if ENV["USE_HERMES"] == nil || ENV["USE_HERMES"] == "1"
|
||||
s.dependency "hermes-engine"
|
||||
else
|
||||
s.dependency "React-jsi"
|
||||
end
|
||||
|
||||
s.test_spec 'Tests' do |test_spec|
|
||||
test_spec.source_files = "Tests/**/*.{mm}"
|
||||
|
||||
@@ -469,7 +469,10 @@ android {
|
||||
"-DREACT_BUILD_DIR=$buildDir",
|
||||
"-DANDROID_STL=c++_shared",
|
||||
"-DANDROID_TOOLCHAIN=clang",
|
||||
"-DANDROID_PLATFORM=android-21"
|
||||
"-DANDROID_PLATFORM=android-21",
|
||||
// Due to https://github.com/android/ndk/issues/1693 we're losing Android
|
||||
// specific compilation flags. This can be removed once we moved to NDK 25/26
|
||||
"-DANDROID_USE_LEGACY_TOOLCHAIN_FILE=ON"
|
||||
|
||||
targets "jsijniprofiler",
|
||||
"reactnativeblob",
|
||||
|
||||
@@ -46,7 +46,20 @@ target_include_directories(${CMAKE_PROJECT_NAME}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${PROJECT_BUILD_DIR}/generated/rncli/src/main/jni)
|
||||
|
||||
target_compile_options(${CMAKE_PROJECT_NAME} PRIVATE -Wall -Werror -fexceptions -frtti -std=c++17 -DWITH_INSPECTOR=1 -DLOG_TAG=\"ReactNative\")
|
||||
target_compile_options(${CMAKE_PROJECT_NAME}
|
||||
PRIVATE
|
||||
-Wall
|
||||
-Werror
|
||||
# We suppress cpp #error and #warning to don't fail the build
|
||||
# due to use migrating away from
|
||||
# #include <react/renderer/graphics/conversions.h>
|
||||
# This can be removed for React Native 0.73
|
||||
-Wno-error=cpp
|
||||
-fexceptions
|
||||
-frtti
|
||||
-std=c++17
|
||||
-DWITH_INSPECTOR=1
|
||||
-DLOG_TAG=\"ReactNative\")
|
||||
|
||||
# Prefab packages from React Native
|
||||
find_package(ReactAndroid REQUIRED CONFIG)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
VERSION_NAME=1000.0.0
|
||||
VERSION_NAME=0.72.2
|
||||
GROUP=com.facebook.react
|
||||
|
||||
# JVM Versions
|
||||
|
||||
@@ -154,6 +154,9 @@ android {
|
||||
// We intentionally build Hermes with Intl support only. This is to simplify
|
||||
// the build setup and to avoid overcomplicating the build-type matrix.
|
||||
arguments "-DHERMES_ENABLE_INTL=True"
|
||||
// Due to https://github.com/android/ndk/issues/1693 we're losing Android
|
||||
// specific compilation flags. This can be removed once we moved to NDK 25/26
|
||||
arguments "-DANDROID_USE_LEGACY_TOOLCHAIN_FILE=ON"
|
||||
targets "libhermes"
|
||||
}
|
||||
}
|
||||
@@ -178,6 +181,8 @@ android {
|
||||
// This has the (unlucky) side effect of letting AGP call the build
|
||||
// tasks `configureCMakeRelease` while is actually building the debug flavor.
|
||||
arguments "-DCMAKE_BUILD_TYPE=Release"
|
||||
// Adding -O3 to patch the issue here: https://github.com/android/ndk/issues/1740#issuecomment-1198438260
|
||||
cppFlags "-O3"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -185,6 +190,8 @@ android {
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
arguments "-DCMAKE_BUILD_TYPE=MinSizeRel"
|
||||
// For release builds, we don't want to enable the Hermes Debugger.
|
||||
arguments "-DHERMES_ENABLE_DEBUGGER=False"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+40
-1
@@ -11,6 +11,7 @@ import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.KeyEvent;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.facebook.infer.annotation.Assertions;
|
||||
import com.facebook.react.devsupport.DoubleTapReloadRecognizer;
|
||||
@@ -33,6 +34,8 @@ public class ReactDelegate {
|
||||
|
||||
private ReactNativeHost mReactNativeHost;
|
||||
|
||||
private boolean mFabricEnabled = false;
|
||||
|
||||
public ReactDelegate(
|
||||
Activity activity,
|
||||
ReactNativeHost reactNativeHost,
|
||||
@@ -45,6 +48,20 @@ public class ReactDelegate {
|
||||
mReactNativeHost = reactNativeHost;
|
||||
}
|
||||
|
||||
public ReactDelegate(
|
||||
Activity activity,
|
||||
ReactNativeHost reactNativeHost,
|
||||
@Nullable String appKey,
|
||||
@Nullable Bundle launchOptions,
|
||||
boolean fabricEnabled) {
|
||||
mActivity = activity;
|
||||
mMainComponentName = appKey;
|
||||
mLaunchOptions = composeLaunchOptions(launchOptions);
|
||||
mDoubleTapReloadRecognizer = new DoubleTapReloadRecognizer();
|
||||
mReactNativeHost = reactNativeHost;
|
||||
mFabricEnabled = fabricEnabled;
|
||||
}
|
||||
|
||||
public void onHostResume() {
|
||||
if (getReactNativeHost().hasInstance()) {
|
||||
if (mActivity instanceof DefaultHardwareBackBtnHandler) {
|
||||
@@ -109,7 +126,9 @@ public class ReactDelegate {
|
||||
}
|
||||
|
||||
protected ReactRootView createRootView() {
|
||||
return new ReactRootView(mActivity);
|
||||
ReactRootView reactRootView = new ReactRootView(mActivity);
|
||||
reactRootView.setIsFabric(isFabricEnabled());
|
||||
return reactRootView;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -144,4 +163,24 @@ public class ReactDelegate {
|
||||
public ReactInstanceManager getReactInstanceManager() {
|
||||
return getReactNativeHost().getReactInstanceManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this method if you wish to selectively toggle Fabric for a specific surface. This will
|
||||
* also control if Concurrent Root (React 18) should be enabled or not.
|
||||
*
|
||||
* @return true if Fabric is enabled for this Activity, false otherwise.
|
||||
*/
|
||||
protected boolean isFabricEnabled() {
|
||||
return mFabricEnabled;
|
||||
}
|
||||
|
||||
private @NonNull Bundle composeLaunchOptions(Bundle composedLaunchOptions) {
|
||||
if (isFabricEnabled()) {
|
||||
if (composedLaunchOptions == null) {
|
||||
composedLaunchOptions = new Bundle();
|
||||
}
|
||||
composedLaunchOptions.putBoolean("concurrentRoot", true);
|
||||
}
|
||||
return composedLaunchOptions;
|
||||
}
|
||||
}
|
||||
|
||||
+22
-7
@@ -16,6 +16,7 @@ import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import com.facebook.react.modules.core.PermissionAwareActivity;
|
||||
@@ -29,6 +30,7 @@ public class ReactFragment extends Fragment implements PermissionAwareActivity {
|
||||
|
||||
protected static final String ARG_COMPONENT_NAME = "arg_component_name";
|
||||
protected static final String ARG_LAUNCH_OPTIONS = "arg_launch_options";
|
||||
protected static final String ARG_FABRIC_ENABLED = "arg_fabric_enabled";
|
||||
|
||||
private ReactDelegate mReactDelegate;
|
||||
|
||||
@@ -40,13 +42,16 @@ public class ReactFragment extends Fragment implements PermissionAwareActivity {
|
||||
|
||||
/**
|
||||
* @param componentName The name of the react native component
|
||||
* @param fabricEnabled Flag to enable Fabric for ReactFragment
|
||||
* @return A new instance of fragment ReactFragment.
|
||||
*/
|
||||
private static ReactFragment newInstance(String componentName, Bundle launchOptions) {
|
||||
private static ReactFragment newInstance(
|
||||
String componentName, Bundle launchOptions, Boolean fabricEnabled) {
|
||||
ReactFragment fragment = new ReactFragment();
|
||||
Bundle args = new Bundle();
|
||||
args.putString(ARG_COMPONENT_NAME, componentName);
|
||||
args.putBundle(ARG_LAUNCH_OPTIONS, launchOptions);
|
||||
args.putBoolean(ARG_FABRIC_ENABLED, fabricEnabled);
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
@@ -57,15 +62,18 @@ public class ReactFragment extends Fragment implements PermissionAwareActivity {
|
||||
super.onCreate(savedInstanceState);
|
||||
String mainComponentName = null;
|
||||
Bundle launchOptions = null;
|
||||
Boolean fabricEnabled = null;
|
||||
if (getArguments() != null) {
|
||||
mainComponentName = getArguments().getString(ARG_COMPONENT_NAME);
|
||||
launchOptions = getArguments().getBundle(ARG_LAUNCH_OPTIONS);
|
||||
fabricEnabled = getArguments().getBoolean(ARG_FABRIC_ENABLED);
|
||||
}
|
||||
if (mainComponentName == null) {
|
||||
throw new IllegalStateException("Cannot loadApp if component name is null");
|
||||
}
|
||||
mReactDelegate =
|
||||
new ReactDelegate(getActivity(), getReactNativeHost(), mainComponentName, launchOptions);
|
||||
new ReactDelegate(
|
||||
getActivity(), getReactNativeHost(), mainComponentName, launchOptions, fabricEnabled);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -85,7 +93,7 @@ public class ReactFragment extends Fragment implements PermissionAwareActivity {
|
||||
|
||||
@Override
|
||||
public View onCreateView(
|
||||
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
mReactDelegate.loadApp();
|
||||
return mReactDelegate.getReactRootView();
|
||||
}
|
||||
@@ -140,7 +148,7 @@ public class ReactFragment extends Fragment implements PermissionAwareActivity {
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(
|
||||
int requestCode, String[] permissions, int[] grantResults) {
|
||||
int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
if (mPermissionListener != null
|
||||
&& mPermissionListener.onRequestPermissionsResult(requestCode, permissions, grantResults)) {
|
||||
@@ -170,12 +178,14 @@ public class ReactFragment extends Fragment implements PermissionAwareActivity {
|
||||
/** Builder class to help instantiate a ReactFragment */
|
||||
public static class Builder {
|
||||
|
||||
String mComponentName;
|
||||
Bundle mLaunchOptions;
|
||||
@Nullable String mComponentName;
|
||||
@Nullable Bundle mLaunchOptions;
|
||||
@Nullable Boolean mFabricEnabled;
|
||||
|
||||
public Builder() {
|
||||
mComponentName = null;
|
||||
mLaunchOptions = null;
|
||||
mFabricEnabled = null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -201,7 +211,12 @@ public class ReactFragment extends Fragment implements PermissionAwareActivity {
|
||||
}
|
||||
|
||||
public ReactFragment build() {
|
||||
return ReactFragment.newInstance(mComponentName, mLaunchOptions);
|
||||
return ReactFragment.newInstance(mComponentName, mLaunchOptions, mFabricEnabled);
|
||||
}
|
||||
|
||||
public Builder setFabricEnabled(boolean fabricEnabled) {
|
||||
mFabricEnabled = fabricEnabled;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+9
@@ -1360,6 +1360,15 @@ public class ReactInstanceManager {
|
||||
|
||||
reactContext.initializeWithInstance(catalystInstance);
|
||||
|
||||
if (ReactFeatureFlags.unstable_useRuntimeSchedulerAlways) {
|
||||
// On Old Architecture, we need to initialize the Native Runtime Scheduler so that
|
||||
// the `nativeRuntimeScheduler` object is registered on JS.
|
||||
// On New Architecture, this is normally triggered by instantiate a TurboModuleManager.
|
||||
// Here we invoke getRuntimeScheduler() to trigger the creation of it regardless of the
|
||||
// architecture so it will always be there.
|
||||
catalystInstance.getRuntimeScheduler();
|
||||
}
|
||||
|
||||
if (ReactFeatureFlags.useTurboModules && mTMMDelegateBuilder != null) {
|
||||
TurboModuleManagerDelegate tmmDelegate =
|
||||
mTMMDelegateBuilder
|
||||
|
||||
+14
-1
@@ -7,9 +7,12 @@
|
||||
|
||||
package com.facebook.react.animated;
|
||||
|
||||
import com.facebook.common.logging.FLog;
|
||||
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.common.build.ReactBuildConfig;
|
||||
|
||||
/**
|
||||
* Implementation of {@link AnimationDriver} which provides a support for simple time-based
|
||||
@@ -70,7 +73,17 @@ class FrameBasedAnimationDriver extends AnimationDriver {
|
||||
long timeFromStartMillis = (frameTimeNanos - mStartFrameTimeNanos) / 1000000;
|
||||
int frameIndex = (int) Math.round(timeFromStartMillis / FRAME_TIME_MILLIS);
|
||||
if (frameIndex < 0) {
|
||||
throw new IllegalStateException("Calculated frame index should never be lower than 0");
|
||||
String message =
|
||||
"Calculated frame index should never be lower than 0. Called with frameTimeNanos "
|
||||
+ frameTimeNanos
|
||||
+ " and mStartFrameTimeNanos "
|
||||
+ mStartFrameTimeNanos;
|
||||
if (ReactBuildConfig.DEBUG) {
|
||||
throw new IllegalStateException(message);
|
||||
} else {
|
||||
FLog.w(ReactConstants.TAG, message);
|
||||
return;
|
||||
}
|
||||
} else if (mHasFinished) {
|
||||
// nothing to do here
|
||||
return;
|
||||
|
||||
+10
@@ -295,6 +295,16 @@ public class NativeAnimatedModule extends NativeAnimatedModuleSpec
|
||||
mCurrentFrameNumber++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void willMountItems(UIManager uiManager) {
|
||||
// noop
|
||||
}
|
||||
|
||||
@Override
|
||||
public void didMountItems(UIManager uiManager) {
|
||||
// noop
|
||||
}
|
||||
|
||||
// For FabricUIManager only
|
||||
@Override
|
||||
@UiThread
|
||||
|
||||
+29
@@ -21,6 +21,7 @@ import com.facebook.common.logging.FLog;
|
||||
import com.facebook.infer.annotation.Assertions;
|
||||
import com.facebook.infer.annotation.ThreadConfined;
|
||||
import com.facebook.proguard.annotations.DoNotStrip;
|
||||
import com.facebook.react.bridge.interop.InteropModuleRegistry;
|
||||
import com.facebook.react.bridge.queue.MessageQueueThread;
|
||||
import com.facebook.react.bridge.queue.ReactQueueConfiguration;
|
||||
import com.facebook.react.common.LifecycleState;
|
||||
@@ -69,6 +70,8 @@ public class ReactContext extends ContextWrapper {
|
||||
private @Nullable JSExceptionHandler mJSExceptionHandler;
|
||||
private @Nullable JSExceptionHandler mExceptionHandlerWrapper;
|
||||
private @Nullable WeakReference<Activity> mCurrentActivity;
|
||||
|
||||
private @Nullable InteropModuleRegistry mInteropModuleRegistry;
|
||||
private boolean mIsInitialized = false;
|
||||
|
||||
public ReactContext(Context base) {
|
||||
@@ -93,6 +96,7 @@ public class ReactContext extends ContextWrapper {
|
||||
|
||||
ReactQueueConfiguration queueConfig = catalystInstance.getReactQueueConfiguration();
|
||||
initializeMessageQueueThreads(queueConfig);
|
||||
initializeInteropModules();
|
||||
}
|
||||
|
||||
/** Initialize message queue threads using a ReactQueueConfiguration. */
|
||||
@@ -120,6 +124,14 @@ public class ReactContext extends ContextWrapper {
|
||||
mIsInitialized = true;
|
||||
}
|
||||
|
||||
protected void initializeInteropModules() {
|
||||
mInteropModuleRegistry = new InteropModuleRegistry();
|
||||
}
|
||||
|
||||
protected void initializeInteropModules(ReactContext reactContext) {
|
||||
mInteropModuleRegistry = reactContext.mInteropModuleRegistry;
|
||||
}
|
||||
|
||||
public void resetPerfStats() {
|
||||
if (mNativeModulesMessageQueueThread != null) {
|
||||
mNativeModulesMessageQueueThread.resetPerfStats();
|
||||
@@ -163,6 +175,10 @@ public class ReactContext extends ContextWrapper {
|
||||
}
|
||||
throw new IllegalStateException(EARLY_JS_ACCESS_EXCEPTION_MESSAGE);
|
||||
}
|
||||
if (mInteropModuleRegistry != null
|
||||
&& mInteropModuleRegistry.shouldReturnInteropModule(jsInterface)) {
|
||||
return mInteropModuleRegistry.getInteropModule(jsInterface);
|
||||
}
|
||||
return mCatalystInstance.getJSModule(jsInterface);
|
||||
}
|
||||
|
||||
@@ -546,4 +562,17 @@ public class ReactContext extends ContextWrapper {
|
||||
Assertions.assertNotNull(mCatalystInstance).registerSegment(segmentId, path);
|
||||
Assertions.assertNotNull(callback).invoke();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a {@link JavaScriptModule} within the Interop Layer so that can be consumed whenever
|
||||
* getJSModule is invoked.
|
||||
*
|
||||
* <p>This method is internal to React Native and should not be used externally.
|
||||
*/
|
||||
public <T extends JavaScriptModule> void internal_registerInteropModule(
|
||||
Class<T> interopModuleInterface, Object interopModule) {
|
||||
if (mInteropModuleRegistry != null) {
|
||||
mInteropModuleRegistry.registerInteropModule(interopModuleInterface, interopModule);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+25
-2
@@ -12,10 +12,33 @@ public interface UIManagerListener {
|
||||
/**
|
||||
* Called right before view updates are dispatched at the end of a batch. This is useful if a
|
||||
* module needs to add UIBlocks to the queue before it is flushed.
|
||||
*
|
||||
* <p>This is called by Paper only.
|
||||
*/
|
||||
void willDispatchViewUpdates(UIManager uiManager);
|
||||
/* Called right after view updates are dispatched for a frame. */
|
||||
/**
|
||||
* Called on UIThread right before view updates are executed.
|
||||
*
|
||||
* <p>This is called by Fabric only.
|
||||
*/
|
||||
void willMountItems(UIManager uiManager);
|
||||
/**
|
||||
* Called on UIThread right after view updates are executed.
|
||||
*
|
||||
* <p>This is called by Fabric only.
|
||||
*/
|
||||
void didMountItems(UIManager uiManager);
|
||||
/**
|
||||
* Called on UIThread right after view updates are dispatched for a frame. Note that this will be
|
||||
* called for every frame even if there are no updates.
|
||||
*
|
||||
* <p>This is called by Fabric only.
|
||||
*/
|
||||
void didDispatchMountItems(UIManager uiManager);
|
||||
/* Called right after scheduleMountItems is called in Fabric, after a new tree is committed. */
|
||||
/**
|
||||
* Called right after scheduleMountItems is called in Fabric, after a new tree is committed.
|
||||
*
|
||||
* <p>This is called by Fabric only.
|
||||
*/
|
||||
void didScheduleMountItems(UIManager uiManager);
|
||||
}
|
||||
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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.bridge.interop;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import com.facebook.react.bridge.JavaScriptModule;
|
||||
import com.facebook.react.config.ReactFeatureFlags;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* A utility class that takes care of returning {@link JavaScriptModule} which are used for the
|
||||
* Fabric Interop Layer. This allows us to override the returned classes once the user is invoking
|
||||
* `ReactContext.getJsModule()`.
|
||||
*
|
||||
* <p>Currently we only support a `RCTEventEmitter` re-implementation, being `InteropEventEmitter`
|
||||
* but this class can support other re-implementation in the future.
|
||||
*/
|
||||
public class InteropModuleRegistry {
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private final HashMap<Class, Object> supportedModules;
|
||||
|
||||
public InteropModuleRegistry() {
|
||||
this.supportedModules = new HashMap<>();
|
||||
}
|
||||
|
||||
public <T extends JavaScriptModule> boolean shouldReturnInteropModule(Class<T> requestedModule) {
|
||||
return checkReactFeatureFlagsConditions() && supportedModules.containsKey(requestedModule);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public <T extends JavaScriptModule> T getInteropModule(Class<T> requestedModule) {
|
||||
if (checkReactFeatureFlagsConditions()) {
|
||||
//noinspection unchecked
|
||||
return (T) supportedModules.get(requestedModule);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public <T extends JavaScriptModule> void registerInteropModule(
|
||||
Class<T> interopModuleInterface, Object interopModule) {
|
||||
if (checkReactFeatureFlagsConditions()) {
|
||||
supportedModules.put(interopModuleInterface, interopModule);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkReactFeatureFlagsConditions() {
|
||||
return ReactFeatureFlags.enableFabricRenderer && ReactFeatureFlags.unstable_useFabricInterop;
|
||||
}
|
||||
}
|
||||
+18
@@ -34,6 +34,21 @@ public class ReactFeatureFlags {
|
||||
*/
|
||||
public static volatile boolean enableFabricRenderer = false;
|
||||
|
||||
/**
|
||||
* Should this application enable the Fabric Interop Layer for Android? If yes, the application
|
||||
* will behave so that it can accept non-Fabric components and render them on Fabric. This toggle
|
||||
* is controlling extra logic such as custom event dispatching that are needed for the Fabric
|
||||
* Interop Layer to work correctly.
|
||||
*/
|
||||
public static volatile boolean unstable_useFabricInterop = false;
|
||||
|
||||
/**
|
||||
* Should this application always use the Native RuntimeScheduler? If yes, we'll be instantiating
|
||||
* it over all the architectures (both Old and New). This is intentionally set to true as we want
|
||||
* to use it more as a kill-switch to turn off this feature to potentially debug issues.
|
||||
*/
|
||||
public static volatile boolean unstable_useRuntimeSchedulerAlways = true;
|
||||
|
||||
/**
|
||||
* Feature flag to enable the new bridgeless architecture. Note: Enabling this will force enable
|
||||
* the following flags: `useTurboModules` & `enableFabricRenderer`.
|
||||
@@ -75,6 +90,9 @@ public class ReactFeatureFlags {
|
||||
/** Feature Flag to enable the pending event queue in fabric before mounting views */
|
||||
public static boolean enableFabricPendingEventQueue = false;
|
||||
|
||||
/** Feature Flag to enable caching mechanism of text measurement at shadow node level */
|
||||
public static boolean enableTextMeasureCachePerShadowNode = false;
|
||||
|
||||
/**
|
||||
* Feature flag that controls how turbo modules are exposed to JS
|
||||
*
|
||||
|
||||
+1
@@ -31,6 +31,7 @@ object DefaultNewArchitectureEntryPoint {
|
||||
) {
|
||||
ReactFeatureFlags.useTurboModules = turboModulesEnabled
|
||||
ReactFeatureFlags.enableFabricRenderer = fabricEnabled
|
||||
ReactFeatureFlags.unstable_useFabricInterop = fabricEnabled
|
||||
|
||||
this.privateFabricEnabled = fabricEnabled
|
||||
this.privateTurboModulesEnabled = turboModulesEnabled
|
||||
|
||||
+4
@@ -7,6 +7,7 @@
|
||||
|
||||
package com.facebook.react.defaults
|
||||
|
||||
import android.os.Bundle
|
||||
import com.facebook.react.ReactActivity
|
||||
import com.facebook.react.ReactActivityDelegate
|
||||
import com.facebook.react.ReactRootView
|
||||
@@ -43,4 +44,7 @@ open class DefaultReactActivityDelegate(
|
||||
|
||||
override fun createRootView(): ReactRootView =
|
||||
ReactRootView(context).apply { setIsFabric(fabricEnabled) }
|
||||
|
||||
override fun createRootView(bundle: Bundle?): ReactRootView =
|
||||
ReactRootView(context).apply { setIsFabric(fabricEnabled) }
|
||||
}
|
||||
|
||||
+26
-8
@@ -24,6 +24,7 @@ import android.util.Pair;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import androidx.annotation.Nullable;
|
||||
@@ -553,17 +554,30 @@ public abstract class DevSupportManagerBase implements DevSupportManager {
|
||||
return;
|
||||
}
|
||||
|
||||
final TextView textView = new TextView(getApplicationContext());
|
||||
textView.setText("React Native DevMenu (" + getUniqueTag() + ")");
|
||||
textView.setPadding(0, 50, 0, 0);
|
||||
textView.setGravity(Gravity.CENTER);
|
||||
textView.setTextColor(Color.BLACK);
|
||||
textView.setTextSize(17);
|
||||
textView.setTypeface(textView.getTypeface(), Typeface.BOLD);
|
||||
final LinearLayout header = new LinearLayout(getApplicationContext());
|
||||
header.setOrientation(LinearLayout.VERTICAL);
|
||||
|
||||
final TextView title = new TextView(getApplicationContext());
|
||||
title.setText("React Native Dev Menu (" + getUniqueTag() + ")");
|
||||
title.setPadding(0, 50, 0, 0);
|
||||
title.setGravity(Gravity.CENTER);
|
||||
title.setTextColor(Color.DKGRAY);
|
||||
title.setTextSize(16);
|
||||
title.setTypeface(title.getTypeface(), Typeface.BOLD);
|
||||
|
||||
final TextView jsExecutorLabel = new TextView(getApplicationContext());
|
||||
jsExecutorLabel.setText(getJSExecutorDescription());
|
||||
jsExecutorLabel.setPadding(0, 20, 0, 0);
|
||||
jsExecutorLabel.setGravity(Gravity.CENTER);
|
||||
jsExecutorLabel.setTextColor(Color.GRAY);
|
||||
jsExecutorLabel.setTextSize(14);
|
||||
|
||||
header.addView(title);
|
||||
header.addView(jsExecutorLabel);
|
||||
|
||||
mDevOptionsDialog =
|
||||
new AlertDialog.Builder(context)
|
||||
.setCustomTitle(textView)
|
||||
.setCustomTitle(header)
|
||||
.setItems(
|
||||
options.keySet().toArray(new String[0]),
|
||||
new DialogInterface.OnClickListener() {
|
||||
@@ -587,6 +601,10 @@ public abstract class DevSupportManagerBase implements DevSupportManager {
|
||||
}
|
||||
}
|
||||
|
||||
private String getJSExecutorDescription() {
|
||||
return "Running " + getReactInstanceDevHelper().getJavaScriptExecutorFactory().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link ReactInstanceDevCommandsHandler} is responsible for enabling/disabling dev support when
|
||||
* a React view is attached/detached or when application state changes (e.g. the application is
|
||||
|
||||
+21
@@ -56,6 +56,7 @@ import com.facebook.react.config.ReactFeatureFlags;
|
||||
import com.facebook.react.fabric.events.EventBeatManager;
|
||||
import com.facebook.react.fabric.events.EventEmitterWrapper;
|
||||
import com.facebook.react.fabric.events.FabricEventEmitter;
|
||||
import com.facebook.react.fabric.interop.InteropEventEmitter;
|
||||
import com.facebook.react.fabric.mounting.MountItemDispatcher;
|
||||
import com.facebook.react.fabric.mounting.MountingManager;
|
||||
import com.facebook.react.fabric.mounting.SurfaceMountingManager;
|
||||
@@ -81,6 +82,7 @@ import com.facebook.react.uimanager.ViewManagerRegistry;
|
||||
import com.facebook.react.uimanager.events.EventCategoryDef;
|
||||
import com.facebook.react.uimanager.events.EventDispatcher;
|
||||
import com.facebook.react.uimanager.events.EventDispatcherImpl;
|
||||
import com.facebook.react.uimanager.events.RCTEventEmitter;
|
||||
import com.facebook.react.views.text.TextLayoutManager;
|
||||
import com.facebook.react.views.text.TextLayoutManagerMapBuffer;
|
||||
import java.util.HashMap;
|
||||
@@ -390,6 +392,11 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
|
||||
|
||||
ReactMarker.addFabricListener(mDevToolsReactPerfLogger);
|
||||
}
|
||||
if (ReactFeatureFlags.unstable_useFabricInterop) {
|
||||
InteropEventEmitter interopEventEmitter = new InteropEventEmitter(mReactApplicationContext);
|
||||
mReactApplicationContext.internal_registerInteropModule(
|
||||
RCTEventEmitter.class, interopEventEmitter);
|
||||
}
|
||||
}
|
||||
|
||||
// This is called on the JS thread (see CatalystInstanceImpl).
|
||||
@@ -1171,6 +1178,20 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
|
||||
}
|
||||
|
||||
private class MountItemDispatchListener implements MountItemDispatcher.ItemDispatchListener {
|
||||
@Override
|
||||
public void willMountItems() {
|
||||
for (UIManagerListener listener : mListeners) {
|
||||
listener.willMountItems(FabricUIManager.this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void didMountItems() {
|
||||
for (UIManagerListener listener : mListeners) {
|
||||
listener.didMountItems(FabricUIManager.this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void didDispatchMountItems() {
|
||||
for (UIManagerListener listener : mListeners) {
|
||||
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react.fabric.interop;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.facebook.react.common.annotations.VisibleForTesting;
|
||||
import com.facebook.react.uimanager.events.Event;
|
||||
|
||||
/**
|
||||
* An {@link Event} class used by the {@link InteropEventEmitter}. This class is just holding the
|
||||
* event name and the data which is received by the `receiveEvent` method and will be passed over
|
||||
* the the {@link com.facebook.react.uimanager.events.EventDispatcher}
|
||||
*/
|
||||
class InteropEvent extends Event<InteropEvent> {
|
||||
|
||||
private final String mName;
|
||||
private final WritableMap mEventData;
|
||||
|
||||
InteropEvent(String name, @Nullable WritableMap eventData, int surfaceId, int viewTag) {
|
||||
super(surfaceId, viewTag);
|
||||
mName = name;
|
||||
mEventData = eventData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventName() {
|
||||
return mName;
|
||||
}
|
||||
|
||||
@Override
|
||||
@VisibleForTesting
|
||||
public WritableMap getEventData() {
|
||||
return mEventData;
|
||||
}
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react.fabric.interop;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
import com.facebook.react.bridge.WritableArray;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.facebook.react.common.annotations.VisibleForTesting;
|
||||
import com.facebook.react.uimanager.UIManagerHelper;
|
||||
import com.facebook.react.uimanager.events.EventDispatcher;
|
||||
import com.facebook.react.uimanager.events.RCTEventEmitter;
|
||||
|
||||
/**
|
||||
* A reimplementation of {@link RCTEventEmitter} which is using a {@link EventDispatcher} under the
|
||||
* hood.
|
||||
*
|
||||
* <p>On Fabric, you're supposed to use {@link EventDispatcher} to dispatch events. However, we
|
||||
* provide an interop layer for non-Fabric migrated components.
|
||||
*
|
||||
* <p>This instance will be returned if the user is invoking `context.getJsModule(RCTEventEmitter)
|
||||
* and is providing support for the `receiveEvent` method, so that non-Fabric ViewManagers can
|
||||
* continue to deliver events also when Fabric is turned on.
|
||||
*/
|
||||
public class InteropEventEmitter implements RCTEventEmitter {
|
||||
|
||||
private final ReactContext mReactContext;
|
||||
|
||||
private @Nullable EventDispatcher mEventDispatcherOverride;
|
||||
|
||||
public InteropEventEmitter(ReactContext reactContext) {
|
||||
mReactContext = reactContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receiveEvent(int targetReactTag, String eventName, @Nullable WritableMap eventData) {
|
||||
EventDispatcher dispatcher;
|
||||
if (mEventDispatcherOverride != null) {
|
||||
dispatcher = mEventDispatcherOverride;
|
||||
} else {
|
||||
dispatcher = UIManagerHelper.getEventDispatcherForReactTag(mReactContext, targetReactTag);
|
||||
}
|
||||
int surfaceId = UIManagerHelper.getSurfaceId(mReactContext);
|
||||
if (dispatcher != null) {
|
||||
dispatcher.dispatchEvent(new InteropEvent(eventName, eventData, surfaceId, targetReactTag));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receiveTouches(
|
||||
String eventName, WritableArray touches, WritableArray changedIndices) {
|
||||
throw new UnsupportedOperationException(
|
||||
"EventEmitter#receiveTouches is not supported by the Fabric Interop Layer");
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void overrideEventDispatcher(EventDispatcher eventDispatcherOverride) {
|
||||
mEventDispatcherOverride = eventDispatcherOverride;
|
||||
}
|
||||
}
|
||||
+9
@@ -193,6 +193,8 @@ public class MountItemDispatcher {
|
||||
return false;
|
||||
}
|
||||
|
||||
mItemDispatchListener.willMountItems();
|
||||
|
||||
// As an optimization, execute all ViewCommands first
|
||||
// This should be:
|
||||
// 1) Performant: ViewCommands are often a replacement for SetNativeProps, which we've always
|
||||
@@ -299,6 +301,9 @@ public class MountItemDispatcher {
|
||||
}
|
||||
mBatchedExecutionTime += SystemClock.uptimeMillis() - batchedExecutionStartTime;
|
||||
}
|
||||
|
||||
mItemDispatchListener.didMountItems();
|
||||
|
||||
Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
|
||||
|
||||
return true;
|
||||
@@ -415,6 +420,10 @@ public class MountItemDispatcher {
|
||||
}
|
||||
|
||||
public interface ItemDispatchListener {
|
||||
void willMountItems();
|
||||
|
||||
void didMountItems();
|
||||
|
||||
void didDispatchMountItems();
|
||||
}
|
||||
}
|
||||
|
||||
+16
-2
@@ -29,7 +29,6 @@ import java.nio.channels.ReadableByteChannel;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.internal.Util;
|
||||
import okio.BufferedSink;
|
||||
import okio.ByteString;
|
||||
import okio.Okio;
|
||||
@@ -122,6 +121,21 @@ import okio.Source;
|
||||
return RequestBody.create(mediaType, gzipByteArrayOutputStream.toByteArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* Reference:
|
||||
* https://github.com/square/okhttp/blob/8c8c3dbcfa91e28de2e13975ec414e07f153fde4/okhttp/src/commonMain/kotlin/okhttp3/internal/-UtilCommon.kt#L281-L288
|
||||
* Checked exceptions will be ignored
|
||||
*/
|
||||
private static void closeQuietly(Source source) {
|
||||
try {
|
||||
source.close();
|
||||
} catch (RuntimeException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
// noop.
|
||||
}
|
||||
}
|
||||
|
||||
/** Creates a RequestBody from a mediaType and inputStream given. */
|
||||
public static RequestBody create(final MediaType mediaType, final InputStream inputStream) {
|
||||
return new RequestBody() {
|
||||
@@ -146,7 +160,7 @@ import okio.Source;
|
||||
source = Okio.source(inputStream);
|
||||
sink.writeAll(source);
|
||||
} finally {
|
||||
Util.closeQuietly(source);
|
||||
closeQuietly(source);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
+3
-3
@@ -15,8 +15,8 @@ import java.util.Map;
|
||||
|
||||
public class ReactNativeVersion {
|
||||
public static final Map<String, Object> VERSION = MapBuilder.<String, Object>of(
|
||||
"major", 1000,
|
||||
"minor", 0,
|
||||
"patch", 0,
|
||||
"major", 0,
|
||||
"minor", 72,
|
||||
"patch", 2,
|
||||
"prerelease", null);
|
||||
}
|
||||
|
||||
+1
@@ -50,6 +50,7 @@ public class ThemedReactContext extends ReactContext {
|
||||
if (reactApplicationContext.hasCatalystInstance()) {
|
||||
initializeWithInstance(reactApplicationContext.getCatalystInstance());
|
||||
}
|
||||
initializeInteropModules(reactApplicationContext);
|
||||
mReactApplicationContext = reactApplicationContext;
|
||||
mModuleName = moduleName;
|
||||
mSurfaceId = surfaceId;
|
||||
|
||||
+32
@@ -10,11 +10,15 @@ package com.facebook.react.uimanager;
|
||||
import static com.facebook.systrace.Systrace.TRACE_TAG_REACT_JAVA_BRIDGE;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import com.facebook.react.common.MapBuilder;
|
||||
import com.facebook.react.config.ReactFeatureFlags;
|
||||
import com.facebook.systrace.SystraceMessage;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Helps generate constants map for {@link UIManagerModule} by collecting and merging constants from
|
||||
@@ -113,6 +117,13 @@ import java.util.Map;
|
||||
|
||||
Map viewManagerBubblingEvents = viewManager.getExportedCustomBubblingEventTypeConstants();
|
||||
if (viewManagerBubblingEvents != null) {
|
||||
|
||||
if (ReactFeatureFlags.enableFabricRenderer && ReactFeatureFlags.unstable_useFabricInterop) {
|
||||
// For Fabric, events needs to be fired with a "top" prefix.
|
||||
// For the sake of Fabric Interop, here we normalize events adding "top" in their
|
||||
// name if the user hasn't provided it.
|
||||
normalizeEventTypes(viewManagerBubblingEvents);
|
||||
}
|
||||
recursiveMerge(cumulativeBubblingEventTypes, viewManagerBubblingEvents);
|
||||
recursiveMerge(viewManagerBubblingEvents, defaultBubblingEvents);
|
||||
viewManagerConstants.put(BUBBLING_EVENTS_KEY, viewManagerBubblingEvents);
|
||||
@@ -145,6 +156,27 @@ import java.util.Map;
|
||||
return viewManagerConstants;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
/* package */ static void normalizeEventTypes(Map events) {
|
||||
if (events == null) {
|
||||
return;
|
||||
}
|
||||
Set<String> keysToNormalize = new HashSet<>();
|
||||
for (Object key : events.keySet()) {
|
||||
if (key instanceof String) {
|
||||
String keyString = (String) key;
|
||||
if (!keyString.startsWith("top")) {
|
||||
keysToNormalize.add(keyString);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (String oldKey : keysToNormalize) {
|
||||
Object value = events.get(oldKey);
|
||||
String newKey = "top" + oldKey.substring(0, 1).toUpperCase() + oldKey.substring(1);
|
||||
events.put(newKey, value);
|
||||
}
|
||||
}
|
||||
|
||||
/** Merges {@param source} map into {@param dest} map recursively */
|
||||
private static void recursiveMerge(@Nullable Map dest, @Nullable Map source) {
|
||||
if (dest == null || source == null || source.isEmpty()) {
|
||||
|
||||
+19
@@ -18,6 +18,7 @@ import com.facebook.react.bridge.UIManager;
|
||||
import com.facebook.react.bridge.UIManagerListener;
|
||||
import com.facebook.react.bridge.UiThreadUtil;
|
||||
import com.facebook.react.uimanager.UIManagerHelper;
|
||||
import com.facebook.react.uimanager.common.UIManagerType;
|
||||
import com.facebook.react.uimanager.common.ViewUtil;
|
||||
import com.facebook.react.views.scroll.ReactScrollViewHelper.HasSmoothScroll;
|
||||
import com.facebook.react.views.view.ReactViewGroup;
|
||||
@@ -89,6 +90,14 @@ public class MaintainVisibleScrollPositionHelper<ScrollViewT extends ViewGroup &
|
||||
* been updated.
|
||||
*/
|
||||
public void updateScrollPosition() {
|
||||
// On Fabric this will be called internally in `didMountItems`.
|
||||
if (ViewUtil.getUIManagerType(mScrollView.getId()) == UIManagerType.FABRIC) {
|
||||
return;
|
||||
}
|
||||
updateScrollPositionInternal();
|
||||
}
|
||||
|
||||
private void updateScrollPositionInternal() {
|
||||
if (mConfig == null || mFirstVisibleView == null || mPrevFirstVisibleFrame == null) {
|
||||
return;
|
||||
}
|
||||
@@ -169,6 +178,16 @@ public class MaintainVisibleScrollPositionHelper<ScrollViewT extends ViewGroup &
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void willMountItems(UIManager uiManager) {
|
||||
computeTargetView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void didMountItems(UIManager uiManager) {
|
||||
updateScrollPositionInternal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void didDispatchMountItems(UIManager uiManager) {
|
||||
// noop
|
||||
|
||||
+4
@@ -37,6 +37,10 @@ public class CustomLetterSpacingSpan extends MetricAffectingSpan implements Reac
|
||||
apply(paint);
|
||||
}
|
||||
|
||||
public float getSpacing() {
|
||||
return mLetterSpacing;
|
||||
}
|
||||
|
||||
private void apply(TextPaint paint) {
|
||||
if (!Float.isNaN(mLetterSpacing)) {
|
||||
paint.setLetterSpacing(mLetterSpacing);
|
||||
|
||||
+4
@@ -71,6 +71,10 @@ public class CustomStyleSpan extends MetricAffectingSpan implements ReactSpan {
|
||||
return mFontFamily;
|
||||
}
|
||||
|
||||
public @Nullable String getFontFeatureSettings() {
|
||||
return mFeatureSettings;
|
||||
}
|
||||
|
||||
private static void apply(
|
||||
Paint paint,
|
||||
int style,
|
||||
|
||||
+3
-1
@@ -42,12 +42,14 @@ public class FontMetricsUtil {
|
||||
X_HEIGHT_MEASUREMENT_TEXT, 0, X_HEIGHT_MEASUREMENT_TEXT.length(), xHeightBounds);
|
||||
double xHeight = xHeightBounds.height() / AMPLIFICATION_FACTOR / dm.density;
|
||||
for (int i = 0; i < layout.getLineCount(); i++) {
|
||||
boolean endsWithNewLine = text.length() > 0 && text.charAt(layout.getLineEnd(i) - 1) == '\n';
|
||||
float lineWidth = endsWithNewLine ? layout.getLineMax(i) : layout.getLineWidth(i);
|
||||
Rect bounds = new Rect();
|
||||
layout.getLineBounds(i, bounds);
|
||||
WritableMap line = Arguments.createMap();
|
||||
line.putDouble("x", layout.getLineLeft(i) / dm.density);
|
||||
line.putDouble("y", bounds.top / dm.density);
|
||||
line.putDouble("width", layout.getLineWidth(i) / dm.density);
|
||||
line.putDouble("width", lineWidth / dm.density);
|
||||
line.putDouble("height", bounds.height() / dm.density);
|
||||
line.putDouble("descender", layout.getLineDescent(i) / dm.density);
|
||||
line.putDouble("ascender", -layout.getLineAscent(i) / dm.density);
|
||||
|
||||
+5
-30
@@ -69,31 +69,6 @@ public abstract class ReactBaseTextShadowNode extends LayoutShadowNode {
|
||||
|
||||
protected @Nullable ReactTextViewManagerCallback mReactTextViewManagerCallback;
|
||||
|
||||
private static class SetSpanOperation {
|
||||
protected int start, end;
|
||||
protected ReactSpan what;
|
||||
|
||||
SetSpanOperation(int start, int end, ReactSpan what) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.what = what;
|
||||
}
|
||||
|
||||
public void execute(SpannableStringBuilder sb, int priority) {
|
||||
// All spans will automatically extend to the right of the text, but not the left - except
|
||||
// for spans that start at the beginning of the text.
|
||||
int spanFlags = Spannable.SPAN_EXCLUSIVE_INCLUSIVE;
|
||||
if (start == 0) {
|
||||
spanFlags = Spannable.SPAN_INCLUSIVE_INCLUSIVE;
|
||||
}
|
||||
|
||||
spanFlags &= ~Spannable.SPAN_PRIORITY;
|
||||
spanFlags |= (priority << Spannable.SPAN_PRIORITY_SHIFT) & Spannable.SPAN_PRIORITY;
|
||||
|
||||
sb.setSpan(what, start, end, spanFlags);
|
||||
}
|
||||
}
|
||||
|
||||
private static void buildSpannedFromShadowNode(
|
||||
ReactBaseTextShadowNode textShadowNode,
|
||||
SpannableStringBuilder sb,
|
||||
@@ -276,8 +251,9 @@ public abstract class ReactBaseTextShadowNode extends LayoutShadowNode {
|
||||
|
||||
// While setting the Spans on the final text, we also check whether any of them are inline views
|
||||
// or images.
|
||||
int priority = 0;
|
||||
for (SetSpanOperation op : ops) {
|
||||
for (int priorityIndex = 0; priorityIndex < ops.size(); priorityIndex++) {
|
||||
final SetSpanOperation op = ops.get(ops.size() - priorityIndex - 1);
|
||||
|
||||
boolean isInlineImage = op.what instanceof TextInlineImageSpan;
|
||||
if (isInlineImage || op.what instanceof TextInlineViewPlaceholderSpan) {
|
||||
int height;
|
||||
@@ -304,9 +280,8 @@ public abstract class ReactBaseTextShadowNode extends LayoutShadowNode {
|
||||
}
|
||||
|
||||
// Actual order of calling {@code execute} does NOT matter,
|
||||
// but the {@code priority} DOES matter.
|
||||
op.execute(sb, priority);
|
||||
priority++;
|
||||
// but the {@code priorityIndex} DOES matter.
|
||||
op.execute(sb, priorityIndex);
|
||||
}
|
||||
|
||||
textShadowNode.mTextAttributes.setHeightOfTallestInlineViewOrImage(
|
||||
|
||||
+4
-1
@@ -135,7 +135,10 @@ public class ReactTextShadowNode extends ReactBaseTextShadowNode {
|
||||
layoutWidth = width;
|
||||
} else {
|
||||
for (int lineIndex = 0; lineIndex < lineCount; lineIndex++) {
|
||||
float lineWidth = layout.getLineWidth(lineIndex);
|
||||
boolean endsWithNewLine =
|
||||
text.length() > 0 && text.charAt(layout.getLineEnd(lineIndex) - 1) == '\n';
|
||||
float lineWidth =
|
||||
endsWithNewLine ? layout.getLineMax(lineIndex) : layout.getLineWidth(lineIndex);
|
||||
if (lineWidth > layoutWidth) {
|
||||
layoutWidth = lineWidth;
|
||||
}
|
||||
|
||||
+4
-52
@@ -27,12 +27,8 @@ public class ReactTextUpdate {
|
||||
private final float mPaddingBottom;
|
||||
private final int mTextAlign;
|
||||
private final int mTextBreakStrategy;
|
||||
private final int mSelectionStart;
|
||||
private final int mSelectionEnd;
|
||||
private final int mJustificationMode;
|
||||
|
||||
public boolean mContainsMultipleFragments;
|
||||
|
||||
/**
|
||||
* @deprecated Use a non-deprecated constructor for ReactTextUpdate instead. This one remains
|
||||
* because it's being used by a unit test that isn't currently open source.
|
||||
@@ -57,35 +53,7 @@ public class ReactTextUpdate {
|
||||
paddingBottom,
|
||||
textAlign,
|
||||
Layout.BREAK_STRATEGY_HIGH_QUALITY,
|
||||
Layout.JUSTIFICATION_MODE_NONE,
|
||||
-1,
|
||||
-1);
|
||||
}
|
||||
|
||||
public ReactTextUpdate(
|
||||
Spannable text,
|
||||
int jsEventCounter,
|
||||
boolean containsImages,
|
||||
float paddingStart,
|
||||
float paddingTop,
|
||||
float paddingEnd,
|
||||
float paddingBottom,
|
||||
int textAlign,
|
||||
int textBreakStrategy,
|
||||
int justificationMode) {
|
||||
this(
|
||||
text,
|
||||
jsEventCounter,
|
||||
containsImages,
|
||||
paddingStart,
|
||||
paddingTop,
|
||||
paddingEnd,
|
||||
paddingBottom,
|
||||
textAlign,
|
||||
textBreakStrategy,
|
||||
justificationMode,
|
||||
-1,
|
||||
-1);
|
||||
Layout.JUSTIFICATION_MODE_NONE);
|
||||
}
|
||||
|
||||
public ReactTextUpdate(
|
||||
@@ -105,9 +73,7 @@ public class ReactTextUpdate {
|
||||
UNSET,
|
||||
textAlign,
|
||||
textBreakStrategy,
|
||||
justificationMode,
|
||||
-1,
|
||||
-1);
|
||||
justificationMode);
|
||||
}
|
||||
|
||||
public ReactTextUpdate(
|
||||
@@ -120,9 +86,7 @@ public class ReactTextUpdate {
|
||||
float paddingBottom,
|
||||
int textAlign,
|
||||
int textBreakStrategy,
|
||||
int justificationMode,
|
||||
int selectionStart,
|
||||
int selectionEnd) {
|
||||
int justificationMode) {
|
||||
mText = text;
|
||||
mJsEventCounter = jsEventCounter;
|
||||
mContainsImages = containsImages;
|
||||
@@ -132,8 +96,6 @@ public class ReactTextUpdate {
|
||||
mPaddingBottom = paddingBottom;
|
||||
mTextAlign = textAlign;
|
||||
mTextBreakStrategy = textBreakStrategy;
|
||||
mSelectionStart = selectionStart;
|
||||
mSelectionEnd = selectionEnd;
|
||||
mJustificationMode = justificationMode;
|
||||
}
|
||||
|
||||
@@ -142,13 +104,11 @@ public class ReactTextUpdate {
|
||||
int jsEventCounter,
|
||||
int textAlign,
|
||||
int textBreakStrategy,
|
||||
int justificationMode,
|
||||
boolean containsMultipleFragments) {
|
||||
int justificationMode) {
|
||||
|
||||
ReactTextUpdate reactTextUpdate =
|
||||
new ReactTextUpdate(
|
||||
text, jsEventCounter, false, textAlign, textBreakStrategy, justificationMode);
|
||||
reactTextUpdate.mContainsMultipleFragments = containsMultipleFragments;
|
||||
return reactTextUpdate;
|
||||
}
|
||||
|
||||
@@ -191,12 +151,4 @@ public class ReactTextUpdate {
|
||||
public int getJustificationMode() {
|
||||
return mJustificationMode;
|
||||
}
|
||||
|
||||
public int getSelectionStart() {
|
||||
return mSelectionStart;
|
||||
}
|
||||
|
||||
public int getSelectionEnd() {
|
||||
return mSelectionEnd;
|
||||
}
|
||||
}
|
||||
|
||||
+4
-1
@@ -264,11 +264,14 @@ public class ReactTextView extends AppCompatTextView implements ReactCompoundVie
|
||||
// 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) {
|
||||
boolean endsWithNewLine =
|
||||
text.length() > 0 && text.charAt(layout.getLineEnd(line) - 1) == '\n';
|
||||
float lineWidth = endsWithNewLine ? layout.getLineMax(line) : layout.getLineWidth(line);
|
||||
placeholderHorizontalPosition =
|
||||
isRtlParagraph
|
||||
// Equivalent to `layout.getLineLeft(line)` but `getLineLeft` returns incorrect
|
||||
// values when the paragraph is RTL and `setSingleLine(true)`.
|
||||
? textViewWidth - (int) layout.getLineWidth(line)
|
||||
? textViewWidth - (int) lineWidth
|
||||
: (int) layout.getLineRight(line) - width;
|
||||
} else {
|
||||
// The direction of the paragraph may not be exactly the direction the string is heading
|
||||
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
package com.facebook.react.views.text;
|
||||
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
import com.facebook.common.logging.FLog;
|
||||
|
||||
class SetSpanOperation {
|
||||
private static final String TAG = "SetSpanOperation";
|
||||
static final int SPAN_MAX_PRIORITY = Spanned.SPAN_PRIORITY >> Spanned.SPAN_PRIORITY_SHIFT;
|
||||
|
||||
protected int start, end;
|
||||
protected ReactSpan what;
|
||||
|
||||
SetSpanOperation(int start, int end, ReactSpan what) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.what = what;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param sb builder
|
||||
* @param priorityIndex index of this operation in the topological sorting which puts operations
|
||||
* with higher priority before operations with lower priority.
|
||||
*/
|
||||
public void execute(SpannableStringBuilder sb, int priorityIndex) {
|
||||
assert priorityIndex >= 0;
|
||||
|
||||
// All spans will automatically extend to the right of the text, but not the left - except
|
||||
// for spans that start at the beginning of the text.
|
||||
int spanFlags = Spannable.SPAN_EXCLUSIVE_INCLUSIVE;
|
||||
if (start == 0) {
|
||||
spanFlags = Spannable.SPAN_INCLUSIVE_INCLUSIVE;
|
||||
}
|
||||
|
||||
// Calculate priority, assigning the highest values to operations with the highest priority
|
||||
final int priority = SPAN_MAX_PRIORITY - priorityIndex;
|
||||
|
||||
if (priority < 0) {
|
||||
FLog.w(TAG, "Text tree size exceeded the limit, styling may become unpredictable");
|
||||
}
|
||||
|
||||
// If the computed priority doesn't fit in the flags, clamp it. The effect might not be correct
|
||||
// in 100% of cases, but doing nothing (as we did in the past) leads to totally random results.
|
||||
final int effectivePriority = Math.max(priority, 0);
|
||||
|
||||
spanFlags &= ~Spannable.SPAN_PRIORITY;
|
||||
spanFlags |= (effectivePriority << Spannable.SPAN_PRIORITY_SHIFT) & Spannable.SPAN_PRIORITY;
|
||||
|
||||
sb.setSpan(what, start, end, spanFlags);
|
||||
}
|
||||
}
|
||||
+13
-33
@@ -213,12 +213,12 @@ public class TextLayoutManager {
|
||||
|
||||
// TODO T31905686: add support for inline Images
|
||||
// While setting the Spans on the final text, we also check whether any of them are images.
|
||||
int priority = 0;
|
||||
for (SetSpanOperation op : ops) {
|
||||
for (int priorityIndex = 0; priorityIndex < ops.size(); ++priorityIndex) {
|
||||
final SetSpanOperation op = ops.get(ops.size() - priorityIndex - 1);
|
||||
|
||||
// Actual order of calling {@code execute} does NOT matter,
|
||||
// but the {@code priority} DOES matter.
|
||||
op.execute(sb, priority);
|
||||
priority++;
|
||||
// but the {@code priorityIndex} DOES matter.
|
||||
op.execute(sb, priorityIndex);
|
||||
}
|
||||
|
||||
if (reactTextViewManagerCallback != null) {
|
||||
@@ -397,7 +397,10 @@ public class TextLayoutManager {
|
||||
calculatedWidth = width;
|
||||
} else {
|
||||
for (int lineIndex = 0; lineIndex < calculatedLineCount; lineIndex++) {
|
||||
float lineWidth = layout.getLineWidth(lineIndex);
|
||||
boolean endsWithNewLine =
|
||||
text.length() > 0 && text.charAt(layout.getLineEnd(lineIndex) - 1) == '\n';
|
||||
float lineWidth =
|
||||
endsWithNewLine ? layout.getLineMax(lineIndex) : layout.getLineWidth(lineIndex);
|
||||
if (lineWidth > calculatedWidth) {
|
||||
calculatedWidth = lineWidth;
|
||||
}
|
||||
@@ -452,11 +455,14 @@ public class TextLayoutManager {
|
||||
// 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) {
|
||||
boolean endsWithNewLine =
|
||||
text.length() > 0 && text.charAt(layout.getLineEnd(line) - 1) == '\n';
|
||||
float lineWidth = endsWithNewLine ? layout.getLineMax(line) : layout.getLineWidth(line);
|
||||
placeholderLeftPosition =
|
||||
isRtlParagraph
|
||||
// Equivalent to `layout.getLineLeft(line)` but `getLineLeft` returns incorrect
|
||||
// values when the paragraph is RTL and `setSingleLine(true)`.
|
||||
? calculatedWidth - layout.getLineWidth(line)
|
||||
? calculatedWidth - lineWidth
|
||||
: layout.getLineRight(line) - placeholderWidth;
|
||||
} else {
|
||||
// The direction of the paragraph may not be exactly the direction the string is heading
|
||||
@@ -551,30 +557,4 @@ public class TextLayoutManager {
|
||||
hyphenationFrequency);
|
||||
return FontMetricsUtil.getFontMetrics(text, layout, sTextPaintInstance, context);
|
||||
}
|
||||
|
||||
// TODO T31905686: This class should be private
|
||||
public static class SetSpanOperation {
|
||||
protected int start, end;
|
||||
protected ReactSpan what;
|
||||
|
||||
public SetSpanOperation(int start, int end, ReactSpan what) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.what = what;
|
||||
}
|
||||
|
||||
public void execute(Spannable sb, int priority) {
|
||||
// All spans will automatically extend to the right of the text, but not the left - except
|
||||
// for spans that start at the beginning of the text.
|
||||
int spanFlags = Spannable.SPAN_EXCLUSIVE_INCLUSIVE;
|
||||
if (start == 0) {
|
||||
spanFlags = Spannable.SPAN_INCLUSIVE_INCLUSIVE;
|
||||
}
|
||||
|
||||
spanFlags &= ~Spannable.SPAN_PRIORITY;
|
||||
spanFlags |= (priority << Spannable.SPAN_PRIORITY_SHIFT) & Spannable.SPAN_PRIORITY;
|
||||
|
||||
sb.setSpan(what, start, end, spanFlags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+13
-33
@@ -227,12 +227,12 @@ public class TextLayoutManagerMapBuffer {
|
||||
|
||||
// TODO T31905686: add support for inline Images
|
||||
// While setting the Spans on the final text, we also check whether any of them are images.
|
||||
int priority = 0;
|
||||
for (SetSpanOperation op : ops) {
|
||||
for (int priorityIndex = 0; priorityIndex < ops.size(); ++priorityIndex) {
|
||||
final SetSpanOperation op = ops.get(ops.size() - priorityIndex - 1);
|
||||
|
||||
// Actual order of calling {@code execute} does NOT matter,
|
||||
// but the {@code priority} DOES matter.
|
||||
op.execute(sb, priority);
|
||||
priority++;
|
||||
// but the {@code priorityIndex} DOES matter.
|
||||
op.execute(sb, priorityIndex);
|
||||
}
|
||||
|
||||
if (reactTextViewManagerCallback != null) {
|
||||
@@ -411,7 +411,10 @@ public class TextLayoutManagerMapBuffer {
|
||||
calculatedWidth = width;
|
||||
} else {
|
||||
for (int lineIndex = 0; lineIndex < calculatedLineCount; lineIndex++) {
|
||||
float lineWidth = layout.getLineWidth(lineIndex);
|
||||
boolean endsWithNewLine =
|
||||
text.length() > 0 && text.charAt(layout.getLineEnd(lineIndex) - 1) == '\n';
|
||||
float lineWidth =
|
||||
endsWithNewLine ? layout.getLineMax(lineIndex) : layout.getLineWidth(lineIndex);
|
||||
if (lineWidth > calculatedWidth) {
|
||||
calculatedWidth = lineWidth;
|
||||
}
|
||||
@@ -466,12 +469,15 @@ public class TextLayoutManagerMapBuffer {
|
||||
// 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) {
|
||||
boolean endsWithNewLine =
|
||||
text.length() > 0 && text.charAt(layout.getLineEnd(line) - 1) == '\n';
|
||||
float lineWidth = endsWithNewLine ? layout.getLineMax(line) : layout.getLineWidth(line);
|
||||
placeholderLeftPosition =
|
||||
isRtlParagraph
|
||||
// Equivalent to `layout.getLineLeft(line)` but `getLineLeft` returns
|
||||
// incorrect
|
||||
// values when the paragraph is RTL and `setSingleLine(true)`.
|
||||
? calculatedWidth - layout.getLineWidth(line)
|
||||
? calculatedWidth - lineWidth
|
||||
: layout.getLineRight(line) - placeholderWidth;
|
||||
} else {
|
||||
// The direction of the paragraph may not be exactly the direction the string is
|
||||
@@ -570,30 +576,4 @@ public class TextLayoutManagerMapBuffer {
|
||||
hyphenationFrequency);
|
||||
return FontMetricsUtil.getFontMetrics(text, layout, sTextPaintInstance, context);
|
||||
}
|
||||
|
||||
// TODO T31905686: This class should be private
|
||||
public static class SetSpanOperation {
|
||||
protected int start, end;
|
||||
protected ReactSpan what;
|
||||
|
||||
public SetSpanOperation(int start, int end, ReactSpan what) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.what = what;
|
||||
}
|
||||
|
||||
public void execute(Spannable sb, int priority) {
|
||||
// All spans will automatically extend to the right of the text, but not the left - except
|
||||
// for spans that start at the beginning of the text.
|
||||
int spanFlags = Spannable.SPAN_EXCLUSIVE_INCLUSIVE;
|
||||
if (start == 0) {
|
||||
spanFlags = Spannable.SPAN_INCLUSIVE_INCLUSIVE;
|
||||
}
|
||||
|
||||
spanFlags &= ~Spannable.SPAN_PRIORITY;
|
||||
spanFlags |= (priority << Spannable.SPAN_PRIORITY_SHIFT) & Spannable.SPAN_PRIORITY;
|
||||
|
||||
sb.setSpan(what, start, end, spanFlags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user