mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Compare commits
68
Commits
0.79-stable
...
v0.77.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
110450105e | ||
|
|
d682655ec1 | ||
|
|
969eb3f007 | ||
|
|
475f797a51 | ||
|
|
d8af0ae3f2 | ||
|
|
83b986d370 | ||
|
|
8baa858412 | ||
|
|
877e82c1a9 | ||
|
|
55d5c44976 | ||
|
|
bc35afefd5 | ||
|
|
ad8a5de275 | ||
|
|
aef6243edd | ||
|
|
4eef167252 | ||
|
|
46cf58770d | ||
|
|
06c8a745b0 | ||
|
|
50678997b9 | ||
|
|
0ed16b407f | ||
|
|
2561db80b1 | ||
|
|
2013bad254 | ||
|
|
36a0cad953 | ||
|
|
4b3ef3b00c | ||
|
|
e7db7a7266 | ||
|
|
bbbeef6fdb | ||
|
|
407c4fbffd | ||
|
|
5a64bde701 | ||
|
|
17a5d2be5a | ||
|
|
bb9d7ad9a9 | ||
|
|
9d472ae28d | ||
|
|
0bcb0c2b2f | ||
|
|
d34032b6c0 | ||
|
|
489b22c797 | ||
|
|
5b8ed374da | ||
|
|
b0d9ef80da | ||
|
|
e3970a4bb3 | ||
|
|
4370860c8c | ||
|
|
0840eab8ed | ||
|
|
e7c44903e1 | ||
|
|
6b22412069 | ||
|
|
c4c52fb2bd | ||
|
|
d4941c7c6d | ||
|
|
125b0f47d1 | ||
|
|
81aaf46c67 | ||
|
|
621f13f9a2 | ||
|
|
b153ec8af7 | ||
|
|
840382d22f | ||
|
|
77b9c55b22 | ||
|
|
c5b53fdfab | ||
|
|
db798c18d6 | ||
|
|
d4d1788cc5 | ||
|
|
a78d74ca20 | ||
|
|
d81be20084 | ||
|
|
6cde3df040 | ||
|
|
19bff65415 | ||
|
|
88c5b4f8ed | ||
|
|
1c3160c7d0 | ||
|
|
b19898e259 | ||
|
|
22072bffaa | ||
|
|
d663fc4397 | ||
|
|
70f6cec5d7 | ||
|
|
b79ec10b78 | ||
|
|
ee4333812c | ||
|
|
9388a7a699 | ||
|
|
8ab87c617e | ||
|
|
184da8907e | ||
|
|
abfa3a23dc | ||
|
|
f6cce65bec | ||
|
|
385318bf6a | ||
|
|
4cffff35e0 |
@@ -28,10 +28,10 @@ runs:
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: /github/home/.cache/ccache
|
||||
key: v1-ccache-android-${{ github.job }}-${{ github.ref }}
|
||||
key: v2-ccache-android-${{ github.job }}-${{ github.ref }}
|
||||
restore-keys: |
|
||||
v1-ccache-android-${{ github.job }}-
|
||||
v1-ccache-android-
|
||||
v2-ccache-android-${{ github.job }}-
|
||||
v2-ccache-android-
|
||||
- name: Show ccache stats
|
||||
shell: bash
|
||||
run: ccache -s -v
|
||||
@@ -60,7 +60,7 @@ runs:
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: /github/home/.cache/ccache
|
||||
key: v1-ccache-android-${{ github.job }}-${{ github.ref }}
|
||||
key: v2-ccache-android-${{ github.job }}-${{ github.ref }}
|
||||
- name: Show ccache stats
|
||||
shell: bash
|
||||
run: ccache -s -v
|
||||
|
||||
@@ -43,9 +43,6 @@ runs:
|
||||
shell: powershell
|
||||
run: |
|
||||
if (-not(Test-Path -Path $Env:HERMES_WS_DIR\win64-bin\hermesc.exe)) {
|
||||
choco install --no-progress cmake --version 3.14.7 --allow-downgrade
|
||||
if (-not $?) { throw "Failed to install CMake" }
|
||||
|
||||
cd $Env:HERMES_WS_DIR\icu
|
||||
# If Invoke-WebRequest shows a progress bar, it will fail with
|
||||
# Win32 internal error "Access is denied" 0x5 occurred [...]
|
||||
|
||||
@@ -25,6 +25,10 @@ inputs:
|
||||
required: false
|
||||
default: "."
|
||||
description: The directory from which metro should be started
|
||||
architecture:
|
||||
required: false
|
||||
default: "NewArch"
|
||||
description: The react native architecture to test
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
@@ -52,6 +56,7 @@ runs:
|
||||
if: ${{ inputs.flavor == 'debug' }}
|
||||
run: ./packages/react-native-codegen/scripts/oss/build.sh
|
||||
- name: Run e2e tests
|
||||
id: run-tests
|
||||
uses: reactivecircus/android-emulator-runner@v2
|
||||
with:
|
||||
api-level: 24
|
||||
@@ -69,16 +74,16 @@ runs:
|
||||
NORM_APP_ID=$(echo "${{ inputs.app-id }}" | tr '.' '-')
|
||||
echo "app-id=$NORM_APP_ID" >> $GITHUB_OUTPUT
|
||||
- name: Store tests result
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4.3.4
|
||||
if: always()
|
||||
with:
|
||||
name: e2e_android_${{ steps.normalize-app-id.outputs.app-id }}_report_${{ inputs.jsengine }}_${{ inputs.flavor }}
|
||||
name: e2e_android_${{ steps.normalize-app-id.outputs.app-id }}_report_${{ inputs.jsengine }}_${{ inputs.flavor }}_${{ inputs.architecture }}
|
||||
path: |
|
||||
report.xml
|
||||
screen.mp4
|
||||
- name: Store Logs
|
||||
if: failure() && steps.run-tests.outcome == 'failure'
|
||||
if: steps.run-tests.outcome == 'failure'
|
||||
uses: actions/upload-artifact@v4.3.4
|
||||
with:
|
||||
name: maestro-logs-android-${{ steps.normalize-app-id.outputs.app-id }}-${{ inputs.jsengine }}-${{ inputs.flavor }}
|
||||
name: maestro-logs-android-${{ steps.normalize-app-id.outputs.app-id }}-${{ inputs.jsengine }}-${{ inputs.flavor }}-${{ inputs.architecture }}
|
||||
path: /tmp/MaestroLogs
|
||||
|
||||
@@ -21,6 +21,10 @@ inputs:
|
||||
required: false
|
||||
default: "."
|
||||
description: The directory from which metro should be started
|
||||
architecture:
|
||||
required: false
|
||||
default: "NewArch"
|
||||
description: The react native architecture to test
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
@@ -86,8 +90,6 @@ runs:
|
||||
CURR_ATTEMPT=$((CURR_ATTEMPT+1))
|
||||
echo "Attempt number $CURR_ATTEMPT"
|
||||
|
||||
|
||||
|
||||
echo "Start video record using pid: video_record_${{ inputs.jsengine }}_$CURR_ATTEMPT.pid"
|
||||
xcrun simctl io booted recordVideo video_record_$CURR_ATTEMPT.mov & echo $! > video_record_${{ inputs.jsengine }}_$CURR_ATTEMPT.pid
|
||||
|
||||
@@ -105,7 +107,7 @@ runs:
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4.3.4
|
||||
with:
|
||||
name: e2e_ios_${{ inputs.app-id }}_report_${{ inputs.jsengine }}_${{ inputs.flavor }}
|
||||
name: e2e_ios_${{ inputs.app-id }}_report_${{ inputs.jsengine }}_${{ inputs.flavor }}_${{ inputs.architecture }}
|
||||
path: |
|
||||
video_record_1.mov
|
||||
video_record_2.mov
|
||||
@@ -117,5 +119,5 @@ runs:
|
||||
if: failure() && steps.run-tests.outcome == 'failure'
|
||||
uses: actions/upload-artifact@v4.3.4
|
||||
with:
|
||||
name: maestro-logs-${{ inputs.app-id }}-${{ inputs.jsengine }}-${{ inputs.flavor }}
|
||||
name: maestro-logs-${{ inputs.app-id }}-${{ inputs.jsengine }}-${{ inputs.flavor }}-${{ inputs.architecture }}
|
||||
path: /tmp/MaestroLogs
|
||||
|
||||
@@ -55,6 +55,7 @@ async function main() {
|
||||
stdio: 'ignore',
|
||||
detached: true,
|
||||
});
|
||||
metroProcess.unref();
|
||||
console.info(`- Metro PID: ${metroProcess.pid}`);
|
||||
}
|
||||
|
||||
@@ -88,15 +89,15 @@ async function main() {
|
||||
if (IS_DEBUG && metroProcess != null) {
|
||||
const pid = metroProcess.pid;
|
||||
console.info(`Kill Metro. PID: ${pid}`);
|
||||
process.kill(-pid);
|
||||
process.kill(pid);
|
||||
console.info(`Metro Killed`);
|
||||
process.exit();
|
||||
}
|
||||
}
|
||||
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
process.exit();
|
||||
}
|
||||
|
||||
function sleep(ms) {
|
||||
|
||||
@@ -233,6 +233,7 @@ jobs:
|
||||
matrix:
|
||||
jsengine: [Hermes, JSC]
|
||||
flavor: [Debug, Release]
|
||||
architecture: [OldArch, NewArch]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
@@ -277,7 +278,12 @@ jobs:
|
||||
|
||||
cd /tmp/RNTestProject/ios
|
||||
bundle install
|
||||
HERMES_ENGINE_TARBALL_PATH=$HERMES_PATH bundle exec pod install
|
||||
NEW_ARCH_ENABLED=1
|
||||
if [[ ${{ matrix.architecture }} == "OldArch" ]]; then
|
||||
echo "Disable the New Architecture"
|
||||
NEW_ARCH_ENABLED=0
|
||||
fi
|
||||
HERMES_ENGINE_TARBALL_PATH=$HERMES_PATH RCT_NEW_ARCH_ENABLED=$NEW_ARCH_ENABLED bundle exec pod install
|
||||
|
||||
xcodebuild \
|
||||
-scheme "RNTestProject" \
|
||||
@@ -295,6 +301,7 @@ jobs:
|
||||
maestro-flow: ./scripts/e2e/.maestro/
|
||||
flavor: ${{ matrix.flavor }}
|
||||
working-directory: /tmp/RNTestProject
|
||||
architecture: ${{ matrix.architecture }}
|
||||
|
||||
test_e2e_android_templateapp:
|
||||
if: ${{ github.ref == 'refs/heads/main' || contains(github.ref, 'stable') || inputs.run-e2e-tests }}
|
||||
@@ -306,6 +313,7 @@ jobs:
|
||||
matrix:
|
||||
jsengine: [Hermes, JSC]
|
||||
flavor: [debug, release]
|
||||
architecture: [OldArch, NewArch]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
@@ -351,6 +359,11 @@ jobs:
|
||||
cd /tmp/RNTestProject
|
||||
echo "react.internal.mavenLocalRepo=$MAVEN_LOCAL" >> android/gradle.properties
|
||||
|
||||
if [[ ${{matrix.architecture}} == "OldArch" ]]; then
|
||||
echo "Disabling the New Architecture"
|
||||
sed -i 's/newArchEnabled=true/newArchEnabled=false/' android/gradle.properties
|
||||
fi
|
||||
|
||||
# Build
|
||||
cd android
|
||||
CAPITALIZED_FLAVOR=$(echo "${{ matrix.flavor }}" | awk '{print toupper(substr($0, 1, 1)) substr($0, 2)}')
|
||||
@@ -366,6 +379,7 @@ jobs:
|
||||
install-java: 'false'
|
||||
flavor: ${{ matrix.flavor }}
|
||||
working-directory: /tmp/RNTestProject
|
||||
architecture: ${{ matrix.architecture }}
|
||||
|
||||
build_hermesc_linux:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -6,3 +6,4 @@ ruby ">= 2.6.10"
|
||||
gem 'cocoapods', '~> 1.13', '!= 1.15.0', '!= 1.15.1'
|
||||
gem 'activesupport', '>= 6.1.7.5', '< 7.1.0'
|
||||
gem 'xcodeproj', '< 1.26.0'
|
||||
gem 'concurrent-ruby', '< 1.3.4'
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
+5
-5
@@ -5,7 +5,7 @@
|
||||
"license": "MIT",
|
||||
"packageManager": "yarn@1.22.22",
|
||||
"scripts": {
|
||||
"android": "cd packages/rn-tester && npm run android",
|
||||
"android": "yarn --cwd packages/rn-tester android",
|
||||
"build-android": "./gradlew :packages:react-native:ReactAndroid:build",
|
||||
"build": "node ./scripts/build/build.js",
|
||||
"clang-format": "clang-format -i --glob=*/**/*.{h,cpp,m,mm}",
|
||||
@@ -14,14 +14,14 @@
|
||||
"flow": "flow",
|
||||
"format-check": "prettier --list-different \"./**/*.{js,md,yml,ts,tsx}\"",
|
||||
"format": "npm run prettier && npm run clang-format",
|
||||
"featureflags": "cd packages/react-native && yarn featureflags",
|
||||
"featureflags": "yarn --cwd packages/react-native featureflags",
|
||||
"lint-ci": "./scripts/circleci/analyze_code.sh && yarn shellcheck",
|
||||
"lint-java": "node ./scripts/lint-java.js",
|
||||
"lint": "eslint .",
|
||||
"prettier": "prettier --write \"./**/*.{js,md,yml,ts,tsx}\"",
|
||||
"print-packages": "node ./scripts/monorepo/print",
|
||||
"shellcheck": "./scripts/circleci/analyze_scripts.sh",
|
||||
"start": "cd packages/rn-tester && npm run start",
|
||||
"start": "yarn --cwd packages/rn-tester start",
|
||||
"set-version": "node ./scripts/releases/set-version.js",
|
||||
"test-android": "./gradlew :packages:react-native:ReactAndroid:test",
|
||||
"test-ci": "jest --maxWorkers=2 --ci --reporters=\"default\" --reporters=\"jest-junit\"",
|
||||
@@ -48,8 +48,8 @@
|
||||
"@babel/preset-flow": "^7.24.7",
|
||||
"@definitelytyped/dtslint": "^0.0.127",
|
||||
"@jest/create-cache-key-function": "^29.6.3",
|
||||
"@react-native/metro-babel-transformer": "0.77.0-main",
|
||||
"@react-native/metro-config": "0.77.0-main",
|
||||
"@react-native/metro-babel-transformer": "0.77.1",
|
||||
"@react-native/metro-config": "0.77.1",
|
||||
"@tsconfig/node18": "1.0.1",
|
||||
"@types/react": "^18.2.6",
|
||||
"@typescript-eslint/parser": "^7.1.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/assets-registry",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.77.1",
|
||||
"description": "Asset support code for React Native.",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
* @flow strict
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import type {PackagerAsset} from './registry.js';
|
||||
/*:: import type {PackagerAsset} from './registry.js'; */
|
||||
|
||||
const androidScaleSuffix = {
|
||||
'0.75': 'ldpi',
|
||||
@@ -27,7 +27,7 @@ const ANDROID_BASE_DENSITY = 160;
|
||||
* FIXME: using number to represent discrete scale numbers is fragile in essence because of
|
||||
* floating point numbers imprecision.
|
||||
*/
|
||||
function getAndroidAssetSuffix(scale: number): string {
|
||||
function getAndroidAssetSuffix(scale /*: number */) /*: string */ {
|
||||
if (scale.toString() in androidScaleSuffix) {
|
||||
// $FlowFixMe[invalid-computed-prop]
|
||||
return androidScaleSuffix[scale.toString()];
|
||||
@@ -53,9 +53,9 @@ const drawableFileTypes = new Set([
|
||||
]);
|
||||
|
||||
function getAndroidResourceFolderName(
|
||||
asset: PackagerAsset,
|
||||
scale: number,
|
||||
): string {
|
||||
asset /*: PackagerAsset */,
|
||||
scale /*: number */,
|
||||
) /*: string */ {
|
||||
if (!drawableFileTypes.has(asset.type)) {
|
||||
return 'raw';
|
||||
}
|
||||
@@ -73,7 +73,9 @@ function getAndroidResourceFolderName(
|
||||
return 'drawable-' + suffix;
|
||||
}
|
||||
|
||||
function getAndroidResourceIdentifier(asset: PackagerAsset): string {
|
||||
function getAndroidResourceIdentifier(
|
||||
asset /*: PackagerAsset */,
|
||||
) /*: string */ {
|
||||
return (getBasePath(asset) + '/' + asset.name)
|
||||
.toLowerCase()
|
||||
.replace(/\//g, '_') // Encode folder structure in file name
|
||||
@@ -81,7 +83,7 @@ function getAndroidResourceIdentifier(asset: PackagerAsset): string {
|
||||
.replace(/^(?:assets|assetsunstable_path)_/, ''); // Remove "assets_" or "assetsunstable_path_" prefix
|
||||
}
|
||||
|
||||
function getBasePath(asset: PackagerAsset): string {
|
||||
function getBasePath(asset /*: PackagerAsset */) /*: string */ {
|
||||
const basePath = asset.httpServerLocation;
|
||||
return basePath.startsWith('/') ? basePath.slice(1) : basePath;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
/*::
|
||||
export type AssetDestPathResolver = 'android' | 'generic';
|
||||
|
||||
export type PackagerAsset = {
|
||||
@@ -25,16 +26,17 @@ export type PackagerAsset = {
|
||||
+resolver?: AssetDestPathResolver,
|
||||
...
|
||||
};
|
||||
*/
|
||||
|
||||
const assets: Array<PackagerAsset> = [];
|
||||
const assets /*: Array<PackagerAsset> */ = [];
|
||||
|
||||
function registerAsset(asset: PackagerAsset): number {
|
||||
function registerAsset(asset /*: PackagerAsset */) /*: number */ {
|
||||
// `push` returns new array length, so the first asset will
|
||||
// get id 1 (not 0) to make the value truthy
|
||||
return assets.push(asset);
|
||||
}
|
||||
|
||||
function getAssetByID(assetId: number): PackagerAsset {
|
||||
function getAssetByID(assetId /*: number */) /*: PackagerAsset */ {
|
||||
return assets[assetId - 1];
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/babel-plugin-codegen",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.77.1",
|
||||
"description": "Babel plugin to generate native module and view manager code for React Native.",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
@@ -26,7 +26,7 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@babel/traverse": "^7.25.3",
|
||||
"@react-native/codegen": "0.77.0-main"
|
||||
"@react-native/codegen": "0.77.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.25.2"
|
||||
|
||||
@@ -15,7 +15,7 @@ Start the React Native development server.
|
||||
#### Usage
|
||||
|
||||
```sh
|
||||
npx react-native start [options]
|
||||
npx @react-native-community/cli start [options]
|
||||
```
|
||||
|
||||
#### Options
|
||||
@@ -37,6 +37,7 @@ npx react-native start [options]
|
||||
| `--cert <path>` | Specify path to a custom SSL cert. |
|
||||
| `--config <string>` | Path to the CLI configuration file. |
|
||||
| `--no-interactive` | Disable interactive mode. |
|
||||
| `--client-logs` | **[Deprecated]** Enable plain text JavaScript log streaming for all connected apps. |
|
||||
|
||||
### `bundle`
|
||||
|
||||
@@ -45,7 +46,7 @@ Build the bundle for the provided JavaScript entry file.
|
||||
#### Usage
|
||||
|
||||
```sh
|
||||
npx react-native bundle --entry-file <path> [options]
|
||||
npx @react-native-community/cli bundle --entry-file <path> [options]
|
||||
```
|
||||
|
||||
#### Options
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/community-cli-plugin",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.77.1",
|
||||
"description": "Core CLI commands for React Native",
|
||||
"keywords": [
|
||||
"react-native",
|
||||
@@ -22,15 +22,14 @@
|
||||
"dist"
|
||||
],
|
||||
"dependencies": {
|
||||
"@react-native/dev-middleware": "0.77.0-main",
|
||||
"@react-native/metro-babel-transformer": "0.77.0-main",
|
||||
"@react-native/dev-middleware": "0.77.1",
|
||||
"@react-native/metro-babel-transformer": "0.77.1",
|
||||
"chalk": "^4.0.0",
|
||||
"debug": "^2.2.0",
|
||||
"invariant": "^2.2.4",
|
||||
"metro": "^0.81.0",
|
||||
"metro-config": "^0.81.0",
|
||||
"metro-core": "^0.81.0",
|
||||
"node-fetch": "^2.2.0",
|
||||
"readline": "^1.3.0",
|
||||
"semver": "^7.1.3"
|
||||
},
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
import type TerminalReporter from 'metro/src/lib/TerminalReporter';
|
||||
|
||||
import chalk from 'chalk';
|
||||
import fetch from 'node-fetch';
|
||||
|
||||
type PageDescription = $ReadOnly<{
|
||||
id: string,
|
||||
|
||||
@@ -95,6 +95,14 @@ const startCommand: Command = {
|
||||
name: '--no-interactive',
|
||||
description: 'Disables interactive mode',
|
||||
},
|
||||
{
|
||||
name: '--client-logs',
|
||||
description:
|
||||
'[Deprecated] Enable plain text JavaScript log streaming for all ' +
|
||||
'connected apps. This feature is deprecated and will be removed in ' +
|
||||
'future.',
|
||||
default: false,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ export type StartCommandArgs = {
|
||||
config?: string,
|
||||
projectRoot?: string,
|
||||
interactive: boolean,
|
||||
clientLogs: boolean,
|
||||
};
|
||||
|
||||
async function runServer(
|
||||
@@ -96,6 +97,11 @@ async function runServer(
|
||||
require.resolve(plugin),
|
||||
);
|
||||
}
|
||||
// TODO(T214991636): Remove legacy Metro log forwarding
|
||||
if (!args.clientLogs) {
|
||||
// $FlowIgnore[cannot-write] Assigning to readonly property
|
||||
metroConfig.server.forwardClientLogs = false;
|
||||
}
|
||||
|
||||
let reportEvent: (event: TerminalReportableEvent) => void;
|
||||
const terminal = new Terminal(process.stdout);
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
*/
|
||||
|
||||
import net from 'net';
|
||||
import fetch from 'node-fetch';
|
||||
|
||||
/**
|
||||
* Determine whether we can run the dev server.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/core-cli-utils",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.77.1",
|
||||
"description": "React Native CLI library for Frameworks to build on",
|
||||
"license": "MIT",
|
||||
"main": "./src/index.flow.js",
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
@generated SignedSource<<6b92b66e59525cef52902139f863f175>>
|
||||
Git revision: b61aae3ccc6e2684dfbf1e2a06b0f985b459f11f
|
||||
@generated SignedSource<<d09e665db66f49ff47c245adf0a4b543>>
|
||||
Git revision: 6b80704fd50ea0bf10f5f5da5a4343de29aff8b2
|
||||
Built with --nohooks: false
|
||||
Is local checkout: false
|
||||
Remote URL: https://github.com/facebookexperimental/rn-chrome-devtools-frontend
|
||||
Remote branch: main
|
||||
Remote branch: 0.77-stable
|
||||
GN build args (overrides only):
|
||||
is_official_build = true
|
||||
Git status in checkout:
|
||||
|
||||
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -42,7 +42,7 @@ import*as e from"../../ui/legacy/legacy.js";import*as t from"../../core/host/hos
|
||||
<p>${d(a.docsDebuggingBasicsDetail)}</p>
|
||||
</div>
|
||||
</button>
|
||||
<button class="rn-welcome-docsfeed-item" type="button" role="link" @click=${this.#o.bind(this,"https://reactnative.dev/docs/react-devtools")} title=${d(a.docsReactNativeDevTools)}>
|
||||
<button class="rn-welcome-docsfeed-item" type="button" role="link" @click=${this.#o.bind(this,"https://reactnative.dev/docs/react-native-devtools")} title=${d(a.docsReactNativeDevTools)}>
|
||||
<div class="rn-welcome-image" style="background-image: url('${c}')"></div>
|
||||
<div>
|
||||
<p class="devtools-link">${d(a.docsReactNativeDevTools)}</p>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/debugger-frontend",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.77.1",
|
||||
"description": "Debugger frontend for React Native based on Chrome DevTools",
|
||||
"keywords": [
|
||||
"react-native",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/dev-middleware",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.77.1",
|
||||
"description": "Dev server middleware for React Native",
|
||||
"keywords": [
|
||||
"react-native",
|
||||
@@ -23,11 +23,12 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@isaacs/ttlcache": "^1.4.1",
|
||||
"@react-native/debugger-frontend": "0.77.0-main",
|
||||
"@react-native/debugger-frontend": "0.77.1",
|
||||
"chrome-launcher": "^0.15.2",
|
||||
"chromium-edge-launcher": "^0.2.0",
|
||||
"connect": "^3.6.5",
|
||||
"debug": "^2.2.0",
|
||||
"invariant": "^2.2.4",
|
||||
"nullthrows": "^1.1.1",
|
||||
"open": "^7.0.3",
|
||||
"selfsigned": "^2.4.1",
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
import type {CreateCustomMessageHandlerFn} from './inspector-proxy/CustomMessageHandler';
|
||||
import type {BrowserLauncher} from './types/BrowserLauncher';
|
||||
import type {EventReporter} from './types/EventReporter';
|
||||
import type {EventReporter, ReportableEvent} from './types/EventReporter';
|
||||
import type {Experiments, ExperimentsConfig} from './types/Experiments';
|
||||
import type {Logger} from './types/Logger';
|
||||
import type {NextHandleFunction} from 'connect';
|
||||
@@ -81,11 +81,15 @@ export default function createDevMiddleware({
|
||||
unstable_customInspectorMessageHandler,
|
||||
}: Options): DevMiddlewareAPI {
|
||||
const experiments = getExperiments(experimentConfig);
|
||||
const eventReporter = createWrappedEventReporter(
|
||||
unstable_eventReporter,
|
||||
logger,
|
||||
);
|
||||
|
||||
const inspectorProxy = new InspectorProxy(
|
||||
projectRoot,
|
||||
serverBaseUrl,
|
||||
unstable_eventReporter,
|
||||
eventReporter,
|
||||
experiments,
|
||||
unstable_customInspectorMessageHandler,
|
||||
);
|
||||
@@ -97,7 +101,7 @@ export default function createDevMiddleware({
|
||||
serverBaseUrl,
|
||||
inspectorProxy,
|
||||
browserLauncher: unstable_browserLauncher,
|
||||
eventReporter: unstable_eventReporter,
|
||||
eventReporter,
|
||||
experiments,
|
||||
logger,
|
||||
}),
|
||||
@@ -129,3 +133,32 @@ function getExperiments(config: ExperimentsConfig): Experiments {
|
||||
enableNetworkInspector: config.enableNetworkInspector ?? false,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a wrapped EventReporter that locally intercepts events to
|
||||
* log to the terminal.
|
||||
*/
|
||||
function createWrappedEventReporter(
|
||||
reporter: ?EventReporter,
|
||||
logger: ?Logger,
|
||||
): EventReporter {
|
||||
return {
|
||||
logEvent(event: ReportableEvent) {
|
||||
switch (event.type) {
|
||||
case 'fusebox_console_notice':
|
||||
logger?.info(
|
||||
'\n' +
|
||||
'\u001B[7m' +
|
||||
' \u001B[1m💡 JavaScript logs have moved!\u001B[22m They can now be ' +
|
||||
'viewed in React Native DevTools. Tip: Type \u001B[1mj\u001B[22m in ' +
|
||||
'the terminal to open (requires Google Chrome or Microsoft Edge).' +
|
||||
'\u001B[27m' +
|
||||
'\n',
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
reporter?.logEvent(event);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -41,6 +41,8 @@ const PAGES_POLLING_INTERVAL = 1000;
|
||||
// more details.
|
||||
const FILE_PREFIX = 'file://';
|
||||
|
||||
let fuseboxConsoleNoticeLogged = false;
|
||||
|
||||
type DebuggerConnection = {
|
||||
// Debugger web socket connection
|
||||
socket: WS,
|
||||
@@ -513,6 +515,7 @@ export default class Device {
|
||||
// created instead of manually checking this on every getPages result.
|
||||
for (const page of this.#pages.values()) {
|
||||
if (this.#pageHasCapability(page, 'nativePageReloads')) {
|
||||
this.#logFuseboxConsoleNotice();
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1067,4 +1070,14 @@ export default class Device {
|
||||
dangerouslyGetSocket(): WS {
|
||||
return this.#deviceSocket;
|
||||
}
|
||||
|
||||
// TODO(T214991636): Remove notice
|
||||
#logFuseboxConsoleNotice() {
|
||||
if (fuseboxConsoleNoticeLogged) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.#deviceEventReporter?.logFuseboxConsoleNotice();
|
||||
fuseboxConsoleNoticeLogged = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,6 +212,12 @@ class DeviceEventReporter {
|
||||
});
|
||||
}
|
||||
|
||||
logFuseboxConsoleNotice(): void {
|
||||
this.#eventReporter.logEvent({
|
||||
type: 'fusebox_console_notice',
|
||||
});
|
||||
}
|
||||
|
||||
#logExpiredCommand(pendingCommand: PendingCommand): void {
|
||||
this.#eventReporter.logEvent({
|
||||
type: 'debugger_command',
|
||||
|
||||
@@ -77,6 +77,9 @@ export type ReportableEvent =
|
||||
| 'PROTOCOL_ERROR',
|
||||
>,
|
||||
}
|
||||
| {
|
||||
type: 'fusebox_console_notice',
|
||||
}
|
||||
| {
|
||||
type: 'proxy_error',
|
||||
status: 'error',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/eslint-config",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.77.1",
|
||||
"description": "ESLint config for React Native",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
@@ -22,7 +22,7 @@
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.25.2",
|
||||
"@babel/eslint-parser": "^7.25.1",
|
||||
"@react-native/eslint-plugin": "0.77.0-main",
|
||||
"@react-native/eslint-plugin": "0.77.1",
|
||||
"@typescript-eslint/eslint-plugin": "^7.1.1",
|
||||
"@typescript-eslint/parser": "^7.1.1",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/eslint-plugin",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.77.1",
|
||||
"description": "ESLint rules for @react-native/eslint-config",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/eslint-plugin-specs",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.77.1",
|
||||
"description": "ESLint rules to validate NativeModule and Component Specs",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
@@ -26,7 +26,7 @@
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.25.2",
|
||||
"@babel/plugin-transform-flow-strip-types": "^7.25.2",
|
||||
"@react-native/codegen": "0.77.0-main",
|
||||
"@react-native/codegen": "0.77.1",
|
||||
"make-dir": "^2.1.0",
|
||||
"pirates": "^4.0.1",
|
||||
"source-map-support": "0.5.0"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/gradle-plugin",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.77.1",
|
||||
"description": "Gradle Plugin for React Native",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
+7
-3
@@ -12,6 +12,7 @@ import com.facebook.react.utils.detectOSAwareHermesCommand
|
||||
import com.facebook.react.utils.moveTo
|
||||
import com.facebook.react.utils.windowsAwareCommandLine
|
||||
import java.io.File
|
||||
import javax.inject.Inject
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.ConfigurableFileTree
|
||||
import org.gradle.api.file.DirectoryProperty
|
||||
@@ -19,6 +20,7 @@ import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.provider.ListProperty
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.tasks.*
|
||||
import org.gradle.process.ExecOperations
|
||||
|
||||
abstract class BundleHermesCTask : DefaultTask() {
|
||||
|
||||
@@ -26,6 +28,8 @@ abstract class BundleHermesCTask : DefaultTask() {
|
||||
group = "react"
|
||||
}
|
||||
|
||||
@get:Inject abstract val execOperations: ExecOperations
|
||||
|
||||
@get:Internal abstract val root: DirectoryProperty
|
||||
|
||||
@get:InputFiles
|
||||
@@ -127,9 +131,9 @@ abstract class BundleHermesCTask : DefaultTask() {
|
||||
File(jsIntermediateSourceMapsDir.get().asFile, "$bundleAssetName.compiler.map")
|
||||
|
||||
private fun runCommand(command: List<Any>) {
|
||||
project.exec {
|
||||
it.workingDir(root.get().asFile)
|
||||
it.commandLine(command)
|
||||
execOperations.exec { exec ->
|
||||
exec.workingDir(root.get().asFile)
|
||||
exec.commandLine(command)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ abstract class BuildCodegenCLITask : Exec() {
|
||||
}
|
||||
|
||||
override fun exec() {
|
||||
val logfile = "${project.layout.buildDirectory}/build-cli.log"
|
||||
val logfile = "${project.layout.buildDirectory.getAsFile().get()}/build-cli.log"
|
||||
File(logfile).apply {
|
||||
parentFile.mkdirs()
|
||||
if (exists()) {
|
||||
|
||||
@@ -5,3 +5,4 @@ ruby ">= 2.6.10"
|
||||
gem 'cocoapods', '~> 1.13', '!= 1.15.0', '!= 1.15.1'
|
||||
gem 'activesupport', '>= 6.1.7.5', '< 7.1.0'
|
||||
gem 'xcodeproj', '< 1.26.0'
|
||||
gem 'concurrent-ruby', '< 1.3.4'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "helloworld",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.77.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"bootstrap": "node ./cli.js bootstrap",
|
||||
@@ -13,16 +13,16 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "18.3.1",
|
||||
"react-native": "1000.0.0"
|
||||
"react-native": "0.77.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.25.2",
|
||||
"@babel/preset-env": "^7.25.3",
|
||||
"@babel/runtime": "^7.25.0",
|
||||
"@react-native/babel-preset": "0.77.0-main",
|
||||
"@react-native/core-cli-utils": "0.77.0-main",
|
||||
"@react-native/eslint-config": "0.77.0-main",
|
||||
"@react-native/metro-config": "0.77.0-main",
|
||||
"@react-native/babel-preset": "0.77.1",
|
||||
"@react-native/core-cli-utils": "0.77.1",
|
||||
"@react-native/eslint-config": "0.77.1",
|
||||
"@react-native/metro-config": "0.77.1",
|
||||
"chalk": "^4.1.2",
|
||||
"commander": "^12.0.0",
|
||||
"eslint": "^8.19.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/hermes-inspector-msggen",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.77.1",
|
||||
"private": true,
|
||||
"description": "Hermes Inspector Message Generator for React Native",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/metro-config",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.77.1",
|
||||
"description": "Metro configuration for React Native.",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
@@ -26,8 +26,8 @@
|
||||
"dist"
|
||||
],
|
||||
"dependencies": {
|
||||
"@react-native/js-polyfills": "0.77.0-main",
|
||||
"@react-native/metro-babel-transformer": "0.77.0-main",
|
||||
"@react-native/js-polyfills": "0.77.1",
|
||||
"@react-native/metro-babel-transformer": "0.77.1",
|
||||
"metro-config": "^0.81.0",
|
||||
"metro-runtime": "^0.81.0"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/normalize-colors",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.77.1",
|
||||
"description": "Color normalization for React Native.",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/js-polyfills",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.77.1",
|
||||
"description": "Polyfills for React Native.",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/babel-preset",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.77.1",
|
||||
"description": "Babel preset for React Native applications",
|
||||
"main": "src/index.js",
|
||||
"repository": {
|
||||
@@ -55,7 +55,7 @@
|
||||
"@babel/plugin-transform-typescript": "^7.25.2",
|
||||
"@babel/plugin-transform-unicode-regex": "^7.24.7",
|
||||
"@babel/template": "^7.25.0",
|
||||
"@react-native/babel-plugin-codegen": "0.77.0-main",
|
||||
"@react-native/babel-plugin-codegen": "0.77.1",
|
||||
"babel-plugin-syntax-hermes-parser": "0.25.1",
|
||||
"babel-plugin-transform-flow-enums": "^0.0.2",
|
||||
"react-refresh": "^0.14.0"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/metro-babel-transformer",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.77.1",
|
||||
"description": "Babel transformer for React Native applications.",
|
||||
"main": "src/index.js",
|
||||
"repository": {
|
||||
@@ -16,7 +16,7 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.25.2",
|
||||
"@react-native/babel-preset": "0.77.0-main",
|
||||
"@react-native/babel-preset": "0.77.1",
|
||||
"hermes-parser": "0.25.1",
|
||||
"nullthrows": "^1.1.1"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@react-native/bots",
|
||||
"description": "React Native Bots",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.77.1",
|
||||
"private": true,
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/codegen-typescript-test",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.77.1",
|
||||
"private": true,
|
||||
"description": "TypeScript related unit test for @react-native/codegen",
|
||||
"license": "MIT",
|
||||
@@ -19,7 +19,7 @@
|
||||
"prepare": "yarn run build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-native/codegen": "0.77.0-main"
|
||||
"@react-native/codegen": "0.77.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.25.2",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/codegen",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.77.1",
|
||||
"description": "Code generation tools for React Native",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-native-info",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.77.1",
|
||||
"main": "build/index.js",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/popup-menu-android",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.77.1",
|
||||
"description": "PopupMenu for the Android platform",
|
||||
"main": "index.js",
|
||||
"files": [
|
||||
@@ -17,7 +17,7 @@
|
||||
],
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@react-native/codegen": "0.77.0-main"
|
||||
"@react-native/codegen": "0.77.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "^18.2.6",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/oss-library-example",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.77.1",
|
||||
"private": true,
|
||||
"description": "Package that includes native module exapmle, native component example, targets both the old and the new architecture. It should serve as an example of a real-world OSS library.",
|
||||
"license": "MIT",
|
||||
@@ -26,8 +26,8 @@
|
||||
],
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.25.2",
|
||||
"@react-native/babel-preset": "0.77.0-main",
|
||||
"react-native": "1000.0.0"
|
||||
"@react-native/babel-preset": "0.77.1",
|
||||
"react-native": "0.77.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@react-native/test-renderer",
|
||||
"private": true,
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.77.1",
|
||||
"description": "A Test rendering library for React Native",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
|
||||
@@ -106,17 +106,17 @@ export function allowTransformProp(prop: string): void {
|
||||
}
|
||||
|
||||
export function isSupportedColorStyleProp(prop: string): boolean {
|
||||
return Object.hasOwn(SUPPORTED_COLOR_STYLES, prop);
|
||||
return SUPPORTED_COLOR_STYLES.hasOwnProperty(prop);
|
||||
}
|
||||
|
||||
export function isSupportedInterpolationParam(param: string): boolean {
|
||||
return Object.hasOwn(SUPPORTED_INTERPOLATION_PARAMS, param);
|
||||
return SUPPORTED_INTERPOLATION_PARAMS.hasOwnProperty(param);
|
||||
}
|
||||
|
||||
export function isSupportedStyleProp(prop: string): boolean {
|
||||
return Object.hasOwn(SUPPORTED_STYLES, prop);
|
||||
return SUPPORTED_STYLES.hasOwnProperty(prop);
|
||||
}
|
||||
|
||||
export function isSupportedTransformProp(prop: string): boolean {
|
||||
return Object.hasOwn(SUPPORTED_TRANSFORMS, prop);
|
||||
return SUPPORTED_TRANSFORMS.hasOwnProperty(prop);
|
||||
}
|
||||
|
||||
@@ -121,12 +121,10 @@ describe('Animated', () => {
|
||||
|
||||
await unmount(root);
|
||||
|
||||
expect(callback).not.toBeCalled();
|
||||
await jest.runOnlyPendingTimersAsync();
|
||||
expect(callback).toBeCalledWith({finished: false});
|
||||
});
|
||||
|
||||
it('triggers callback when spring is at rest', async () => {
|
||||
it('triggers callback when spring is at rest', () => {
|
||||
const anim = new Animated.Value(0);
|
||||
const callback = jest.fn();
|
||||
Animated.spring(anim, {
|
||||
@@ -134,10 +132,7 @@ describe('Animated', () => {
|
||||
velocity: 0,
|
||||
useNativeDriver: false,
|
||||
}).start(callback);
|
||||
|
||||
expect(callback).not.toBeCalled();
|
||||
await jest.runOnlyPendingTimersAsync();
|
||||
expect(callback).toBeCalledWith({finished: true});
|
||||
expect(callback).toBeCalled();
|
||||
});
|
||||
|
||||
it('send toValue when a critically damped spring stops', () => {
|
||||
|
||||
@@ -165,7 +165,7 @@ export default class Animation {
|
||||
const callback = this.#onEnd;
|
||||
if (callback != null) {
|
||||
this.#onEnd = null;
|
||||
queueMicrotask(() => callback(result));
|
||||
callback(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ function createAnimatedProps(
|
||||
const key = keys[ii];
|
||||
const value = inputProps[key];
|
||||
|
||||
if (allowlist == null || Object.hasOwn(allowlist, key)) {
|
||||
if (allowlist == null || hasOwn(allowlist, key)) {
|
||||
let node;
|
||||
if (key === 'style') {
|
||||
node = AnimatedStyle.from(value, allowlist?.style);
|
||||
@@ -271,3 +271,11 @@ export default class AnimatedProps extends AnimatedNode {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Supported versions of JSC do not implement the newer Object.hasOwn. Remove
|
||||
// this shim when they do.
|
||||
// $FlowIgnore[method-unbinding]
|
||||
const _hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
const hasOwn: (obj: $ReadOnly<{...}>, prop: string) => boolean =
|
||||
// $FlowIgnore[method-unbinding]
|
||||
Object.hasOwn ?? ((obj, prop) => _hasOwnProp.call(obj, prop));
|
||||
|
||||
@@ -35,7 +35,7 @@ function createAnimatedStyle(
|
||||
const key = keys[ii];
|
||||
const value = inputStyle[key];
|
||||
|
||||
if (allowlist == null || Object.hasOwn(allowlist, key)) {
|
||||
if (allowlist == null || hasOwn(allowlist, key)) {
|
||||
let node;
|
||||
if (value != null && key === 'transform') {
|
||||
node = ReactNativeFeatureFlags.shouldUseAnimatedObjectForTransform()
|
||||
@@ -241,3 +241,11 @@ export default class AnimatedStyle extends AnimatedWithChildren {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Supported versions of JSC do not implement the newer Object.hasOwn. Remove
|
||||
// this shim when they do.
|
||||
// $FlowIgnore[method-unbinding]
|
||||
const _hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
const hasOwn: (obj: $ReadOnly<{...}>, prop: string) => boolean =
|
||||
// $FlowIgnore[method-unbinding]
|
||||
Object.hasOwn ?? ((obj, prop) => _hasOwnProp.call(obj, prop));
|
||||
|
||||
@@ -14,9 +14,9 @@ const version: $ReadOnly<{
|
||||
patch: number,
|
||||
prerelease: string | null,
|
||||
}> = {
|
||||
major: 1000,
|
||||
minor: 0,
|
||||
patch: 0,
|
||||
major: 0,
|
||||
minor: 77,
|
||||
patch: 1,
|
||||
prerelease: null,
|
||||
};
|
||||
|
||||
|
||||
@@ -42,9 +42,8 @@ if (__DEV__) {
|
||||
if (!Platform.isTesting) {
|
||||
const HMRClient = require('../Utilities/HMRClient');
|
||||
|
||||
if (global.__FUSEBOX_HAS_FULL_CONSOLE_SUPPORT__) {
|
||||
HMRClient.unstable_notifyFuseboxConsoleEnabled();
|
||||
} else if (console._isPolyfilled) {
|
||||
// TODO(T214991636): Remove legacy Metro log forwarding
|
||||
if (console._isPolyfilled) {
|
||||
// We assume full control over the console and send JavaScript logs to Metro.
|
||||
[
|
||||
'trace',
|
||||
|
||||
@@ -477,7 +477,15 @@ static UIImage *RCTResizeImageIfNeeded(UIImage *image, CGSize size, CGFloat scal
|
||||
|
||||
// Add missing png extension
|
||||
if (request.URL.fileURL && request.URL.pathExtension.length == 0) {
|
||||
mutableRequest.URL = [request.URL URLByAppendingPathExtension:@"png"];
|
||||
// Check if there exists a file with that url on disk already
|
||||
// This should fix issue https://github.com/facebook/react-native/issues/46870
|
||||
if ([[NSFileManager defaultManager] fileExistsAtPath:request.URL.path]) {
|
||||
mutableRequest.URL = request.URL;
|
||||
} else {
|
||||
// This is the default behavior in case there is no file on disk with no extension.
|
||||
// We assume that the extension is `png`.
|
||||
mutableRequest.URL = [request.URL URLByAppendingPathExtension:@"png"];
|
||||
}
|
||||
}
|
||||
if (_redirectDelegate != nil) {
|
||||
mutableRequest.URL = [_redirectDelegate redirectAssetsURL:mutableRequest.URL];
|
||||
|
||||
+11
-3
@@ -28,6 +28,15 @@ type FormDataPart =
|
||||
...
|
||||
};
|
||||
|
||||
/**
|
||||
* Encode a FormData filename compliant with RFC 2183
|
||||
*
|
||||
* https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition#directives
|
||||
*/
|
||||
function encodeFilename(filename: string): string {
|
||||
return encodeURIComponent(filename.replace(/\//g, '_'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Polyfill for XMLHttpRequest2 FormData API, allowing multipart POST requests
|
||||
* with mixed data (string, native files) to be submitted via XMLHttpRequest.
|
||||
@@ -82,9 +91,8 @@ class FormData {
|
||||
// content type (cf. web Blob interface.)
|
||||
if (typeof value === 'object' && !Array.isArray(value) && value) {
|
||||
if (typeof value.name === 'string') {
|
||||
headers['content-disposition'] += `; filename="${
|
||||
value.name
|
||||
}"; filename*=utf-8''${encodeURI(value.name)}`;
|
||||
headers['content-disposition'] +=
|
||||
`; filename="${encodeFilename(value.name)}"`;
|
||||
}
|
||||
if (typeof value.type === 'string') {
|
||||
headers['content-type'] = value.type;
|
||||
|
||||
@@ -48,8 +48,7 @@ describe('FormData', function () {
|
||||
type: 'image/jpeg',
|
||||
name: 'photo.jpg',
|
||||
headers: {
|
||||
'content-disposition':
|
||||
'form-data; name="photo"; filename="photo.jpg"; filename*=utf-8\'\'photo.jpg',
|
||||
'content-disposition': 'form-data; name="photo"; filename="photo.jpg"',
|
||||
'content-type': 'image/jpeg',
|
||||
},
|
||||
fieldName: 'photo',
|
||||
@@ -70,7 +69,7 @@ describe('FormData', function () {
|
||||
name: '测试photo.jpg',
|
||||
headers: {
|
||||
'content-disposition':
|
||||
'form-data; name="photo"; filename="测试photo.jpg"; filename*=utf-8\'\'%E6%B5%8B%E8%AF%95photo.jpg',
|
||||
'form-data; name="photo"; filename="%E6%B5%8B%E8%AF%95photo.jpg"',
|
||||
'content-type': 'image/jpeg',
|
||||
},
|
||||
fieldName: 'photo',
|
||||
|
||||
@@ -476,7 +476,7 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithFrame : (CGRect)frame)
|
||||
_maxLength.integerValue - (NSInteger)backedTextInputView.attributedText.string.length + (NSInteger)range.length,
|
||||
0);
|
||||
|
||||
if (text.length > _maxLength.integerValue) {
|
||||
if (text.length > allowedLength) {
|
||||
// If we typed/pasted more than one character, limit the text inputted.
|
||||
if (text.length > 1) {
|
||||
if (allowedLength > 0) {
|
||||
|
||||
@@ -26,7 +26,6 @@ let hmrUnavailableReason: string | null = null;
|
||||
let currentCompileErrorMessage: string | null = null;
|
||||
let didConnect: boolean = false;
|
||||
let pendingLogs: Array<[LogLevel, $ReadOnlyArray<mixed>]> = [];
|
||||
let pendingFuseboxConsoleNotification = false;
|
||||
|
||||
type LogLevel =
|
||||
| 'trace'
|
||||
@@ -52,7 +51,6 @@ export type HMRClientNativeInterface = {|
|
||||
isEnabled: boolean,
|
||||
scheme?: string,
|
||||
): void,
|
||||
unstable_notifyFuseboxConsoleEnabled(): void,
|
||||
|};
|
||||
|
||||
/**
|
||||
@@ -142,29 +140,6 @@ const HMRClient: HMRClientNativeInterface = {
|
||||
}
|
||||
},
|
||||
|
||||
unstable_notifyFuseboxConsoleEnabled() {
|
||||
if (!hmrClient) {
|
||||
pendingFuseboxConsoleNotification = true;
|
||||
return;
|
||||
}
|
||||
hmrClient.send(
|
||||
JSON.stringify({
|
||||
type: 'log',
|
||||
level: 'info',
|
||||
data: [
|
||||
'\n' +
|
||||
'\u001B[7m' +
|
||||
' \u001B[1m💡 JavaScript logs have moved!\u001B[22m They can now be ' +
|
||||
'viewed in React Native DevTools. Tip: Type \u001B[1mj\u001B[22m in ' +
|
||||
'the terminal to open (requires Google Chrome or Microsoft Edge).' +
|
||||
'\u001B[27m' +
|
||||
'\n',
|
||||
],
|
||||
}),
|
||||
);
|
||||
pendingFuseboxConsoleNotification = false;
|
||||
},
|
||||
|
||||
// Called once by the bridge on startup, even if Fast Refresh is off.
|
||||
// It creates the HMR client but doesn't actually set up the socket yet.
|
||||
setup(
|
||||
@@ -341,9 +316,6 @@ function flushEarlyLogs(client: MetroHMRClient) {
|
||||
pendingLogs.forEach(([level, data]) => {
|
||||
HMRClient.log(level, data);
|
||||
});
|
||||
if (pendingFuseboxConsoleNotification) {
|
||||
HMRClient.unstable_notifyFuseboxConsoleEnabled();
|
||||
}
|
||||
} finally {
|
||||
pendingLogs.length = 0;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ const HMRClientProdShim: HMRClientNativeInterface = {
|
||||
disable() {},
|
||||
registerBundle() {},
|
||||
log() {},
|
||||
unstable_notifyFuseboxConsoleEnabled() {},
|
||||
};
|
||||
|
||||
module.exports = HMRClientProdShim;
|
||||
|
||||
@@ -8942,7 +8942,6 @@ export type HMRClientNativeInterface = {|
|
||||
isEnabled: boolean,
|
||||
scheme?: string
|
||||
): void,
|
||||
unstable_notifyFuseboxConsoleEnabled(): void,
|
||||
|};
|
||||
declare const HMRClient: HMRClientNativeInterface;
|
||||
declare module.exports: HMRClient;
|
||||
|
||||
@@ -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: @(77),
|
||||
RCTVersionPatch: @(1),
|
||||
RCTVersionPrerelease: [NSNull null],
|
||||
};
|
||||
});
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@
|
||||
/**
|
||||
* UIView class for root <ModalHostView> component.
|
||||
*/
|
||||
@interface RCTModalHostViewComponentView : RCTViewComponentView
|
||||
@interface RCTModalHostViewComponentView : RCTViewComponentView <UIAdaptivePresentationControllerDelegate>
|
||||
|
||||
/**
|
||||
* Subclasses may override this method and present the modal on different view controller.
|
||||
|
||||
+12
@@ -149,6 +149,8 @@ static ModalHostViewEventEmitter::OnOrientationChange onOrientationChangeStruct(
|
||||
{
|
||||
BOOL shouldBePresented = !_isPresented && _shouldPresent && self.window;
|
||||
if (shouldBePresented) {
|
||||
self.viewController.presentationController.delegate = self;
|
||||
|
||||
_isPresented = YES;
|
||||
[self presentViewController:self.viewController
|
||||
animated:_shouldAnimatePresentation
|
||||
@@ -274,6 +276,16 @@ static ModalHostViewEventEmitter::OnOrientationChange onOrientationChangeStruct(
|
||||
[childComponentView removeFromSuperview];
|
||||
}
|
||||
|
||||
#pragma mark - UIAdaptivePresentationControllerDelegate
|
||||
|
||||
- (void)presentationControllerDidAttemptToDismiss:(UIPresentationController *)controller
|
||||
{
|
||||
auto eventEmitter = [self modalEventEmitter];
|
||||
if (eventEmitter) {
|
||||
eventEmitter->onRequestClose({});
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
+4
-9
@@ -189,10 +189,11 @@ RCTSendScrollEventForNativeAnimations_DEPRECATED(UIScrollView *scrollView, NSInt
|
||||
|
||||
UIEdgeInsets newEdgeInsets = _scrollView.contentInset;
|
||||
CGFloat inset = MAX(scrollViewLowerY - keyboardEndFrame.origin.y, 0);
|
||||
const auto &props = static_cast<const ScrollViewProps &>(*_props);
|
||||
if (isInverted) {
|
||||
newEdgeInsets.top = MAX(inset, _scrollView.contentInset.top);
|
||||
newEdgeInsets.top = MAX(inset, props.contentInset.top);
|
||||
} else {
|
||||
newEdgeInsets.bottom = MAX(inset, _scrollView.contentInset.bottom);
|
||||
newEdgeInsets.bottom = MAX(inset, props.contentInset.bottom);
|
||||
}
|
||||
|
||||
CGPoint newContentOffset = _scrollView.contentOffset;
|
||||
@@ -210,12 +211,6 @@ RCTSendScrollEventForNativeAnimations_DEPRECATED(UIScrollView *scrollView, NSInt
|
||||
contentDiff = keyboardEndFrame.origin.y - keyboardBeginFrame.origin.y;
|
||||
}
|
||||
} else {
|
||||
CGRect viewIntersection = CGRectIntersection(self.firstResponderFocus, keyboardEndFrame);
|
||||
|
||||
if (CGRectIsNull(viewIntersection)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Inner text field focused
|
||||
CGFloat focusEnd = CGRectGetMaxY(self.firstResponderFocus);
|
||||
if (focusEnd > keyboardEndFrame.origin.y) {
|
||||
@@ -247,7 +242,7 @@ RCTSendScrollEventForNativeAnimations_DEPRECATED(UIScrollView *scrollView, NSInt
|
||||
animations:^{
|
||||
self->_scrollView.contentInset = newEdgeInsets;
|
||||
self->_scrollView.verticalScrollIndicatorInsets = newEdgeInsets;
|
||||
[self scrollToOffset:newContentOffset animated:NO];
|
||||
[self scrollTo:newContentOffset.x y:newContentOffset.y animated:NO];
|
||||
}
|
||||
completion:nil];
|
||||
}
|
||||
|
||||
+11
-1
@@ -68,6 +68,8 @@ static NSSet<NSNumber *> *returnKeyTypesSet;
|
||||
* later comparison insensitive to them.
|
||||
*/
|
||||
NSDictionary<NSAttributedStringKey, id> *_originalTypingAttributes;
|
||||
|
||||
BOOL _hasInputAccessoryView;
|
||||
}
|
||||
|
||||
#pragma mark - UIView overrides
|
||||
@@ -99,9 +101,11 @@ static NSSet<NSNumber *> *returnKeyTypesSet;
|
||||
NSMutableDictionary<NSAttributedStringKey, id> *defaultAttributes =
|
||||
[_backedTextInputView.defaultTextAttributes mutableCopy];
|
||||
|
||||
#if !TARGET_OS_MACCATALYST
|
||||
RCTWeakEventEmitterWrapper *eventEmitterWrapper = [RCTWeakEventEmitterWrapper new];
|
||||
eventEmitterWrapper.eventEmitter = _eventEmitter;
|
||||
defaultAttributes[RCTAttributedStringEventEmitterKey] = eventEmitterWrapper;
|
||||
#endif
|
||||
|
||||
_backedTextInputView.defaultTextAttributes = defaultAttributes;
|
||||
}
|
||||
@@ -262,8 +266,10 @@ static NSSet<NSNumber *> *returnKeyTypesSet;
|
||||
if (newTextInputProps.textAttributes != oldTextInputProps.textAttributes) {
|
||||
NSMutableDictionary<NSAttributedStringKey, id> *defaultAttributes =
|
||||
RCTNSTextAttributesFromTextAttributes(newTextInputProps.getEffectiveTextAttributes(RCTFontSizeMultiplier()));
|
||||
#if !TARGET_OS_MACCATALYST
|
||||
defaultAttributes[RCTAttributedStringEventEmitterKey] =
|
||||
_backedTextInputView.defaultTextAttributes[RCTAttributedStringEventEmitterKey];
|
||||
#endif
|
||||
_backedTextInputView.defaultTextAttributes = defaultAttributes;
|
||||
}
|
||||
|
||||
@@ -606,10 +612,12 @@ static NSSet<NSNumber *> *returnKeyTypesSet;
|
||||
keyboardType == UIKeyboardTypeDecimalPad || keyboardType == UIKeyboardTypeASCIICapableNumberPad) &&
|
||||
(containsKeyType || containsInputAccessoryViewButtonLabel);
|
||||
|
||||
if ((_backedTextInputView.inputAccessoryView != nil) == shouldHaveInputAccessoryView) {
|
||||
if (_hasInputAccessoryView == shouldHaveInputAccessoryView) {
|
||||
return;
|
||||
}
|
||||
|
||||
_hasInputAccessoryView = shouldHaveInputAccessoryView;
|
||||
|
||||
if (shouldHaveInputAccessoryView) {
|
||||
NSString *buttonLabel = inputAccessoryViewButtonLabel != nil ? inputAccessoryViewButtonLabel
|
||||
: [self returnKeyTypeToString:returnKeyType];
|
||||
@@ -635,6 +643,8 @@ static NSSet<NSNumber *> *returnKeyTypesSet;
|
||||
|
||||
- (void)handleInputAccessoryDoneButton
|
||||
{
|
||||
// Ignore the value of whether we submitted; just make sure the submit event is called if necessary.
|
||||
[self textInputShouldSubmitOnReturn];
|
||||
if ([self textInputShouldReturn]) {
|
||||
[_backedTextInputView endEditing:YES];
|
||||
}
|
||||
|
||||
@@ -426,6 +426,10 @@ public abstract interface class com/facebook/react/ReactRootView$ReactRootViewEv
|
||||
public abstract fun onAttachedToReactInstance (Lcom/facebook/react/ReactRootView;)V
|
||||
}
|
||||
|
||||
public abstract class com/facebook/react/TurboReactPackage : com/facebook/react/BaseReactPackage {
|
||||
public fun <init> ()V
|
||||
}
|
||||
|
||||
public abstract interface class com/facebook/react/ViewManagerOnDemandReactPackage {
|
||||
public abstract fun createViewManager (Lcom/facebook/react/bridge/ReactApplicationContext;Ljava/lang/String;)Lcom/facebook/react/uimanager/ViewManager;
|
||||
public abstract fun getViewManagerNames (Lcom/facebook/react/bridge/ReactApplicationContext;)Ljava/util/Collection;
|
||||
@@ -2959,6 +2963,7 @@ public abstract interface annotation class com/facebook/react/module/annotations
|
||||
public final class com/facebook/react/module/model/ReactModuleInfo {
|
||||
public static final field Companion Lcom/facebook/react/module/model/ReactModuleInfo$Companion;
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;ZZZZ)V
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;ZZZZZ)V
|
||||
public final fun canOverrideExistingModule ()Z
|
||||
public static final fun classIsTurboModule (Ljava/lang/Class;)Z
|
||||
public final fun className ()Ljava/lang/String;
|
||||
@@ -7438,6 +7443,7 @@ public class com/facebook/react/views/text/TextAttributeProps {
|
||||
public static final field TA_KEY_LETTER_SPACING S
|
||||
public static final field TA_KEY_LINE_BREAK_STRATEGY S
|
||||
public static final field TA_KEY_LINE_HEIGHT S
|
||||
public static final field TA_KEY_MAX_FONT_SIZE_MULTIPLIER S
|
||||
public static final field TA_KEY_OPACITY S
|
||||
public static final field TA_KEY_ROLE S
|
||||
public static final field TA_KEY_TEXT_DECORATION_COLOR S
|
||||
@@ -7470,6 +7476,7 @@ public class com/facebook/react/views/text/TextAttributeProps {
|
||||
protected field mLetterSpacingInput F
|
||||
protected field mLineHeight F
|
||||
protected field mLineHeightInput F
|
||||
protected field mMaxFontSizeMultiplier F
|
||||
protected field mNumberOfLines I
|
||||
protected field mOpacity F
|
||||
protected field mRole Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$Role;
|
||||
@@ -7831,6 +7838,7 @@ public class com/facebook/react/views/view/ReactViewGroup : android/view/ViewGro
|
||||
protected fun dispatchSetPressed (Z)V
|
||||
public fun draw (Landroid/graphics/Canvas;)V
|
||||
protected fun drawChild (Landroid/graphics/Canvas;Landroid/view/View;J)Z
|
||||
public fun endViewTransition (Landroid/view/View;)V
|
||||
protected fun getChildDrawingOrder (II)I
|
||||
public fun getClippingRect (Landroid/graphics/Rect;)V
|
||||
public fun getHitSlopRect ()Landroid/graphics/Rect;
|
||||
|
||||
@@ -39,9 +39,19 @@ if (PROJECT_ROOT_DIR)
|
||||
# variable is defined if user need to access it.
|
||||
endif ()
|
||||
|
||||
file(GLOB input_SRC CONFIGURE_DEPENDS
|
||||
${REACT_ANDROID_DIR}/cmake-utils/default-app-setup/*.cpp
|
||||
${BUILD_DIR}/generated/autolinking/src/main/jni/*.cpp)
|
||||
file(GLOB override_cpp_SRC CONFIGURE_DEPENDS *.cpp)
|
||||
# We check if the user is providing a custom OnLoad.cpp file. If so, we pick that
|
||||
# for compilation. Otherwise we fallback to using the `default-app-setup/OnLoad.cpp`
|
||||
# file instead.
|
||||
if(override_cpp_SRC)
|
||||
file(GLOB input_SRC CONFIGURE_DEPENDS
|
||||
*.cpp
|
||||
${BUILD_DIR}/generated/autolinking/src/main/jni/*.cpp)
|
||||
else()
|
||||
file(GLOB input_SRC CONFIGURE_DEPENDS
|
||||
${REACT_ANDROID_DIR}/cmake-utils/default-app-setup/*.cpp
|
||||
${BUILD_DIR}/generated/autolinking/src/main/jni/*.cpp)
|
||||
endif()
|
||||
|
||||
add_library(${CMAKE_PROJECT_NAME} SHARED ${input_SRC})
|
||||
|
||||
|
||||
@@ -29,12 +29,7 @@
|
||||
|
||||
#include <DefaultComponentsRegistry.h>
|
||||
#include <DefaultTurboModuleManagerDelegate.h>
|
||||
#if __has_include("<autolinking.h>")
|
||||
#define AUTOLINKING_AVAILABLE 1
|
||||
#include <autolinking.h>
|
||||
#else
|
||||
#define AUTOLINKING_AVAILABLE 0
|
||||
#endif
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <react/renderer/componentregistry/ComponentDescriptorProviderRegistry.h>
|
||||
#include <rncore.h>
|
||||
@@ -61,10 +56,8 @@ void registerComponents(
|
||||
REACT_NATIVE_APP_COMPONENT_REGISTRATION(registry);
|
||||
#endif
|
||||
|
||||
#if AUTOLINKING_AVAILABLE
|
||||
// And we fallback to the components autolinked
|
||||
autolinking_registerProviders(registry);
|
||||
#endif
|
||||
}
|
||||
|
||||
std::shared_ptr<TurboModule> cxxModuleProvider(
|
||||
@@ -78,12 +71,8 @@ std::shared_ptr<TurboModule> cxxModuleProvider(
|
||||
// return std::make_shared<NativeCxxModuleExample>(jsInvoker);
|
||||
// }
|
||||
|
||||
#if AUTOLINKING_AVAILABLE
|
||||
// And we fallback to the CXX module providers autolinked
|
||||
return autolinking_cxxModuleProvider(name, jsInvoker);
|
||||
#endif
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<TurboModule> javaModuleProvider(
|
||||
@@ -112,12 +101,10 @@ std::shared_ptr<TurboModule> javaModuleProvider(
|
||||
return module;
|
||||
}
|
||||
|
||||
#if AUTOLINKING_AVAILABLE
|
||||
// And we fallback to the module providers autolinked
|
||||
if (auto module = autolinking_ModuleProvider(name, params)) {
|
||||
return module;
|
||||
}
|
||||
#endif
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
VERSION_NAME=1000.0.0
|
||||
VERSION_NAME=0.77.1
|
||||
react.internal.publishingGroup=com.facebook.react
|
||||
|
||||
android.useAndroidX=true
|
||||
|
||||
+12
-13
@@ -179,9 +179,18 @@ public abstract class HeadlessJsTaskService extends Service implements HeadlessJ
|
||||
}
|
||||
|
||||
private void createReactContextAndScheduleTask(final HeadlessJsTaskConfig taskConfig) {
|
||||
final ReactHost reactHost = getReactHost();
|
||||
|
||||
if (reactHost == null) { // old arch
|
||||
if (ReactNativeFeatureFlags.enableBridgelessArchitecture()) {
|
||||
final ReactHost reactHost = getReactHost();
|
||||
reactHost.addReactInstanceEventListener(
|
||||
new ReactInstanceEventListener() {
|
||||
@Override
|
||||
public void onReactContextInitialized(@NonNull ReactContext reactContext) {
|
||||
invokeStartTask(reactContext, taskConfig);
|
||||
reactHost.removeReactInstanceEventListener(this);
|
||||
}
|
||||
});
|
||||
reactHost.start();
|
||||
} else {
|
||||
final ReactInstanceManager reactInstanceManager =
|
||||
getReactNativeHost().getReactInstanceManager();
|
||||
|
||||
@@ -194,16 +203,6 @@ public abstract class HeadlessJsTaskService extends Service implements HeadlessJ
|
||||
}
|
||||
});
|
||||
reactInstanceManager.createReactContextInBackground();
|
||||
} else { // new arch
|
||||
reactHost.addReactInstanceEventListener(
|
||||
new ReactInstanceEventListener() {
|
||||
@Override
|
||||
public void onReactContextInitialized(@NonNull ReactContext reactContext) {
|
||||
invokeStartTask(reactContext, taskConfig);
|
||||
reactHost.removeReactInstanceEventListener(this);
|
||||
}
|
||||
});
|
||||
reactHost.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
@Deprecated(
|
||||
message = "Use BaseReactPackage instead",
|
||||
replaceWith = ReplaceWith(expression = "BaseReactPackage"))
|
||||
public abstract class TurboReactPackage : BaseReactPackage() {}
|
||||
+6
-2
@@ -268,8 +268,12 @@ public class StackTraceHelper {
|
||||
List<ReadableMap> readableMapList = new ArrayList<>();
|
||||
for (ParsedError.StackFrame frame : frames) {
|
||||
JavaOnlyMap map = new JavaOnlyMap();
|
||||
map.putDouble(COLUMN_KEY, frame.getColumn());
|
||||
map.putDouble(LINE_NUMBER_KEY, frame.getLineNumber());
|
||||
if (frame.getColumn() != null) {
|
||||
map.putDouble(COLUMN_KEY, frame.getColumn());
|
||||
}
|
||||
if (frame.getLineNumber() != null) {
|
||||
map.putDouble(LINE_NUMBER_KEY, frame.getLineNumber());
|
||||
}
|
||||
map.putString(FILE_KEY, (String) frame.getFile());
|
||||
map.putString(METHOD_NAME_KEY, (String) frame.getMethodName());
|
||||
readableMapList.add(map);
|
||||
|
||||
+15
-8
@@ -330,14 +330,11 @@ public class MountingManager {
|
||||
@AnyThread
|
||||
@ThreadConfined(ANY)
|
||||
public @Nullable EventEmitterWrapper getEventEmitter(int surfaceId, int reactTag) {
|
||||
SurfaceMountingManager surfaceMountingManager =
|
||||
(surfaceId == ViewUtil.NO_SURFACE_ID
|
||||
? getSurfaceManagerForView(reactTag)
|
||||
: getSurfaceManager(surfaceId));
|
||||
if (surfaceMountingManager == null) {
|
||||
SurfaceMountingManager smm = getSurfaceMountingManager(surfaceId, reactTag);
|
||||
if (smm == null) {
|
||||
return null;
|
||||
}
|
||||
return surfaceMountingManager.getEventEmitter(reactTag);
|
||||
return smm.getEventEmitter(reactTag);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -434,11 +431,21 @@ public class MountingManager {
|
||||
boolean canCoalesceEvent,
|
||||
@Nullable WritableMap params,
|
||||
@EventCategoryDef int eventCategory) {
|
||||
@Nullable SurfaceMountingManager smm = getSurfaceManager(surfaceId);
|
||||
SurfaceMountingManager smm = getSurfaceMountingManager(surfaceId, reactTag);
|
||||
if (smm == null) {
|
||||
// Cannot queue event without valid surface mountng manager. Do nothing here.
|
||||
FLog.d(
|
||||
TAG,
|
||||
"Cannot queue event without valid surface mounting manager for tag: %d, surfaceId: %d",
|
||||
reactTag,
|
||||
surfaceId);
|
||||
return;
|
||||
}
|
||||
smm.enqueuePendingEvent(reactTag, eventName, canCoalesceEvent, params, eventCategory);
|
||||
}
|
||||
|
||||
private @Nullable SurfaceMountingManager getSurfaceMountingManager(int surfaceId, int reactTag) {
|
||||
return (surfaceId == ViewUtil.NO_SURFACE_ID
|
||||
? getSurfaceManagerForView(reactTag)
|
||||
: getSurfaceManager(surfaceId));
|
||||
}
|
||||
}
|
||||
|
||||
+18
@@ -21,6 +21,24 @@ public class ReactModuleInfo(
|
||||
public val isCxxModule: Boolean,
|
||||
public val isTurboModule: Boolean
|
||||
) {
|
||||
|
||||
@Deprecated(
|
||||
"This constructor is deprecated and will be removed in the future. Use ReactModuleInfo(String, String, boolean, boolean, boolean, boolean)]",
|
||||
replaceWith =
|
||||
ReplaceWith(
|
||||
expression =
|
||||
"ReactModuleInfo(name, className, canOverrideExistingModule, needsEagerInit, isCxxModule, isTurboModule)"),
|
||||
level = DeprecationLevel.WARNING)
|
||||
public constructor(
|
||||
name: String,
|
||||
className: String,
|
||||
canOverrideExistingModule: Boolean,
|
||||
needsEagerInit: Boolean,
|
||||
@Suppress("UNUSED_PARAMETER") hasConstants: Boolean,
|
||||
isCxxModule: Boolean,
|
||||
isTurboModule: Boolean
|
||||
) : this(name, className, canOverrideExistingModule, needsEagerInit, isCxxModule, isTurboModule)
|
||||
|
||||
public companion object {
|
||||
/**
|
||||
* Checks if the passed class is a TurboModule. Useful to populate the parameter [isTurboModule]
|
||||
|
||||
+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", 77,
|
||||
"patch", 1,
|
||||
"prerelease", null);
|
||||
}
|
||||
|
||||
+9
-8
@@ -16,6 +16,7 @@ import android.graphics.drawable.LayerDrawable
|
||||
import android.os.Build
|
||||
import com.facebook.react.common.annotations.UnstableReactNativeAPI
|
||||
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags
|
||||
import com.facebook.react.uimanager.PixelUtil.dpToPx
|
||||
import com.facebook.react.uimanager.style.BorderInsets
|
||||
import com.facebook.react.uimanager.style.BorderRadiusStyle
|
||||
|
||||
@@ -200,14 +201,14 @@ internal class CompositeBackgroundDrawable(
|
||||
pathForOutline.addRoundRect(
|
||||
RectF(bounds),
|
||||
floatArrayOf(
|
||||
it.topLeft.horizontal + (computedBorderInsets?.left ?: 0f),
|
||||
it.topLeft.vertical + (computedBorderInsets?.top ?: 0f),
|
||||
it.topRight.horizontal + (computedBorderInsets?.right ?: 0f),
|
||||
it.topRight.vertical + (computedBorderInsets?.top ?: 0f),
|
||||
it.bottomRight.horizontal + (computedBorderInsets?.right ?: 0f),
|
||||
it.bottomRight.vertical + (computedBorderInsets?.bottom ?: 0f),
|
||||
it.bottomLeft.horizontal + (computedBorderInsets?.left ?: 0f),
|
||||
it.bottomLeft.vertical) + (computedBorderInsets?.bottom ?: 0f),
|
||||
(it.topLeft.horizontal + (computedBorderInsets?.left ?: 0f)).dpToPx(),
|
||||
(it.topLeft.vertical + (computedBorderInsets?.top ?: 0f)).dpToPx(),
|
||||
(it.topRight.horizontal + (computedBorderInsets?.right ?: 0f)).dpToPx(),
|
||||
(it.topRight.vertical + (computedBorderInsets?.top ?: 0f)).dpToPx(),
|
||||
(it.bottomRight.horizontal + (computedBorderInsets?.right ?: 0f)).dpToPx(),
|
||||
(it.bottomRight.vertical + (computedBorderInsets?.bottom ?: 0f)).dpToPx(),
|
||||
(it.bottomLeft.horizontal + (computedBorderInsets?.left ?: 0f)).dpToPx(),
|
||||
(it.bottomLeft.vertical + (computedBorderInsets?.bottom ?: 0f)).dpToPx()),
|
||||
Path.Direction.CW)
|
||||
}
|
||||
|
||||
|
||||
+16
-2
@@ -61,6 +61,7 @@ public class TextAttributeProps {
|
||||
public static final short TA_KEY_LINE_BREAK_STRATEGY = 25;
|
||||
public static final short TA_KEY_ROLE = 26;
|
||||
public static final short TA_KEY_TEXT_TRANSFORM = 27;
|
||||
public static final short TA_KEY_MAX_FONT_SIZE_MULTIPLIER = 29;
|
||||
|
||||
public static final int UNSET = -1;
|
||||
|
||||
@@ -81,6 +82,7 @@ public class TextAttributeProps {
|
||||
protected float mLineHeight = Float.NaN;
|
||||
protected boolean mIsColorSet = false;
|
||||
protected boolean mAllowFontScaling = true;
|
||||
protected float mMaxFontSizeMultiplier = Float.NaN;
|
||||
protected int mColor;
|
||||
protected boolean mIsBackgroundColorSet = false;
|
||||
protected int mBackgroundColor;
|
||||
@@ -227,6 +229,9 @@ public class TextAttributeProps {
|
||||
case TA_KEY_TEXT_TRANSFORM:
|
||||
result.setTextTransform(entry.getStringValue());
|
||||
break;
|
||||
case TA_KEY_MAX_FONT_SIZE_MULTIPLIER:
|
||||
result.setMaxFontSizeMultiplier((float) entry.getDoubleValue());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,6 +248,8 @@ public class TextAttributeProps {
|
||||
result.setLineHeight(getFloatProp(props, ViewProps.LINE_HEIGHT, ReactConstants.UNSET));
|
||||
result.setLetterSpacing(getFloatProp(props, ViewProps.LETTER_SPACING, Float.NaN));
|
||||
result.setAllowFontScaling(getBooleanProp(props, ViewProps.ALLOW_FONT_SCALING, true));
|
||||
result.setMaxFontSizeMultiplier(
|
||||
getFloatProp(props, ViewProps.MAX_FONT_SIZE_MULTIPLIER, Float.NaN));
|
||||
result.setFontSize(getFloatProp(props, ViewProps.FONT_SIZE, ReactConstants.UNSET));
|
||||
result.setColor(props.hasKey(ViewProps.COLOR) ? props.getInt(ViewProps.COLOR, 0) : null);
|
||||
result.setColor(
|
||||
@@ -411,7 +418,14 @@ public class TextAttributeProps {
|
||||
mAllowFontScaling = allowFontScaling;
|
||||
setFontSize(mFontSizeInput);
|
||||
setLineHeight(mLineHeightInput);
|
||||
setLetterSpacing(mLetterSpacingInput);
|
||||
}
|
||||
}
|
||||
|
||||
private void setMaxFontSizeMultiplier(float maxFontSizeMultiplier) {
|
||||
if (maxFontSizeMultiplier != mMaxFontSizeMultiplier) {
|
||||
mMaxFontSizeMultiplier = maxFontSizeMultiplier;
|
||||
setFontSize(mFontSizeInput);
|
||||
setLineHeight(mLineHeightInput);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -420,7 +434,7 @@ public class TextAttributeProps {
|
||||
if (fontSize != ReactConstants.UNSET) {
|
||||
fontSize =
|
||||
mAllowFontScaling
|
||||
? (float) Math.ceil(PixelUtil.toPixelFromSP(fontSize))
|
||||
? (float) Math.ceil(PixelUtil.toPixelFromSP(fontSize, mMaxFontSizeMultiplier))
|
||||
: (float) Math.ceil(PixelUtil.toPixelFromDIP(fontSize));
|
||||
}
|
||||
mFontSize = (int) fontSize;
|
||||
|
||||
-3
@@ -62,9 +62,6 @@ public abstract class ReactClippingViewManager<T : ReactViewGroup> : ViewGroupMa
|
||||
if (removeClippedSubviews) {
|
||||
val child = getChildAt(parent, index)
|
||||
if (child != null) {
|
||||
if (child.parent != null) {
|
||||
parent.removeView(child)
|
||||
}
|
||||
parent.removeViewWithSubviewClippingEnabled(child)
|
||||
}
|
||||
} else {
|
||||
|
||||
+35
-2
@@ -56,6 +56,8 @@ import com.facebook.react.uimanager.style.BorderRadiusProp;
|
||||
import com.facebook.react.uimanager.style.BorderStyle;
|
||||
import com.facebook.react.uimanager.style.LogicalEdge;
|
||||
import com.facebook.react.uimanager.style.Overflow;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Backing for a React View. Has support for borders, but since borders aren't common, lazy
|
||||
@@ -134,6 +136,7 @@ public class ReactViewGroup extends ViewGroup
|
||||
private @Nullable ViewGroupDrawingOrderHelper mDrawingOrderHelper;
|
||||
private float mBackfaceOpacity;
|
||||
private String mBackfaceVisibility;
|
||||
private @Nullable Set<Integer> mChildrenRemovedWhileTransitioning;
|
||||
|
||||
/**
|
||||
* Creates a new `ReactViewGroup` instance.
|
||||
@@ -167,6 +170,7 @@ public class ReactViewGroup extends ViewGroup
|
||||
mDrawingOrderHelper = null;
|
||||
mBackfaceOpacity = 1.f;
|
||||
mBackfaceVisibility = "visible";
|
||||
mChildrenRemovedWhileTransitioning = null;
|
||||
}
|
||||
|
||||
/* package */ void recycleView() {
|
||||
@@ -349,6 +353,7 @@ public class ReactViewGroup extends ViewGroup
|
||||
return;
|
||||
}
|
||||
mRemoveClippedSubviews = removeClippedSubviews;
|
||||
mChildrenRemovedWhileTransitioning = null;
|
||||
if (removeClippedSubviews) {
|
||||
mClippingRect = new Rect();
|
||||
ReactClippingViewGroupHelper.calculateClippingRect(this, mClippingRect);
|
||||
@@ -402,6 +407,26 @@ public class ReactViewGroup extends ViewGroup
|
||||
updateClippingToRect(mClippingRect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endViewTransition(View view) {
|
||||
super.endViewTransition(view);
|
||||
if (mChildrenRemovedWhileTransitioning != null) {
|
||||
mChildrenRemovedWhileTransitioning.remove(view.getId());
|
||||
}
|
||||
}
|
||||
|
||||
private void trackChildViewTransition(int childId) {
|
||||
if (mChildrenRemovedWhileTransitioning == null) {
|
||||
mChildrenRemovedWhileTransitioning = new HashSet<>();
|
||||
}
|
||||
mChildrenRemovedWhileTransitioning.add(childId);
|
||||
}
|
||||
|
||||
private boolean isChildRemovedWhileTransitioning(View child) {
|
||||
return mChildrenRemovedWhileTransitioning != null
|
||||
&& mChildrenRemovedWhileTransitioning.contains(child.getId());
|
||||
}
|
||||
|
||||
private void updateClippingToRect(Rect clippingRect) {
|
||||
Assertions.assertNotNull(mAllChildren);
|
||||
int clippedSoFar = 0;
|
||||
@@ -548,6 +573,12 @@ public class ReactViewGroup extends ViewGroup
|
||||
} else {
|
||||
setChildrenDrawingOrderEnabled(false);
|
||||
}
|
||||
|
||||
// The parent might not be null in case the child is transitioning.
|
||||
if (child.getParent() != null) {
|
||||
trackChildViewTransition(child.getId());
|
||||
}
|
||||
|
||||
super.onViewRemoved(child);
|
||||
}
|
||||
|
||||
@@ -622,11 +653,12 @@ public class ReactViewGroup extends ViewGroup
|
||||
/*package*/ void addViewWithSubviewClippingEnabled(
|
||||
final View child, int index, ViewGroup.LayoutParams params) {
|
||||
Assertions.assertCondition(mRemoveClippedSubviews);
|
||||
Rect clippingRect = Assertions.assertNotNull(mClippingRect);
|
||||
View[] childArray = Assertions.assertNotNull(mAllChildren);
|
||||
addInArray(child, index);
|
||||
|
||||
// we add view as "clipped" and then run {@link #updateSubviewClipStatus} to conditionally
|
||||
// attach it
|
||||
Rect clippingRect = Assertions.assertNotNull(mClippingRect);
|
||||
View[] childArray = Assertions.assertNotNull(mAllChildren);
|
||||
int clippedSoFar = 0;
|
||||
for (int i = 0; i < index; i++) {
|
||||
if (isViewClipped(childArray[i])) {
|
||||
@@ -676,6 +708,7 @@ public class ReactViewGroup extends ViewGroup
|
||||
}
|
||||
}
|
||||
removeViewsInLayout(index - clippedSoFar, 1);
|
||||
invalidate();
|
||||
}
|
||||
removeFromArray(index);
|
||||
}
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
namespace facebook::react {
|
||||
|
||||
constexpr struct {
|
||||
int32_t Major = 1000;
|
||||
int32_t Minor = 0;
|
||||
int32_t Patch = 0;
|
||||
int32_t Major = 0;
|
||||
int32_t Minor = 77;
|
||||
int32_t Patch = 1;
|
||||
std::string_view Prerelease = "";
|
||||
} ReactNativeVersion;
|
||||
|
||||
|
||||
+13
-4
@@ -123,6 +123,15 @@ std::vector<ExportedMethod> parseExportedMethods(std::string moduleName, Class m
|
||||
NSArray<RCTMethodArgument *> *arguments;
|
||||
SEL objCMethodSelector = NSSelectorFromString(RCTParseMethodSignature(methodInfo->objcName, &arguments));
|
||||
NSMethodSignature *objCMethodSignature = [moduleClass instanceMethodSignatureForSelector:objCMethodSelector];
|
||||
if (objCMethodSignature == nullptr) {
|
||||
RCTLogWarn(
|
||||
@"The objective-c `%s` method signature for the JS method `%@` can not be found in the ObjecitveC definition of the %s module.\nThe `%@` JS method will not be available.",
|
||||
methodInfo->objcName,
|
||||
jsMethodName,
|
||||
moduleName.c_str(),
|
||||
jsMethodName);
|
||||
continue;
|
||||
}
|
||||
std::string objCMethodReturnType = [objCMethodSignature methodReturnType];
|
||||
|
||||
if (objCMethodSignature.numberOfArguments - 2 != [arguments count]) {
|
||||
@@ -337,7 +346,7 @@ void ObjCInteropTurboModule::setInvocationArg(
|
||||
SEL selector = selectorForType(argumentType);
|
||||
|
||||
if ([RCTConvert respondsToSelector:selector]) {
|
||||
id objCArg = TurboModuleConvertUtils::convertJSIValueToObjCObject(runtime, jsiArg, jsInvoker_);
|
||||
id objCArg = TurboModuleConvertUtils::convertJSIValueToObjCObject(runtime, jsiArg, jsInvoker_, YES);
|
||||
|
||||
if (objCArgType == @encode(char)) {
|
||||
char arg = RCTConvertTo<char>(selector, objCArg);
|
||||
@@ -491,7 +500,7 @@ void ObjCInteropTurboModule::setInvocationArg(
|
||||
}
|
||||
|
||||
RCTResponseSenderBlock arg =
|
||||
(RCTResponseSenderBlock)TurboModuleConvertUtils::convertJSIValueToObjCObject(runtime, jsiArg, jsInvoker_);
|
||||
(RCTResponseSenderBlock)TurboModuleConvertUtils::convertJSIValueToObjCObject(runtime, jsiArg, jsInvoker_, YES);
|
||||
if (arg) {
|
||||
[retainedObjectsForInvocation addObject:arg];
|
||||
}
|
||||
@@ -506,7 +515,7 @@ void ObjCInteropTurboModule::setInvocationArg(
|
||||
}
|
||||
|
||||
RCTResponseSenderBlock senderBlock =
|
||||
(RCTResponseSenderBlock)TurboModuleConvertUtils::convertJSIValueToObjCObject(runtime, jsiArg, jsInvoker_);
|
||||
(RCTResponseSenderBlock)TurboModuleConvertUtils::convertJSIValueToObjCObject(runtime, jsiArg, jsInvoker_, YES);
|
||||
RCTResponseErrorBlock arg = ^(NSError *error) {
|
||||
senderBlock(@[ RCTJSErrorFromNSError(error) ]);
|
||||
};
|
||||
@@ -536,7 +545,7 @@ void ObjCInteropTurboModule::setInvocationArg(
|
||||
runtime, errorPrefix + "JavaScript argument must be a plain object. Got " + getType(runtime, jsiArg));
|
||||
}
|
||||
|
||||
id arg = TurboModuleConvertUtils::convertJSIValueToObjCObject(runtime, jsiArg, jsInvoker_);
|
||||
id arg = TurboModuleConvertUtils::convertJSIValueToObjCObject(runtime, jsiArg, jsInvoker_, YES);
|
||||
|
||||
RCTManagedPointer *(*convert)(id, SEL, id) = (__typeof__(convert))objc_msgSend;
|
||||
RCTManagedPointer *box = convert([RCTCxxConvert class], selector, arg);
|
||||
|
||||
+5
@@ -32,6 +32,11 @@ using EventEmitterCallback = std::function<void(const std::string &, id)>;
|
||||
namespace TurboModuleConvertUtils {
|
||||
jsi::Value convertObjCObjectToJSIValue(jsi::Runtime &runtime, id value);
|
||||
id convertJSIValueToObjCObject(jsi::Runtime &runtime, const jsi::Value &value, std::shared_ptr<CallInvoker> jsInvoker);
|
||||
id convertJSIValueToObjCObject(
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &value,
|
||||
std::shared_ptr<CallInvoker> jsInvoker,
|
||||
BOOL useNSNull);
|
||||
} // namespace TurboModuleConvertUtils
|
||||
|
||||
template <>
|
||||
|
||||
+27
-9
@@ -111,21 +111,27 @@ static NSString *convertJSIStringToNSString(jsi::Runtime &runtime, const jsi::St
|
||||
return [NSString stringWithUTF8String:value.utf8(runtime).c_str()];
|
||||
}
|
||||
|
||||
static NSArray *
|
||||
convertJSIArrayToNSArray(jsi::Runtime &runtime, const jsi::Array &value, std::shared_ptr<CallInvoker> jsInvoker)
|
||||
static NSArray *convertJSIArrayToNSArray(
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Array &value,
|
||||
std::shared_ptr<CallInvoker> jsInvoker,
|
||||
BOOL useNSNull)
|
||||
{
|
||||
size_t size = value.size(runtime);
|
||||
NSMutableArray *result = [NSMutableArray new];
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
// Insert kCFNull when it's `undefined` value to preserve the indices.
|
||||
id convertedObject = convertJSIValueToObjCObject(runtime, value.getValueAtIndex(runtime, i), jsInvoker);
|
||||
id convertedObject = convertJSIValueToObjCObject(runtime, value.getValueAtIndex(runtime, i), jsInvoker, useNSNull);
|
||||
[result addObject:convertedObject ? convertedObject : (id)kCFNull];
|
||||
}
|
||||
return [result copy];
|
||||
}
|
||||
|
||||
static NSDictionary *
|
||||
convertJSIObjectToNSDictionary(jsi::Runtime &runtime, const jsi::Object &value, std::shared_ptr<CallInvoker> jsInvoker)
|
||||
static NSDictionary *convertJSIObjectToNSDictionary(
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Object &value,
|
||||
std::shared_ptr<CallInvoker> jsInvoker,
|
||||
BOOL useNSNull)
|
||||
{
|
||||
jsi::Array propertyNames = value.getPropertyNames(runtime);
|
||||
size_t size = propertyNames.size(runtime);
|
||||
@@ -133,7 +139,7 @@ convertJSIObjectToNSDictionary(jsi::Runtime &runtime, const jsi::Object &value,
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
jsi::String name = propertyNames.getValueAtIndex(runtime, i).getString(runtime);
|
||||
NSString *k = convertJSIStringToNSString(runtime, name);
|
||||
id v = convertJSIValueToObjCObject(runtime, value.getProperty(runtime, name), jsInvoker);
|
||||
id v = convertJSIValueToObjCObject(runtime, value.getProperty(runtime, name), jsInvoker, useNSNull);
|
||||
if (v) {
|
||||
result[k] = v;
|
||||
}
|
||||
@@ -161,9 +167,21 @@ convertJSIFunctionToCallback(jsi::Runtime &rt, jsi::Function &&function, std::sh
|
||||
|
||||
id convertJSIValueToObjCObject(jsi::Runtime &runtime, const jsi::Value &value, std::shared_ptr<CallInvoker> jsInvoker)
|
||||
{
|
||||
if (value.isUndefined() || value.isNull()) {
|
||||
return convertJSIValueToObjCObject(runtime, value, jsInvoker, NO);
|
||||
}
|
||||
|
||||
id convertJSIValueToObjCObject(
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &value,
|
||||
std::shared_ptr<CallInvoker> jsInvoker,
|
||||
BOOL useNSNull)
|
||||
{
|
||||
if (value.isUndefined() || (value.isNull() && !useNSNull)) {
|
||||
return nil;
|
||||
}
|
||||
if (value.isNull() && useNSNull) {
|
||||
return [NSNull null];
|
||||
}
|
||||
if (value.isBool()) {
|
||||
return @(value.getBool());
|
||||
}
|
||||
@@ -176,12 +194,12 @@ id convertJSIValueToObjCObject(jsi::Runtime &runtime, const jsi::Value &value, s
|
||||
if (value.isObject()) {
|
||||
jsi::Object o = value.getObject(runtime);
|
||||
if (o.isArray(runtime)) {
|
||||
return convertJSIArrayToNSArray(runtime, o.getArray(runtime), jsInvoker);
|
||||
return convertJSIArrayToNSArray(runtime, o.getArray(runtime), jsInvoker, useNSNull);
|
||||
}
|
||||
if (o.isFunction(runtime)) {
|
||||
return convertJSIFunctionToCallback(runtime, o.getFunction(runtime), jsInvoker);
|
||||
}
|
||||
return convertJSIObjectToNSDictionary(runtime, o, jsInvoker);
|
||||
return convertJSIObjectToNSDictionary(runtime, o, jsInvoker, useNSNull);
|
||||
}
|
||||
|
||||
throw std::runtime_error("Unsupported jsi::Value kind");
|
||||
|
||||
@@ -46,6 +46,9 @@ void TextAttributes::apply(TextAttributes textAttributes) {
|
||||
allowFontScaling = textAttributes.allowFontScaling.has_value()
|
||||
? textAttributes.allowFontScaling
|
||||
: allowFontScaling;
|
||||
maxFontSizeMultiplier = !std::isnan(textAttributes.maxFontSizeMultiplier)
|
||||
? textAttributes.maxFontSizeMultiplier
|
||||
: maxFontSizeMultiplier;
|
||||
dynamicTypeRamp = textAttributes.dynamicTypeRamp.has_value()
|
||||
? textAttributes.dynamicTypeRamp
|
||||
: dynamicTypeRamp;
|
||||
@@ -168,6 +171,7 @@ bool TextAttributes::operator==(const TextAttributes& rhs) const {
|
||||
rhs.accessibilityRole,
|
||||
rhs.role,
|
||||
rhs.textTransform) &&
|
||||
floatEquality(maxFontSizeMultiplier, rhs.maxFontSizeMultiplier) &&
|
||||
floatEquality(opacity, rhs.opacity) &&
|
||||
floatEquality(fontSize, rhs.fontSize) &&
|
||||
floatEquality(fontSizeMultiplier, rhs.fontSizeMultiplier) &&
|
||||
@@ -211,6 +215,8 @@ SharedDebugStringConvertibleList TextAttributes::getDebugProps() const {
|
||||
debugStringConvertibleItem("fontStyle", fontStyle),
|
||||
debugStringConvertibleItem("fontVariant", fontVariant),
|
||||
debugStringConvertibleItem("allowFontScaling", allowFontScaling),
|
||||
debugStringConvertibleItem(
|
||||
"maxFontSizeMultiplier", maxFontSizeMultiplier),
|
||||
debugStringConvertibleItem("dynamicTypeRamp", dynamicTypeRamp),
|
||||
debugStringConvertibleItem("letterSpacing", letterSpacing),
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ class TextAttributes : public DebugStringConvertible {
|
||||
std::optional<FontStyle> fontStyle{};
|
||||
std::optional<FontVariant> fontVariant{};
|
||||
std::optional<bool> allowFontScaling{};
|
||||
Float maxFontSizeMultiplier{std::numeric_limits<Float>::quiet_NaN()};
|
||||
std::optional<DynamicTypeRamp> dynamicTypeRamp{};
|
||||
Float letterSpacing{std::numeric_limits<Float>::quiet_NaN()};
|
||||
std::optional<TextTransform> textTransform{};
|
||||
@@ -117,6 +118,7 @@ struct hash<facebook::react::TextAttributes> {
|
||||
textAttributes.opacity,
|
||||
textAttributes.fontFamily,
|
||||
textAttributes.fontSize,
|
||||
textAttributes.maxFontSizeMultiplier,
|
||||
textAttributes.fontSizeMultiplier,
|
||||
textAttributes.fontWeight,
|
||||
textAttributes.fontStyle,
|
||||
|
||||
@@ -910,6 +910,7 @@ constexpr static MapBuffer::Key TA_KEY_LINE_BREAK_STRATEGY = 25;
|
||||
constexpr static MapBuffer::Key TA_KEY_ROLE = 26;
|
||||
constexpr static MapBuffer::Key TA_KEY_TEXT_TRANSFORM = 27;
|
||||
constexpr static MapBuffer::Key TA_KEY_ALIGNMENT_VERTICAL = 28;
|
||||
constexpr static MapBuffer::Key TA_KEY_MAX_FONT_SIZE_MULTIPLIER = 29;
|
||||
|
||||
// constants for ParagraphAttributes serialization
|
||||
constexpr static MapBuffer::Key PA_KEY_MAX_NUMBER_OF_LINES = 0;
|
||||
@@ -1004,6 +1005,10 @@ inline MapBuffer toMapBuffer(const TextAttributes& textAttributes) {
|
||||
builder.putBool(
|
||||
TA_KEY_ALLOW_FONT_SCALING, *textAttributes.allowFontScaling);
|
||||
}
|
||||
if (!std::isnan(textAttributes.maxFontSizeMultiplier)) {
|
||||
builder.putDouble(
|
||||
TA_KEY_MAX_FONT_SIZE_MULTIPLIER, textAttributes.maxFontSizeMultiplier);
|
||||
}
|
||||
if (!std::isnan(textAttributes.letterSpacing)) {
|
||||
builder.putDouble(TA_KEY_LETTER_SPACING, textAttributes.letterSpacing);
|
||||
}
|
||||
|
||||
@@ -73,6 +73,12 @@ static TextAttributes convertRawProp(
|
||||
"allowFontScaling",
|
||||
sourceTextAttributes.allowFontScaling,
|
||||
defaultTextAttributes.allowFontScaling);
|
||||
textAttributes.maxFontSizeMultiplier = convertRawProp(
|
||||
context,
|
||||
rawProps,
|
||||
"maxFontSizeMultiplier",
|
||||
sourceTextAttributes.maxFontSizeMultiplier,
|
||||
defaultTextAttributes.maxFontSizeMultiplier);
|
||||
textAttributes.dynamicTypeRamp = convertRawProp(
|
||||
context,
|
||||
rawProps,
|
||||
@@ -266,6 +272,12 @@ void BaseTextProps::setProp(
|
||||
defaults, value, textAttributes, fontVariant, "fontVariant");
|
||||
REBUILD_FIELD_SWITCH_CASE(
|
||||
defaults, value, textAttributes, allowFontScaling, "allowFontScaling");
|
||||
REBUILD_FIELD_SWITCH_CASE(
|
||||
defaults,
|
||||
value,
|
||||
textAttributes,
|
||||
maxFontSizeMultiplier,
|
||||
"maxFontSizeMultiplier");
|
||||
REBUILD_FIELD_SWITCH_CASE(
|
||||
defaults, value, textAttributes, letterSpacing, "letterSpacing");
|
||||
REBUILD_FIELD_SWITCH_CASE(
|
||||
|
||||
+2
-3
@@ -208,8 +208,7 @@ inline bool operator==(
|
||||
return areAttributedStringsEquivalentLayoutWise(
|
||||
lhs.attributedString, rhs.attributedString) &&
|
||||
lhs.paragraphAttributes == rhs.paragraphAttributes &&
|
||||
lhs.layoutConstraints.maximumSize.width ==
|
||||
rhs.layoutConstraints.maximumSize.width;
|
||||
lhs.layoutConstraints == rhs.layoutConstraints;
|
||||
}
|
||||
|
||||
inline bool operator!=(
|
||||
@@ -243,7 +242,7 @@ struct hash<facebook::react::TextMeasureCacheKey> {
|
||||
return facebook::react::hash_combine(
|
||||
attributedStringHashLayoutWise(key.attributedString),
|
||||
key.paragraphAttributes,
|
||||
key.layoutConstraints.maximumSize.width);
|
||||
key.layoutConstraints);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+7
-3
@@ -135,6 +135,7 @@ inline static CGFloat RCTBaseSizeForDynamicTypeRamp(const DynamicTypeRamp &dynam
|
||||
inline static CGFloat RCTEffectiveFontSizeMultiplierFromTextAttributes(const TextAttributes &textAttributes)
|
||||
{
|
||||
if (textAttributes.allowFontScaling.value_or(true)) {
|
||||
CGFloat fontSizeMultiplier = !isnan(textAttributes.fontSizeMultiplier) ? textAttributes.fontSizeMultiplier : 1.0;
|
||||
if (textAttributes.dynamicTypeRamp.has_value()) {
|
||||
DynamicTypeRamp dynamicTypeRamp = textAttributes.dynamicTypeRamp.value();
|
||||
UIFontMetrics *fontMetrics =
|
||||
@@ -142,10 +143,11 @@ inline static CGFloat RCTEffectiveFontSizeMultiplierFromTextAttributes(const Tex
|
||||
// Using a specific font size reduces rounding errors from -scaledValueForValue:
|
||||
CGFloat requestedSize =
|
||||
isnan(textAttributes.fontSize) ? RCTBaseSizeForDynamicTypeRamp(dynamicTypeRamp) : textAttributes.fontSize;
|
||||
return [fontMetrics scaledValueForValue:requestedSize] / requestedSize;
|
||||
} else {
|
||||
return textAttributes.fontSizeMultiplier;
|
||||
fontSizeMultiplier = [fontMetrics scaledValueForValue:requestedSize] / requestedSize;
|
||||
}
|
||||
CGFloat maxFontSizeMultiplier =
|
||||
!isnan(textAttributes.maxFontSizeMultiplier) ? textAttributes.maxFontSizeMultiplier : 0.0;
|
||||
return maxFontSizeMultiplier >= 1.0 ? fminf(maxFontSizeMultiplier, fontSizeMultiplier) : fontSizeMultiplier;
|
||||
} else {
|
||||
return 1.0;
|
||||
}
|
||||
@@ -403,6 +405,7 @@ static NSMutableAttributedString *RCTNSAttributedStringFragmentWithAttributesFro
|
||||
{
|
||||
auto nsAttributedStringFragment = RCTNSAttributedStringFragmentFromFragment(fragment, placeholderImage);
|
||||
|
||||
#if !TARGET_OS_MACCATALYST
|
||||
if (fragment.parentShadowView.componentHandle) {
|
||||
RCTWeakEventEmitterWrapper *eventEmitterWrapper = [RCTWeakEventEmitterWrapper new];
|
||||
eventEmitterWrapper.eventEmitter = fragment.parentShadowView.eventEmitter;
|
||||
@@ -413,6 +416,7 @@ static NSMutableAttributedString *RCTNSAttributedStringFragmentWithAttributesFro
|
||||
[nsAttributedStringFragment addAttributes:additionalTextAttributes
|
||||
range:NSMakeRange(0, nsAttributedStringFragment.length)];
|
||||
}
|
||||
#endif
|
||||
|
||||
return nsAttributedStringFragment;
|
||||
}
|
||||
|
||||
@@ -236,47 +236,51 @@ std::string simpleBasename(const std::string& path) {
|
||||
*/
|
||||
void ReactInstance::loadScript(
|
||||
std::unique_ptr<const JSBigString> script,
|
||||
const std::string& sourceURL) {
|
||||
const std::string& sourceURL,
|
||||
std::function<void(jsi::Runtime& runtime)>&& completion) {
|
||||
auto buffer = std::make_shared<BigStringBuffer>(std::move(script));
|
||||
std::string scriptName = simpleBasename(sourceURL);
|
||||
|
||||
runtimeScheduler_->scheduleWork(
|
||||
[this,
|
||||
scriptName,
|
||||
sourceURL,
|
||||
buffer = std::move(buffer),
|
||||
weakBufferedRuntimeExecuter = std::weak_ptr<BufferedRuntimeExecutor>(
|
||||
bufferedRuntimeExecutor_)](jsi::Runtime& runtime) {
|
||||
SystraceSection s("ReactInstance::loadScript");
|
||||
bool hasLogger(ReactMarker::logTaggedMarkerBridgelessImpl);
|
||||
if (hasLogger) {
|
||||
ReactMarker::logTaggedMarkerBridgeless(
|
||||
ReactMarker::RUN_JS_BUNDLE_START, scriptName.c_str());
|
||||
}
|
||||
runtimeScheduler_->scheduleWork([this,
|
||||
scriptName,
|
||||
sourceURL,
|
||||
buffer = std::move(buffer),
|
||||
weakBufferedRuntimeExecuter =
|
||||
std::weak_ptr<BufferedRuntimeExecutor>(
|
||||
bufferedRuntimeExecutor_),
|
||||
completion](jsi::Runtime& runtime) {
|
||||
SystraceSection s("ReactInstance::loadScript");
|
||||
bool hasLogger(ReactMarker::logTaggedMarkerBridgelessImpl);
|
||||
if (hasLogger) {
|
||||
ReactMarker::logTaggedMarkerBridgeless(
|
||||
ReactMarker::RUN_JS_BUNDLE_START, scriptName.c_str());
|
||||
}
|
||||
|
||||
runtime.evaluateJavaScript(buffer, sourceURL);
|
||||
runtime.evaluateJavaScript(buffer, sourceURL);
|
||||
|
||||
/**
|
||||
* TODO(T183610671): We need a safe/reliable way to enable the js
|
||||
* pipeline from javascript. Remove this after we figure that out, or
|
||||
* after we just remove the js pipeline.
|
||||
*/
|
||||
if (!jsErrorHandler_->hasHandledFatalError()) {
|
||||
jsErrorHandler_->setRuntimeReady();
|
||||
}
|
||||
/**
|
||||
* TODO(T183610671): We need a safe/reliable way to enable the js
|
||||
* pipeline from javascript. Remove this after we figure that out, or
|
||||
* after we just remove the js pipeline.
|
||||
*/
|
||||
if (!jsErrorHandler_->hasHandledFatalError()) {
|
||||
jsErrorHandler_->setRuntimeReady();
|
||||
}
|
||||
|
||||
if (hasLogger) {
|
||||
ReactMarker::logTaggedMarkerBridgeless(
|
||||
ReactMarker::RUN_JS_BUNDLE_STOP, scriptName.c_str());
|
||||
ReactMarker::logMarkerBridgeless(
|
||||
ReactMarker::INIT_REACT_RUNTIME_STOP);
|
||||
ReactMarker::logMarkerBridgeless(ReactMarker::APP_STARTUP_STOP);
|
||||
}
|
||||
if (auto strongBufferedRuntimeExecuter =
|
||||
weakBufferedRuntimeExecuter.lock()) {
|
||||
strongBufferedRuntimeExecuter->flush();
|
||||
}
|
||||
});
|
||||
if (hasLogger) {
|
||||
ReactMarker::logTaggedMarkerBridgeless(
|
||||
ReactMarker::RUN_JS_BUNDLE_STOP, scriptName.c_str());
|
||||
ReactMarker::logMarkerBridgeless(ReactMarker::INIT_REACT_RUNTIME_STOP);
|
||||
ReactMarker::logMarkerBridgeless(ReactMarker::APP_STARTUP_STOP);
|
||||
}
|
||||
if (auto strongBufferedRuntimeExecuter =
|
||||
weakBufferedRuntimeExecuter.lock()) {
|
||||
strongBufferedRuntimeExecuter->flush();
|
||||
}
|
||||
if (completion) {
|
||||
completion(runtime);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -49,7 +49,8 @@ class ReactInstance final : private jsinspector_modern::InstanceTargetDelegate {
|
||||
|
||||
void loadScript(
|
||||
std::unique_ptr<const JSBigString> script,
|
||||
const std::string& sourceURL);
|
||||
const std::string& sourceURL,
|
||||
std::function<void(jsi::Runtime& runtime)>&& completion = nullptr);
|
||||
|
||||
void registerSegment(uint32_t segmentId, const std::string& segmentPath);
|
||||
|
||||
|
||||
+3
-2
@@ -472,8 +472,9 @@ void RCTInstanceSetRuntimeDiagnosticFlags(NSString *flags)
|
||||
|
||||
auto script = std::make_unique<NSDataBigString>(source.data);
|
||||
const auto *url = deriveSourceURL(source.url).UTF8String;
|
||||
_reactInstance->loadScript(std::move(script), url);
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:@"RCTInstanceDidLoadBundle" object:nil];
|
||||
_reactInstance->loadScript(std::move(script), url, [](jsi::Runtime &_) {
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:@"RCTInstanceDidLoadBundle" object:nil];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)_handleJSError:(const JsErrorHandler::ParsedError &)error withRuntime:(jsi::Runtime &)runtime
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-native",
|
||||
"version": "1000.0.0",
|
||||
"version": "0.77.1",
|
||||
"description": "A framework for building native apps using React",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
@@ -108,13 +108,13 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@jest/create-cache-key-function": "^29.6.3",
|
||||
"@react-native/assets-registry": "0.77.0-main",
|
||||
"@react-native/codegen": "0.77.0-main",
|
||||
"@react-native/community-cli-plugin": "0.77.0-main",
|
||||
"@react-native/gradle-plugin": "0.77.0-main",
|
||||
"@react-native/js-polyfills": "0.77.0-main",
|
||||
"@react-native/normalize-colors": "0.77.0-main",
|
||||
"@react-native/virtualized-lists": "0.77.0-main",
|
||||
"@react-native/assets-registry": "0.77.1",
|
||||
"@react-native/codegen": "0.77.1",
|
||||
"@react-native/community-cli-plugin": "0.77.1",
|
||||
"@react-native/gradle-plugin": "0.77.1",
|
||||
"@react-native/js-polyfills": "0.77.1",
|
||||
"@react-native/normalize-colors": "0.77.1",
|
||||
"@react-native/virtualized-lists": "0.77.1",
|
||||
"abort-controller": "^3.0.0",
|
||||
"anser": "^1.4.9",
|
||||
"ansi-regex": "^5.0.0",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user