Compare commits

..
Author SHA1 Message Date
CodemodService BotandFacebook GitHub Bot 873c65d871 Fix CQS signal readability-implicit-bool-conversion in xplat/js/react-native-github/packages [B]
Reviewed By: rshest

Differential Revision: D81699709
2025-09-05 01:26:10 -07:00
247 changed files with 1923 additions and 4821 deletions
-1
View File
@@ -19,7 +19,6 @@ on:
jobs:
create_release:
if: github.repository == 'facebook/react-native'
runs-on: ubuntu-latest
steps:
- name: Checkout
+3 -6
View File
@@ -23,7 +23,6 @@ jobs:
prepare_hermes_workspace:
runs-on: ubuntu-latest
if: github.repository == 'facebook/react-native'
env:
HERMES_WS_DIR: /tmp/hermes
HERMES_VERSION_FILE: packages/react-native/sdks/.hermesversion
@@ -51,8 +50,8 @@ jobs:
- name: Build HermesC Apple
uses: ./.github/actions/build-hermesc-apple
with:
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
hermes-version: ${{ needs.prepare_hermes_workspace.output.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.output.react-native-version }}
build_apple_slices_hermes:
runs-on: macos-14
@@ -76,7 +75,7 @@ jobs:
uses: ./.github/actions/build-apple-slices-hermes
with:
flavor: ${{ matrix.flavor }}
slice: ${{ matrix.slice }}
slice: ${{ matrix.slice}}
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
@@ -102,7 +101,6 @@ jobs:
flavor: ${{ matrix.flavor }}
prebuild_apple_dependencies:
if: github.repository == 'facebook/react-native'
uses: ./.github/workflows/prebuild-ios-dependencies.yml
secrets: inherit
@@ -147,7 +145,6 @@ jobs:
build_android:
runs-on: 8-core-ubuntu
if: github.repository == 'facebook/react-native'
needs: [set_release_type]
container:
image: reactnativecommunity/react-native-android:latest
@@ -9,7 +9,6 @@ on:
jobs:
publish_bumped_packages:
runs-on: ubuntu-latest
if: github.repository == 'facebook/react-native'
env:
GHA_NPM_TOKEN: ${{ secrets.GHA_NPM_TOKEN }}
steps:
-2
View File
@@ -21,7 +21,6 @@ jobs:
prepare_hermes_workspace:
runs-on: ubuntu-latest
if: github.repository == 'facebook/react-native'
env:
HERMES_WS_DIR: /tmp/hermes
HERMES_VERSION_FILE: packages/react-native/sdks/.hermesversion
@@ -99,7 +98,6 @@ jobs:
flavor: ${{ matrix.flavor }}
prebuild_apple_dependencies:
if: github.repository == 'facebook/react-native'
uses: ./.github/workflows/prebuild-ios-dependencies.yml
secrets: inherit
-1
View File
@@ -9,7 +9,6 @@ on:
jobs:
rerun:
runs-on: ubuntu-latest
if: github.repository == 'facebook/react-native'
steps:
- name: rerun ${{ inputs.run_id }}
env:
+2 -9
View File
@@ -11,7 +11,6 @@ on:
jobs:
set_release_type:
runs-on: ubuntu-latest
if: github.repository == 'facebook/react-native'
outputs:
RELEASE_TYPE: ${{ steps.set_release_type.outputs.RELEASE_TYPE }}
env:
@@ -35,7 +34,6 @@ jobs:
prepare_hermes_workspace:
runs-on: ubuntu-latest
if: github.repository == 'facebook/react-native'
env:
HERMES_WS_DIR: /tmp/hermes
HERMES_VERSION_FILE: packages/react-native/sdks/.hermesversion
@@ -114,7 +112,6 @@ jobs:
flavor: ${{ matrix.flavor }}
prebuild_apple_dependencies:
if: github.repository == 'facebook/react-native'
uses: ./.github/workflows/prebuild-ios-dependencies.yml
secrets: inherit
@@ -276,8 +273,7 @@ jobs:
NEW_ARCH_ENABLED=1
export RCT_USE_LOCAL_RN_DEP=/tmp/third-party/ReactNativeDependencies${{ matrix.flavor }}.xcframework.tar.gz
# Disable prebuilds for now, as they are causing issues with E2E tests for 0.82-stable branch
# export RCT_TESTONLY_RNCORE_TARBALL_PATH="/tmp/ReactCore/ReactCore${{ matrix.flavor }}.xcframework.tar.gz"
export RCT_TESTONLY_RNCORE_TARBALL_PATH="/tmp/ReactCore/ReactCore${{ matrix.flavor }}.xcframework.tar.gz"
HERMES_ENGINE_TARBALL_PATH=$HERMES_PATH RCT_NEW_ARCH_ENABLED=$NEW_ARCH_ENABLED bundle exec pod install
xcodebuild \
@@ -383,8 +379,7 @@ jobs:
runs-on: 8-core-ubuntu
needs: [set_release_type]
container:
# Version is pinned to v18.0 to unblock `run_fantom_tests` - see https://github.com/react-native-community/docker-android/pull/242#issuecomment-3280029122
image: reactnativecommunity/react-native-android:v18.0
image: reactnativecommunity/react-native-android:latest
env:
TERM: "dumb"
GRADLE_OPTS: "-Dorg.gradle.daemon=false"
@@ -599,7 +594,6 @@ jobs:
test_js:
runs-on: ubuntu-latest
if: github.repository == 'facebook/react-native'
strategy:
fail-fast: false
matrix:
@@ -614,7 +608,6 @@ jobs:
lint:
runs-on: ubuntu-latest
if: github.repository == 'facebook/react-native'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
@@ -27,7 +27,6 @@ on:
jobs:
validate-dotslash-artifacts:
runs-on: ubuntu-latest
if: github.repository == 'facebook/react-native'
steps:
- name: Checkout repository
uses: actions/checkout@v4
-56
View File
@@ -1,61 +1,5 @@
# Changelog
## v0.81.3
### Fixed
#### iOS specific
- Reverted "Use autolinking-generated react-native-config output in second step of cocoapods linking that generates artifacts and generated source" ([537e3ad930](https://github.com/facebook/react-native/commit/537e3ad93041c0cef959f0d20586fe97818900a6) by [@gabrieldonadel](https://github.com/gabrieldonadel))
## v0.81.2
### Added
#### Android specific
- Create a debugOptimized buildType for Android ([5e3edafec6](https://github.com/facebook/react-native/commit/5e3edafec6c69558521061dced7a6bcd046576b0) by [@cortinico](https://github.com/cortinico))
- Add `useNativeEqualsInNativeReadableArrayAndroid` and `useNativeTransformHelperAndroid` feature flag to the experimental channel. This should alleviate some of the perf issue users are seeing on Android + Reanimated + NewArch on 0.81([a346096da8](https://github.com/facebook/react-native/commit/a346096da81fccf5fbc82d83bfc128695e6ec3a5) by [@cortinico](https://github.com/cortinico))
### Fixed
#### iOS specific
- Fix Node scripts related to prebuilt tarball extraction for paths containing whitespaces ([366f2ad505](https://github.com/facebook/react-native/commit/366f2ad5057ffecc1f5b211f6aae29567ae6b7e5) by [@kitten](https://github.com/kitten))
- Use autolinking-generated react-native-config output in second step of cocoapods linking that generates artifacts and generated source ([a2eb29e5e7](https://github.com/facebook/react-native/commit/a2eb29e5e7aef8bbdf4c647c8467b5292b013b20) by [@kitten](https://github.com/kitten))
## v0.82.0-rc.1
### Added
#### Android specific
- **Hermes V1:** Added opt-in to use the new Hermes ([3e9990f860](https://github.com/facebook/react-native/commit/3e9990f860eb9380837ef431ca02def32c4261ad) by [@j-piasecki](https://github.com/j-piasecki))
#### iOS specific
- **Hermes V1:** Added opt-in to use the new Hermes ([e9cdc308b4](https://github.com/facebook/react-native/commit/e9cdc308b4c04753d85757e8877ac00c3c687b95) by [@j-piasecki](https://github.com/j-piasecki))
### Changed
- **Hermes V1:** Changed the source of hermesc binary to be an npm package ([2e0bd13a25](https://github.com/facebook/react-native/commit/2e0bd13a2533fe7ab64125a95b9215b806018c6e) by [@j-piasecki](https://github.com/j-piasecki))
### Deprecated
- **APIs:** Deprecate legacy javascript react native apis ([e7aeea26bd](https://github.com/facebook/react-native/commit/e7aeea26bde6e9cda0a3a0a55fc2a0421fb0c0e5) by [@RSNara](https://github.com/RSNara))
### Fixed
#### Android specific
- **Build From Source:** Fix build from source due to missing folder error on Gradle 9.0 ([9fbce3eff1](https://github.com/facebook/react-native/commit/9fbce3eff18060f16e796badc415ba733ede19af) by [@cortinico](https://github.com/cortinico))
#### iOS specific
- **RCTAlertController:** Simplify RCTAlertController, don't create additional UIWindow ([05c4321b19](https://github.com/facebook/react-native/commit/05c4321b194c3d0e146b6085bcaccc75acd3fd67) by [@okwasniewski](https://github.com/okwasniewski))
- **Prebuild:** Fix Node scripts related to prebuilt tarball extraction for paths containing whitespaces ([9731e8ebc5](https://github.com/facebook/react-native/commit/9731e8ebc5ea87526a91b9903172639e062cd920) by [@kitten](https://github.com/kitten))
- **Prebuild:** Use autolinking-generated react-native-config output in second step of cocoapods linking that generates artifacts and generated source ([f170db412b](https://github.com/facebook/react-native/commit/f170db412b3ab46fd0894d5d66431d9c230cd3a8) by [@kitten](https://github.com/kitten))
## v0.82.0-rc.0
### Breaking
+2 -5
View File
@@ -17,13 +17,10 @@
<img src="https://img.shields.io/npm/v/react-native?color=brightgreen&label=npm%20package" alt="Current npm package version." />
</a>
<a href="https://reactnative.dev/docs/contributing">
<img src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg" alt="PRs are welcome!" />
<img src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg" alt="PRs welcome!" />
</a>
<a href="https://twitter.com/intent/follow?screen_name=reactnative">
<img src="https://img.shields.io/twitter/follow/reactnative.svg?label=Follow%20@reactnative" alt="Follow @reactnative on X" />
</a>
<a href="https://bsky.app/profile/reactnative.dev">
<img src="https://img.shields.io/badge/Bluesky-0285FF?logo=bluesky&logoColor=fff" alt="Follow @reactnative.dev on Bluesky" />
<img src="https://img.shields.io/twitter/follow/reactnative.svg?label=Follow%20@reactnative" alt="Follow @reactnative" />
</a>
</p>
-1
View File
@@ -135,7 +135,6 @@ if (project.findProperty("react.internal.useHermesNightly")?.toString()?.toBoole
configurations.all {
resolutionStrategy.dependencySubstitution {
substitute(project(":packages:react-native:ReactAndroid:hermes-engine"))
// TODO: T237406039 update coordinates
.using(module("com.facebook.react:hermes-android:0.+"))
.because("Users opted to use hermes from nightly")
}
-41
View File
@@ -1,41 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
* @format
*/
declare module 'electron-store' {
declare export type Schema = any;
declare export type Options = {
+name?: string,
defaults?: Object,
schema?: any,
migrations?: any,
beforeEachMigration?: any,
clearInvalidConfig?: boolean,
serialize?: any,
deserialize?: any,
accessPropertiesByDotNotation?: boolean,
watch?: boolean,
encryptionKey?: string | Buffer | $ReadOnlyArray<number>,
...
};
declare class ElectronStore {
constructor(options?: Options): this;
get(key: string): any;
get(key: string, defaultValue: any): any;
set(key: string, value: any): void;
set(object: Object): void;
has(key: string): boolean;
delete(key: string): void;
clear(): void;
}
declare module.exports: Class<ElectronStore>;
}
+2 -2
View File
@@ -100,7 +100,7 @@
"jsonc-parser": "2.2.1",
"markdownlint-cli2": "^0.17.2",
"markdownlint-rule-relative-links": "^3.0.0",
"memfs": "^4.38.2",
"memfs": "^4.7.7",
"metro-babel-register": "^0.83.1",
"metro-transform-plugins": "^0.83.1",
"micromatch": "^4.0.4",
@@ -117,7 +117,7 @@
"temp-dir": "^2.0.0",
"tinybench": "^4.1.0",
"typescript": "5.8.3",
"ws": "^7.5.10"
"ws": "^6.2.3"
},
"resolutions": {
"eslint-plugin-react-hooks": "6.1.0-canary-12bc60f5-20250613",
+2 -2
View File
@@ -1,5 +1,5 @@
@generated SignedSource<<0b54f75686e4893a5444839bf621a317>>
Git revision: 5a792db1225adda206313e9bf751198a1ca7851a
@generated SignedSource<<b6a779e724ecce5e727ee674dc20f809>>
Git revision: e87564a24cf233c60aaebee8c418ec85724f7214
Built with --nohooks: false
Is local checkout: false
Remote URL: https://github.com/facebook/react-native-devtools-frontend
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -238,7 +238,7 @@ import"../../ui/components/icon_button/icon_button.js";import"../../ui/component
<td>${e.method}</td>
<td>${e.params?d`<code>${JSON.stringify(e.params)}</code>`:""}</td>
<td>
${e.result?d`<code>${JSON.stringify(e.result)}</code>`:e.error?d`<code>${JSON.stringify(e.error)}</code>`:"id"in e?"(pending)":""}
${e.result?d`<code>${JSON.stringify(e.result)}</code>`:e.error?d`<code>${JSON.stringify(e.error)}</code>`:"(pending)"}
</td>
<td data-value=${e.elapsedTime||0}>
${"id"in e?e.elapsedTime?U(A.sMs,{PH1:String(e.elapsedTime)}):"(pending)":""}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,71 +1,71 @@
#!/usr/bin/env dotslash
// @generated SignedSource<<9df662721aea6e3774a8677e2a6065e4>>
// @generated SignedSource<<e93d55b5e28943e44271f5d3738083e0>>
{
"name": "React Native DevTools",
"platforms": {
"linux-aarch64": {
"size": 116056584,
"size": 116060647,
"hash": "sha256",
"digest": "fac3912f10e3c373c874be6c4696f11e05cbaa754c116db6ea72189afae5efe6",
"digest": "4352f1c9848ca919101ec628bd08b87a72a828d1ab55fa43a02098329fa452fa",
"providers": [
{
"type": "http",
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQPdlYV_w4y_wxd5Rs8c_F-soLMbY1zwXJjD-JM4TkOtOELyxZGyreTb6dTehp_X6e3qVFZUT05ETRs0MbvqYr4mqdb6dkG9DqNQEVv3TBoHwl7TYSygtHJEs3gXTAtMLYEKW9xXODJlVF-9II7fdTdHU7x7Pyf6NR6S3nv7sKUVD-zKpxF50L2TwUQ"
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQM24LW0nPZRk0ypuIG9prz_72YjBJNcVlGSIEpO4zdlLXgw4dFNodH7MKg9eKNTnx7wrVDDBNACrnEPt_OfXOjZyZsV9Oaqu0-vNFRdlEyis4YqmpqGLtz3LvD-9R6fzcWxJI9zrhdPvOvlXP-3Syt1UNITaxXDVqIwAAYpCaAh0oLpupAFCc2yvYw"
}
],
"format": "tar.gz",
"path": "React Native DevTools-linux-arm64/React Native DevTools"
},
"linux-x86_64": {
"size": 115929093,
"size": 115930333,
"hash": "sha256",
"digest": "06bbaeb62ae2e0081d184eba42b9f15be0d0b3f4901142b08a8a1430ff83e722",
"digest": "11c7b07942928a6301b07fbf2bc77ce1229b2a52891f23541cdd9858b5250e64",
"providers": [
{
"type": "http",
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQPENbrxrg0RF_TiyxSY_YVYqC1UfRKj_bMfKb3qHUsIhBlya8n3FkbfJqTXTNdqL4riFRulXS5ecXZprtvk_9kao-zY59r3kiTRwobzF0jnjM507_9UOnEHWzG5ZJYzQyOtS3kQmT0HwZabVj9qw38OB9mk-MPVCZIPZay2PRnIThBzpKDoOOP9"
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQNDwm7HZRhtNxHqMr1FfSb0afHFGrn1OHxH0gOiggrLrht9QRUgJ3GG5jj7huhQzMRogE-LCMsnxh1ioOZks-YYX4KRt6Kj1-whdWsGFc7lBhPOpk1ssbYFGN1NNyuyFRmH-3nCY3lBC4AmbCUkbDTUeCi9DidCtJeyc73CZJEu7M62rIzxR2yV"
}
],
"format": "tar.gz",
"path": "React Native DevTools-linux-x64/React Native DevTools"
},
"macos-aarch64": {
"size": 110891603,
"size": 110891041,
"hash": "sha256",
"digest": "eeb9cc1399c0c38c429848dbf622f1b46e88d7d97788dcdc4c30a9fcce37705c",
"digest": "3cbe8b1b3d17e433347f1601435bb9a6cb758528a5c176a66fc52d9977223175",
"providers": [
{
"type": "http",
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQN9bd7nbXi-uF_MooJEiUL2jJVifMqgQxZ236aqbSdiJe5Uzjud5ANf0LDAl8GDVVRShd6x4B-gsZ-qRowH0qJikoGatQIkBgyzp4i8ors52etGOIIwdAxdNIng5Vtp441j2_N__btkJqlHcMMbbqvO8fg9oeYTlhMpOx3MLLWXIlG7ix5IFUDiYChf"
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQOmC2cqqSv4OrSJKJroYVg_NE8OE4O73AXqY7wXiYqiWQVkDt0Xnyw3ZeUpQT_Qb0-OoT5F8REKoFrB6eqwat8Ovkyina30peYTTwNUzmwnnGQEg7J0fOHNxLF4dkmU1FagXtsoWgex4dKgsK_VpcMsHj3Vp7diomkYvWBVTf_gPVEseYSN9oKq92qa"
}
],
"format": "tar.gz",
"path": "React Native DevTools.app/Contents/MacOS/React Native DevTools"
},
"macos-x86_64": {
"size": 117770388,
"size": 117766158,
"hash": "sha256",
"digest": "a65e446e526502b267cbe6800ae031e4e1b5b0aca21412152a66ffe1d3a29410",
"digest": "6fb79bc2ba3008401b4c9c128248657b95b98581ccde60f8fadb622163779775",
"providers": [
{
"type": "http",
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQN29ukKLZS48QcCU-gms06YFnG-fxxDfrWTup-Z6KoIAP-QEu3sFzrpqeZz4g-jFsh3o-IIoHJsdbu4a2U7ROjPfWGguGJrPK8fdc3iV67Qw1_VAPU13dm0dI1DbSY50ah05wh43jdBG3LGCAYYJ-W8_mZMC3HqM2v-8KVd-DoPT4hOh1s9CCFgEQ"
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQMMtGn-YGdfLfTVWC8zbQkQx65Asq6iArKt1t__cjZ8UY_s6-sX5XBHr8k1SaexAO21dFZENQVZ1jW_wn_gJ9ENvosQDG1KfWMViKsHli0xRzZ1HVsgPIj_KVXe907QZwwtJf2XhgH0HT8dfH-AQdDcd0_TB5DFUwOsHzhH0nBrHet7YFkbJtPTaA"
}
],
"format": "tar.gz",
"path": "React Native DevTools.app/Contents/MacOS/React Native DevTools"
},
"windows-x86_64": {
"size": 125526370,
"size": 125527537,
"hash": "sha256",
"digest": "26b190c0f85249dee91999e020b8fe7ffd5c007458a2103ed3822558861dbe87",
"digest": "579a5b0944c51c3b1b541ad5af66c1ffedf93cae2a891ecdf88cb7219fd9b096",
"providers": [
{
"type": "http",
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQO0mdIJx1eYiSDJNiAZ2soaeECILayWnvOeiey-fpS4ydDTreAMfwL4QZ5GZo4-AsGwOXCSdF3hBMM2ufnvw6BDFg5UEiTc4DALJu7o6YBBG4wlVZbI-2kkaXd7u8RhBQPjmhsdcX3sDmCGmSr3WK9EkTRKStE2lb6ilOn-969h4dYWekwUUCSX"
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQOQ3E8lBXqdVHbDPyVb5AOQMrDWjFrFV8fnLLBsygQvLWdpu6ixyG9PgWdwpi5jM-XcDdCHkhBdhaq-5dwT_tgRWKCAMsEBoAIUk0Xg77mGyHG2VF7bNfQ2qFBMuObrsTmrKy1nJ-UFDDm29pJD4GkFQW5NesiBwndJj8t3B8Ur8cczh_XR8rF5"
}
],
"format": "tar.gz",
-2
View File
@@ -1,6 +1,5 @@
{
"name": "@react-native/debugger-shell",
"productName": "React Native DevTools",
"version": "0.82.0-main",
"description": "Experimental debugger shell for React Native for use with @react-native/debugger-frontend",
"keywords": [
@@ -35,7 +34,6 @@
},
"devDependencies": {
"electron": "37.2.6",
"electron-store": "^8.2.0",
"semver": "^7.1.3"
},
"files": [
@@ -9,12 +9,10 @@
*/
// $FlowFixMe[unclear-type] We have no Flow types for the Electron API.
const {BrowserWindow, Menu, app, shell, ipcMain} = require('electron') as any;
const Store = require('electron-store');
const {BrowserWindow, app, shell, ipcMain} = require('electron') as any;
const path = require('path');
const util = require('util');
const appSettings = new Store();
const windowMetadata = new WeakMap<
typeof BrowserWindow,
$ReadOnly<{
@@ -55,11 +53,10 @@ function handleLaunchArgs(argv: string[]) {
}, 1000);
}
} else {
// Create the browser window.
frontendWindow = new BrowserWindow({
...(getSavedWindowPosition(windowKey) ?? {
width: 1200,
height: 600,
}),
width: 1200,
height: 600,
webPreferences: {
partition: 'persist:react-native-devtools',
preload: require.resolve('./preload.js'),
@@ -69,8 +66,6 @@ function handleLaunchArgs(argv: string[]) {
});
// Auto-hide the Windows/Linux menu bar
frontendWindow.setMenuBarVisibility(false);
// Observe and update saved window position
setupWindowResizeListeners(frontendWindow, windowKey);
}
// Open links in the default browser instead of in new Electron windows.
@@ -96,68 +91,8 @@ function handleLaunchArgs(argv: string[]) {
frontendWindow.focus();
}
function configureAppMenu() {
const template = [
...(process.platform === 'darwin' ? [{role: 'appMenu'}] : []),
{role: 'fileMenu'},
{role: 'editMenu'},
{role: 'viewMenu'},
{role: 'windowMenu'},
{
role: 'help',
submenu: [
{
label: 'React Native Website',
click: () => shell.openExternal('https://reactnative.dev'),
},
{
label: 'Release Notes',
click: () =>
shell.openExternal(
'https://github.com/facebook/react-native/releases',
),
},
],
},
];
const menu = Menu.buildFromTemplate(template);
Menu.setApplicationMenu(menu);
}
function getSavedWindowPosition(
windowKey: string,
): ?{width: number, height: number, x?: number, y?: number} {
return appSettings.get('windowArrangements', {})[windowKey];
}
function saveWindowPosition(
windowKey: string,
position: {x: number, y: number, width: number, height: number},
) {
const windowArrangements = appSettings.get('windowArrangements', {});
windowArrangements[windowKey] = position;
appSettings.set('windowArrangements', windowArrangements);
}
function setupWindowResizeListeners(
browserWindow: typeof BrowserWindow,
windowKey: string,
) {
const savePosition = () => {
if (!browserWindow.isDestroyed()) {
const [x, y] = browserWindow.getPosition();
const [width, height] = browserWindow.getSize();
saveWindowPosition(windowKey, {x, y, width, height});
}
};
browserWindow.on('moved', savePosition);
browserWindow.on('resized', savePosition);
browserWindow.on('closed', savePosition);
}
app.whenReady().then(() => {
handleLaunchArgs(process.argv.slice(app.isPackaged ? 1 : 2));
configureAppMenu();
app.on(
'second-instance',
@@ -16,8 +16,9 @@ const util = require('util');
// $FlowFixMe[unclear-type] We have no Flow types for the Electron API.
const {app} = require('electron') as any;
// Set the application name and version
app.setName(pkg.productName ?? pkg.name);
// Set the app name and version early - these are used in --version as well as
// in the User-Agent string.
app.setName(pkg.name);
app.setVersion(pkg.version + '-' + buildInfo.revision);
// Handle global command line arguments which don't require a window
@@ -30,7 +31,7 @@ const {
strict: false,
});
if (version) {
console.log(`${pkg.name} v${app.getVersion()}`);
console.log(`${app.getName()} v${app.getVersion()}`);
// Not app.quit() - we want to exit immediately without initialising the graphical subsystem.
app.exit(0);
}
+1 -1
View File
@@ -33,7 +33,7 @@
"nullthrows": "^1.1.1",
"open": "^7.0.3",
"serve-static": "^1.16.2",
"ws": "^7.5.10"
"ws": "^6.2.3"
},
"engines": {
"node": ">= 20.19.4"
@@ -55,8 +55,8 @@ class ReactPlugin : Plugin<Project> {
project,
)
if (project.rootProject.isHermesV1Enabled) {
rootExtension.hermesV1Enabled.set(true)
if (project.rootProject.isHermesV1Enabled != rootExtension.hermesV1Enabled.get()) {
rootExtension.hermesV1Enabled.set(project.rootProject.isHermesV1Enabled)
}
// App Only Configuration
@@ -71,11 +71,11 @@ class ReactPlugin : Plugin<Project> {
project.afterEvaluate {
val reactNativeDir = extension.reactNativeDir.get().asFile
val propertiesFile = File(reactNativeDir, "ReactAndroid/gradle.properties")
val hermesVersionPropertiesFile =
File(reactNativeDir, "sdks/hermes-engine/version.properties")
val versionAndGroupStrings =
readVersionAndGroupStrings(propertiesFile, hermesVersionPropertiesFile)
val hermesV1Enabled = rootExtension.hermesV1Enabled.get()
val versionAndGroupStrings = readVersionAndGroupStrings(propertiesFile)
val hermesV1Enabled =
if (project.rootProject.hasProperty("hermesV1Enabled"))
project.rootProject.findProperty("hermesV1Enabled") == "true"
else false
configureDependencies(project, versionAndGroupStrings, hermesV1Enabled)
configureRepositories(project)
}
@@ -14,7 +14,6 @@ import com.facebook.react.utils.KotlinStdlibCompatUtils.capitalizeCompat
import com.facebook.react.utils.NdkConfiguratorUtils.configureJsEnginePackagingOptions
import com.facebook.react.utils.NdkConfiguratorUtils.configureNewArchPackagingOptions
import com.facebook.react.utils.ProjectUtils.isHermesEnabled
import com.facebook.react.utils.ProjectUtils.isHermesV1Enabled
import com.facebook.react.utils.ProjectUtils.useThirdPartyJSC
import com.facebook.react.utils.detectedCliFile
import com.facebook.react.utils.detectedEntryFile
@@ -49,7 +48,6 @@ internal fun Project.configureReactTasks(variant: Variant, config: ReactExtensio
} else {
isHermesEnabledInProject
}
val isHermesV1Enabled = project.isHermesV1Enabled || rootProject.isHermesV1Enabled
val isDebuggableVariant =
config.debuggableVariants.get().any { it.equals(variant.name, ignoreCase = true) }
val useThirdPartyJSC = project.useThirdPartyJSC
@@ -80,7 +78,6 @@ internal fun Project.configureReactTasks(variant: Variant, config: ReactExtensio
task.jsBundleDir.set(jsBundleDir)
task.resourcesDir.set(resourcesDir)
task.hermesEnabled.set(isHermesEnabledInThisVariant)
task.hermesV1Enabled.set(isHermesV1Enabled)
task.minifyEnabled.set(!isHermesEnabledInThisVariant)
task.devEnabled.set(false)
task.jsIntermediateSourceMapsDir.set(jsIntermediateSourceMapsDir)
@@ -63,8 +63,6 @@ abstract class BundleHermesCTask : DefaultTask() {
@get:Input abstract val hermesEnabled: Property<Boolean>
@get:Input abstract val hermesV1Enabled: Property<Boolean>
@get:Input abstract val devEnabled: Property<Boolean>
@get:Input abstract val extraPackagerArgs: ListProperty<String>
@@ -96,8 +94,12 @@ abstract class BundleHermesCTask : DefaultTask() {
runCommand(bundleCommand)
if (hermesEnabled.get()) {
val hermesV1Enabled =
if (project.rootProject.hasProperty("hermesV1Enabled"))
project.rootProject.findProperty("hermesV1Enabled") == "true"
else false
val detectedHermesCommand =
detectOSAwareHermesCommand(root.get().asFile, hermesCommand.get(), hermesV1Enabled.get())
detectOSAwareHermesCommand(root.get().asFile, hermesCommand.get(), hermesV1Enabled)
val bytecodeFile = File("${bundleFile}.hbc")
val outputSourceMap = resolveOutputSourceMap(bundleAssetFilename)
val compilerSourceMap = resolveCompilerSourceMap(bundleAssetFilename)
@@ -13,7 +13,7 @@ import com.facebook.react.utils.PropertyUtils.EXCLUSIVE_ENTEPRISE_REPOSITORY
import com.facebook.react.utils.PropertyUtils.INCLUDE_JITPACK_REPOSITORY
import com.facebook.react.utils.PropertyUtils.INCLUDE_JITPACK_REPOSITORY_DEFAULT
import com.facebook.react.utils.PropertyUtils.INTERNAL_HERMES_PUBLISHING_GROUP
import com.facebook.react.utils.PropertyUtils.INTERNAL_HERMES_V1_VERSION_NAME
import com.facebook.react.utils.PropertyUtils.INTERNAL_HERMES_VERSION_NAME
import com.facebook.react.utils.PropertyUtils.INTERNAL_REACT_NATIVE_MAVEN_LOCAL_REPO
import com.facebook.react.utils.PropertyUtils.INTERNAL_REACT_PUBLISHING_GROUP
import com.facebook.react.utils.PropertyUtils.INTERNAL_USE_HERMES_NIGHTLY
@@ -31,7 +31,6 @@ internal object DependencyUtils {
internal data class Coordinates(
val versionString: String,
val hermesVersionString: String,
val hermesV1VersionString: String,
val reactGroupString: String = DEFAULT_INTERNAL_REACT_PUBLISHING_GROUP,
val hermesGroupString: String = DEFAULT_INTERNAL_HERMES_PUBLISHING_GROUP,
)
@@ -114,12 +113,7 @@ internal object DependencyUtils {
coordinates: Coordinates,
hermesV1Enabled: Boolean = false,
) {
if (
coordinates.versionString.isBlank() ||
(!hermesV1Enabled && coordinates.hermesVersionString.isBlank()) ||
(hermesV1Enabled && coordinates.hermesV1VersionString.isBlank())
)
return
if (coordinates.versionString.isBlank() || coordinates.hermesVersionString.isBlank()) return
project.rootProject.allprojects { eachProject ->
eachProject.configurations.all { configuration ->
// Here we set a dependencySubstitution for both react-native and hermes-engine as those
@@ -139,11 +133,7 @@ internal object DependencyUtils {
// Contributors only: The hermes-engine version is forced only if the user has
// not opted into using nightlies for local development.
configuration.resolutionStrategy.force(
// TODO: T237406039 update coordinates
if (hermesV1Enabled)
"${coordinates.hermesGroupString}:hermes-android:${coordinates.hermesV1VersionString}"
else
"${coordinates.reactGroupString}:hermes-android:${coordinates.hermesVersionString}"
"${coordinates.reactGroupString}:hermes-android:${coordinates.versionString}"
)
}
}
@@ -156,11 +146,10 @@ internal object DependencyUtils {
): List<Triple<String, String, String>> {
// TODO: T231755027 update coordinates and versioning
val dependencySubstitution = mutableListOf<Triple<String, String, String>>()
// TODO: T237406039 update coordinates
val hermesVersionString =
if (hermesV1Enabled)
"${coordinates.hermesGroupString}:hermes-android:${coordinates.hermesV1VersionString}"
else "${coordinates.reactGroupString}:hermes-android:${coordinates.hermesVersionString}"
"${coordinates.hermesGroupString}:hermes-android:${coordinates.versionString}"
else "${coordinates.reactGroupString}:hermes-android:${coordinates.versionString}"
dependencySubstitution.add(
Triple(
"com.facebook.react:react-native",
@@ -183,7 +172,6 @@ internal object DependencyUtils {
"The react-android dependency was modified to use the correct Maven group.",
)
)
// TODO: T237406039 update coordinates
dependencySubstitution.add(
Triple(
"com.facebook.react:hermes-android",
@@ -195,10 +183,14 @@ internal object DependencyUtils {
return dependencySubstitution
}
fun readVersionAndGroupStrings(propertiesFile: File, hermesVersionFile: File): Coordinates {
fun readVersionAndGroupStrings(propertiesFile: File): Coordinates {
val reactAndroidProperties = Properties()
propertiesFile.inputStream().use { reactAndroidProperties.load(it) }
val versionStringFromFile = (reactAndroidProperties[INTERNAL_VERSION_NAME] as? String).orEmpty()
// TODO: T231755027 update HERMES_VERSION_NAME in gradle.properties to point to the correct
// hermes version
val hermesVersionStringFromFile =
(reactAndroidProperties[INTERNAL_HERMES_VERSION_NAME] as? String).orEmpty()
// If on a nightly, we need to fetch the -SNAPSHOT artifact from Sonatype.
val versionString =
if (versionStringFromFile.startsWith("0.0.0") || "-nightly-" in versionStringFromFile) {
@@ -213,18 +205,9 @@ internal object DependencyUtils {
val hermesGroupString =
reactAndroidProperties[INTERNAL_HERMES_PUBLISHING_GROUP] as? String
?: DEFAULT_INTERNAL_HERMES_PUBLISHING_GROUP
// TODO: T237406039 read both versions from the same file
val hermesVersionProperties = Properties()
hermesVersionFile.inputStream().use { hermesVersionProperties.load(it) }
val hermesVersion = versionString
val hermesV1Version =
(hermesVersionProperties[INTERNAL_HERMES_V1_VERSION_NAME] as? String).orEmpty()
return Coordinates(
versionString,
hermesVersion,
hermesV1Version,
hermesVersionStringFromFile,
reactGroupString,
hermesGroupString,
)
@@ -153,7 +153,6 @@ internal fun detectOSAwareHermesCommand(
// 3. If Hermes V1 is enabled, use hermes-compiler from npm, otherwise, if the
// react-native contains a pre-built hermesc, use it.
// TODO: T237406039 use hermes-compiler from npm for both
val hermesCPath = if (hermesV1Enabled) HERMES_COMPILER_NPM_DIR else HERMESC_IN_REACT_NATIVE_DIR
val prebuiltHermesPath =
hermesCPath
@@ -23,7 +23,6 @@ import com.facebook.react.utils.PropertyUtils.SCOPED_USE_THIRD_PARTY_JSC
import com.facebook.react.utils.PropertyUtils.USE_THIRD_PARTY_JSC
import org.gradle.api.Project
import org.gradle.api.file.DirectoryProperty
import org.jetbrains.kotlin.gradle.plugin.extraProperties
internal object ProjectUtils {
@@ -76,11 +75,7 @@ internal object ProjectUtils {
(project.hasProperty(HERMES_V1_ENABLED) &&
project.property(HERMES_V1_ENABLED).toString().toBoolean()) ||
(project.hasProperty(SCOPED_HERMES_V1_ENABLED) &&
project.property(SCOPED_HERMES_V1_ENABLED).toString().toBoolean()) ||
(project.extraProperties.has(HERMES_V1_ENABLED) &&
project.extraProperties.get(HERMES_V1_ENABLED).toString().toBoolean()) ||
(project.extraProperties.has(SCOPED_HERMES_V1_ENABLED) &&
project.extraProperties.get(SCOPED_HERMES_V1_ENABLED).toString().toBoolean())
project.property(SCOPED_HERMES_V1_ENABLED).toString().toBoolean())
internal fun Project.needsCodegenFromPackageJson(rootProperty: DirectoryProperty): Boolean {
val parsedPackageJson = readPackageJsonFile(this, rootProperty)
@@ -79,10 +79,6 @@ object PropertyUtils {
/** Internal property used to control the version name of React Native */
const val INTERNAL_VERSION_NAME = "VERSION_NAME"
/**
* Internal property, shared with iOS, used to control the version name of Hermes Engine. This is
* stored in sdks/hermes-engine/version.properties
*/
const val INTERNAL_HERMES_V1_VERSION_NAME = "HERMES_V1_VERSION_NAME"
/** Internal property used to control the version name of Hermes Engine */
const val INTERNAL_HERMES_VERSION_NAME = "HERMES_VERSION_NAME"
}
@@ -33,9 +33,9 @@ class GeneratePackageListTaskTest {
val inputFile = tempFolder.newFile("config.json")
val task =
createTestTask<GeneratePackageListTask> { testTask ->
testTask.generatedOutputDirectory.set(outputFolder)
testTask.autolinkInputFile.set(inputFile)
createTestTask<GeneratePackageListTask> {
it.generatedOutputDirectory.set(outputFolder)
it.autolinkInputFile.set(inputFile)
}
assertThat(task.inputs.files.singleFile).isEqualTo(inputFile)
@@ -82,11 +82,11 @@ class PrepareGflagsTaskTest {
val gflagsThirdPartyPath = tempFolder.newFolder("gflagspath/jni")
val output = tempFolder.newFolder("output")
val task =
createTestTask<PrepareGflagsTask> { taskConfig ->
taskConfig.gflagsPath.setFrom(gflagspath)
taskConfig.gflagsThirdPartyPath.set(gflagsThirdPartyPath)
taskConfig.gflagsVersion.set("1.0.0")
taskConfig.outputDir.set(output)
createTestTask<PrepareGflagsTask> {
it.gflagsPath.setFrom(gflagspath)
it.gflagsThirdPartyPath.set(gflagsThirdPartyPath)
it.gflagsVersion.set("1.0.0")
it.outputDir.set(output)
}
File(gflagspath, "gflags-1.0.0/src/gflags_declare.h.in").apply {
parentFile.mkdirs()
@@ -98,11 +98,11 @@ class PrepareGlogTaskTest {
val glogThirdPartyJniPath = tempFolder.newFolder("glogpath/jni")
val output = tempFolder.newFolder("output")
val task =
createTestTask<PrepareGlogTask> { task ->
task.glogPath.setFrom(glogpath)
task.glogThirdPartyJniPath.set(glogThirdPartyJniPath)
task.glogVersion.set("1.0.0")
task.outputDir.set(output)
createTestTask<PrepareGlogTask> {
it.glogPath.setFrom(glogpath)
it.glogThirdPartyJniPath.set(glogThirdPartyJniPath)
it.glogVersion.set("1.0.0")
it.outputDir.set(output)
}
File(glogpath, "glog-1.0.0/src/glog.h.in").apply {
parentFile.mkdirs()
@@ -271,69 +271,54 @@ class DependencyUtilsTest {
.isEqualTo(2)
}
// TODO: T236767053
@Test
fun configureDependencies_withEmptyVersion_doesNothing() {
val project = createProject()
configureDependencies(project, DependencyUtils.Coordinates("", "", ""))
configureDependencies(project, DependencyUtils.Coordinates("", ""))
assertThat(project.configurations.first().resolutionStrategy.forcedModules.isEmpty()).isTrue()
}
@Test
fun configureDependencies_withVersionString_appliesResolutionStrategy_withClassicHermes() {
fun configureDependencies_withVersionString_appliesResolutionStrategy() {
val project = createProject()
configureDependencies(project, DependencyUtils.Coordinates("1.2.3", "4.5.6", "7.8.9"))
configureDependencies(project, DependencyUtils.Coordinates("1.2.3", "1.2.3"))
val forcedModules = project.configurations.first().resolutionStrategy.forcedModules
assertThat(forcedModules.any { it.toString() == "com.facebook.react:react-android:1.2.3" })
.isTrue()
assertThat(forcedModules.any { it.toString() == "com.facebook.react:hermes-android:4.5.6" })
assertThat(forcedModules.any { it.toString() == "com.facebook.react:hermes-android:1.2.3" })
.isTrue()
}
@Test
fun configureDependencies_withVersionString_appliesResolutionStrategy_withHermesV1() {
val project = createProject()
configureDependencies(
project,
DependencyUtils.Coordinates("1.2.3", "4.5.6", "7.8.9"),
hermesV1Enabled = true,
)
val forcedModules = project.configurations.first().resolutionStrategy.forcedModules
assertThat(forcedModules.any { it.toString() == "com.facebook.react:react-android:1.2.3" })
.isTrue()
assertThat(forcedModules.any { it.toString() == "com.facebook.hermes:hermes-android:7.8.9" })
.isTrue()
}
@Test
fun configureDependencies_withVersionString_appliesOnAllProjects_withClassicHermes() {
fun configureDependencies_withVersionString_appliesOnAllProjects() {
val rootProject = ProjectBuilder.builder().build()
val appProject = ProjectBuilder.builder().withName("app").withParent(rootProject).build()
val libProject = ProjectBuilder.builder().withName("lib").withParent(rootProject).build()
appProject.plugins.apply("com.android.application")
libProject.plugins.apply("com.android.library")
configureDependencies(appProject, DependencyUtils.Coordinates("1.2.3", "4.5.6", "7.8.9"))
configureDependencies(appProject, DependencyUtils.Coordinates("1.2.3", "1.2.3"))
val appForcedModules = appProject.configurations.first().resolutionStrategy.forcedModules
val libForcedModules = libProject.configurations.first().resolutionStrategy.forcedModules
assertThat(appForcedModules.any { it.toString() == "com.facebook.react:react-android:1.2.3" })
.isTrue()
assertThat(appForcedModules.any { it.toString() == "com.facebook.react:hermes-android:4.5.6" })
assertThat(appForcedModules.any { it.toString() == "com.facebook.react:hermes-android:1.2.3" })
.isTrue()
assertThat(libForcedModules.any { it.toString() == "com.facebook.react:react-android:1.2.3" })
.isTrue()
assertThat(libForcedModules.any { it.toString() == "com.facebook.react:hermes-android:4.5.6" })
assertThat(libForcedModules.any { it.toString() == "com.facebook.react:hermes-android:1.2.3" })
.isTrue()
}
@Test
fun configureDependencies_withVersionString_appliesOnAllProjects_withHermesV1() {
fun configureDependencies_withVersionStringAndGroupString_appliesOnAllProjects() {
val rootProject = ProjectBuilder.builder().build()
val appProject = ProjectBuilder.builder().withName("app").withParent(rootProject).build()
val libProject = ProjectBuilder.builder().withName("lib").withParent(rootProject).build()
@@ -342,93 +327,25 @@ class DependencyUtilsTest {
configureDependencies(
appProject,
DependencyUtils.Coordinates("1.2.3", "4.5.6", "7.8.9"),
hermesV1Enabled = true,
)
val appForcedModules = appProject.configurations.first().resolutionStrategy.forcedModules
val libForcedModules = libProject.configurations.first().resolutionStrategy.forcedModules
assertThat(appForcedModules.any { it.toString() == "com.facebook.react:react-android:1.2.3" })
.isTrue()
assertThat(appForcedModules.any { it.toString() == "com.facebook.hermes:hermes-android:7.8.9" })
.isTrue()
assertThat(libForcedModules.any { it.toString() == "com.facebook.react:react-android:1.2.3" })
.isTrue()
assertThat(libForcedModules.any { it.toString() == "com.facebook.hermes:hermes-android:7.8.9" })
.isTrue()
}
@Test
fun configureDependencies_withVersionStringAndGroupString_appliesOnAllProjects_withClassicHermes() {
val rootProject = ProjectBuilder.builder().build()
val appProject = ProjectBuilder.builder().withName("app").withParent(rootProject).build()
val libProject = ProjectBuilder.builder().withName("lib").withParent(rootProject).build()
appProject.plugins.apply("com.android.application")
libProject.plugins.apply("com.android.library")
configureDependencies(
appProject,
DependencyUtils.Coordinates(
"1.2.3",
"4.5.6",
"7.8.9",
"io.github.test",
"io.github.test.hermes",
),
DependencyUtils.Coordinates("1.2.3", "1.2.3", "io.github.test"),
)
val appForcedModules = appProject.configurations.first().resolutionStrategy.forcedModules
val libForcedModules = libProject.configurations.first().resolutionStrategy.forcedModules
assertThat(appForcedModules.any { it.toString() == "io.github.test:react-android:1.2.3" })
.isTrue()
assertThat(appForcedModules.any { it.toString() == "io.github.test:hermes-android:4.5.6" })
assertThat(appForcedModules.any { it.toString() == "io.github.test:hermes-android:1.2.3" })
.isTrue()
assertThat(libForcedModules.any { it.toString() == "io.github.test:react-android:1.2.3" })
.isTrue()
assertThat(libForcedModules.any { it.toString() == "io.github.test:hermes-android:4.5.6" })
assertThat(libForcedModules.any { it.toString() == "io.github.test:hermes-android:1.2.3" })
.isTrue()
}
@Test
fun configureDependencies_withVersionStringAndGroupString_appliesOnAllProjects_withHermesV1() {
val rootProject = ProjectBuilder.builder().build()
val appProject = ProjectBuilder.builder().withName("app").withParent(rootProject).build()
val libProject = ProjectBuilder.builder().withName("lib").withParent(rootProject).build()
appProject.plugins.apply("com.android.application")
libProject.plugins.apply("com.android.library")
configureDependencies(
appProject,
DependencyUtils.Coordinates(
"1.2.3",
"4.5.6",
"7.8.9",
"io.github.test",
"io.github.test.hermes",
),
hermesV1Enabled = true,
)
val appForcedModules = appProject.configurations.first().resolutionStrategy.forcedModules
val libForcedModules = libProject.configurations.first().resolutionStrategy.forcedModules
assertThat(appForcedModules.any { it.toString() == "io.github.test:react-android:1.2.3" })
.isTrue()
assertThat(
appForcedModules.any { it.toString() == "io.github.test.hermes:hermes-android:7.8.9" }
)
.isTrue()
assertThat(libForcedModules.any { it.toString() == "io.github.test:react-android:1.2.3" })
.isTrue()
assertThat(
libForcedModules.any { it.toString() == "io.github.test.hermes:hermes-android:7.8.9" }
)
.isTrue()
}
@Test
fun getDependencySubstitutions_withDefaultGroup_substitutesCorrectly_withClassicHermes() {
fun getDependencySubstitutions_withDefaultGroup_substitutesCorrectly() {
val dependencySubstitutions =
getDependencySubstitutions(DependencyUtils.Coordinates("0.42.0", "0.42.0", "0.43.0"))
getDependencySubstitutions(DependencyUtils.Coordinates("0.42.0", "0.42.0"))
assertThat("com.facebook.react:react-native").isEqualTo(dependencySubstitutions[0].first)
assertThat("com.facebook.react:react-android:0.42.0")
@@ -447,40 +364,10 @@ class DependencyUtilsTest {
}
@Test
fun getDependencySubstitutions_withDefaultGroup_substitutesCorrectly_withHermesV1() {
fun getDependencySubstitutions_withCustomGroup_substitutesCorrectly() {
val dependencySubstitutions =
getDependencySubstitutions(
DependencyUtils.Coordinates("0.42.0", "0.42.0", "0.43.0"),
hermesV1Enabled = true,
)
assertThat("com.facebook.react:react-native").isEqualTo(dependencySubstitutions[0].first)
assertThat("com.facebook.react:react-android:0.42.0")
.isEqualTo(dependencySubstitutions[0].second)
assertThat(
"The react-native artifact was deprecated in favor of react-android due to https://github.com/facebook/react-native/issues/35210."
)
.isEqualTo(dependencySubstitutions[0].third)
assertThat("com.facebook.react:hermes-engine").isEqualTo(dependencySubstitutions[1].first)
assertThat("com.facebook.hermes:hermes-android:0.43.0")
.isEqualTo(dependencySubstitutions[1].second)
assertThat(
"The hermes-engine artifact was deprecated in favor of hermes-android due to https://github.com/facebook/react-native/issues/35210."
)
.isEqualTo(dependencySubstitutions[1].third)
}
@Test
fun getDependencySubstitutions_withCustomGroup_substitutesCorrectly_withClassicHermes() {
val dependencySubstitutions =
getDependencySubstitutions(
DependencyUtils.Coordinates(
"0.42.0",
"0.42.0",
"0.43.0",
"io.github.test",
"io.github.test.hermes",
)
DependencyUtils.Coordinates("0.42.0", "0.42.0", "io.github.test")
)
assertThat("com.facebook.react:react-native").isEqualTo(dependencySubstitutions[0].first)
@@ -505,44 +392,6 @@ class DependencyUtilsTest {
.isEqualTo(dependencySubstitutions[3].third)
}
@Test
fun getDependencySubstitutions_withCustomGroup_substitutesCorrectly_withHermesV1() {
val dependencySubstitutions =
getDependencySubstitutions(
DependencyUtils.Coordinates(
"0.42.0",
"0.42.0",
"0.43.0",
"io.github.test",
"io.github.test.hermes",
),
hermesV1Enabled = true,
)
assertThat("com.facebook.react:react-native").isEqualTo(dependencySubstitutions[0].first)
assertThat("io.github.test:react-android:0.42.0").isEqualTo(dependencySubstitutions[0].second)
assertThat(
"The react-native artifact was deprecated in favor of react-android due to https://github.com/facebook/react-native/issues/35210."
)
.isEqualTo(dependencySubstitutions[0].third)
assertThat("com.facebook.react:hermes-engine").isEqualTo(dependencySubstitutions[1].first)
assertThat("io.github.test.hermes:hermes-android:0.43.0")
.isEqualTo(dependencySubstitutions[1].second)
assertThat(
"The hermes-engine artifact was deprecated in favor of hermes-android due to https://github.com/facebook/react-native/issues/35210."
)
.isEqualTo(dependencySubstitutions[1].third)
assertThat("com.facebook.react:react-android").isEqualTo(dependencySubstitutions[2].first)
assertThat("io.github.test:react-android:0.42.0").isEqualTo(dependencySubstitutions[2].second)
assertThat("The react-android dependency was modified to use the correct Maven group.")
.isEqualTo(dependencySubstitutions[2].third)
assertThat("com.facebook.react:hermes-android").isEqualTo(dependencySubstitutions[3].first)
assertThat("io.github.test.hermes:hermes-android:0.43.0")
.isEqualTo(dependencySubstitutions[3].second)
assertThat("The hermes-android dependency was modified to use the correct Maven group.")
.isEqualTo(dependencySubstitutions[3].third)
}
@Test
fun readVersionString_withCorrectVersionString_returnsIt() {
val propertiesFile =
@@ -556,25 +405,9 @@ class DependencyUtilsTest {
)
}
val hermesVersionFile =
tempFolder.newFile("version.properties").apply {
writeText(
"""
HERMES_V1_VERSION_NAME=1000.0.0
ANOTHER_PROPERTY=true
"""
.trimIndent()
)
}
val strings = readVersionAndGroupStrings(propertiesFile, hermesVersionFile)
val versionString = strings.versionString
val hermesVersionString = strings.hermesVersionString
val hermesV1VersionString = strings.hermesV1VersionString
val versionString = readVersionAndGroupStrings(propertiesFile).versionString
assertThat(versionString).isEqualTo("1000.0.0")
assertThat(hermesVersionString).isEqualTo("1000.0.0")
assertThat(hermesV1VersionString).isEqualTo("1000.0.0")
}
@Test
@@ -584,33 +417,15 @@ class DependencyUtilsTest {
writeText(
"""
VERSION_NAME=0.0.0-20221101-2019-cfe811ab1
HERMES_VERSION_NAME=0.12.0-commitly-20221101-2019-cfe811ab1
HERMES_V1_VERSION_NAME=250829098.0.0-stable
ANOTHER_PROPERTY=true
"""
.trimIndent()
)
}
val hermesVersionFile =
tempFolder.newFile("version.properties").apply {
writeText(
"""
HERMES_V1_VERSION_NAME=250829098.0.0-stable
ANOTHER_PROPERTY=true
"""
.trimIndent()
)
}
val strings = readVersionAndGroupStrings(propertiesFile, hermesVersionFile)
val versionString = strings.versionString
val hermesVersionString = strings.hermesVersionString
val hermesV1VersionString = strings.hermesV1VersionString
val versionString = readVersionAndGroupStrings(propertiesFile).versionString
assertThat(versionString).isEqualTo("0.0.0-20221101-2019-cfe811ab1-SNAPSHOT")
assertThat(hermesVersionString).isEqualTo("0.0.0-20221101-2019-cfe811ab1-SNAPSHOT")
assertThat(hermesV1VersionString).isEqualTo("250829098.0.0-stable")
}
@Test
@@ -625,23 +440,8 @@ class DependencyUtilsTest {
)
}
val hermesVersionFile =
tempFolder.newFile("version.properties").apply {
writeText(
"""
ANOTHER_PROPERTY=true
"""
.trimIndent()
)
}
val strings = readVersionAndGroupStrings(propertiesFile, hermesVersionFile)
val versionString = strings.versionString
val hermesVersionString = strings.hermesVersionString
val hermesV1VersionString = strings.hermesV1VersionString
val versionString = readVersionAndGroupStrings(propertiesFile).versionString
assertThat(versionString).isEqualTo("")
assertThat(hermesVersionString).isEqualTo("")
assertThat(hermesV1VersionString).isEqualTo("")
}
@Test
@@ -657,24 +457,8 @@ class DependencyUtilsTest {
)
}
val hermesVersionFile =
tempFolder.newFile("version.properties").apply {
writeText(
"""
HERMES_V1_VERSION_NAME=
ANOTHER_PROPERTY=true
"""
.trimIndent()
)
}
val strings = readVersionAndGroupStrings(propertiesFile, hermesVersionFile)
val versionString = strings.versionString
val hermesVersionString = strings.hermesVersionString
val hermesV1VersionString = strings.hermesV1VersionString
val versionString = readVersionAndGroupStrings(propertiesFile).versionString
assertThat(versionString).isEqualTo("")
assertThat(hermesVersionString).isEqualTo("")
assertThat(hermesV1VersionString).isEqualTo("")
}
@Test
@@ -684,30 +468,15 @@ class DependencyUtilsTest {
writeText(
"""
react.internal.publishingGroup=io.github.test
react.internal.hermesPublishingGroup=io.github.test
ANOTHER_PROPERTY=true
"""
.trimIndent()
)
}
val hermesVersionFile =
tempFolder.newFile("version.properties").apply {
writeText(
"""
HERMES_V1_VERSION_NAME=
ANOTHER_PROPERTY=true
"""
.trimIndent()
)
}
val groupString = readVersionAndGroupStrings(propertiesFile).reactGroupString
val strings = readVersionAndGroupStrings(propertiesFile, hermesVersionFile)
val reactGroupString = strings.reactGroupString
val hermesGroupString = strings.hermesGroupString
assertThat(reactGroupString).isEqualTo("io.github.test")
assertThat(hermesGroupString).isEqualTo("io.github.test")
assertThat(groupString).isEqualTo("io.github.test")
}
@Test
@@ -722,23 +491,9 @@ class DependencyUtilsTest {
)
}
val hermesVersionFile =
tempFolder.newFile("version.properties").apply {
writeText(
"""
HERMES_V1_VERSION_NAME=
ANOTHER_PROPERTY=true
"""
.trimIndent()
)
}
val groupString = readVersionAndGroupStrings(propertiesFile).reactGroupString
val strings = readVersionAndGroupStrings(propertiesFile, hermesVersionFile)
val reactGroupString = strings.reactGroupString
val hermesGroupString = strings.hermesGroupString
assertThat(reactGroupString).isEqualTo("com.facebook.react")
assertThat(hermesGroupString).isEqualTo("com.facebook.hermes")
assertThat(groupString).isEqualTo("com.facebook.react")
}
@Test
@@ -166,7 +166,7 @@ class PathUtilsTest {
@WithOs(OS.MAC)
fun detectOSAwareHermesCommand_withHermesV1Enabled() {
tempFolder.newFolder("node_modules/hermes-compiler/osx-bin/")
val expected = tempFolder.newFile("node_modules/hermes-compiler/osx-bin/hermesc")
val expected = tempFolder.newFile("node_modules/hermes-compiler/osx-bin//hermesc")
assertThat(detectOSAwareHermesCommand(tempFolder.root, "", hermesV1Enabled = true))
.isEqualTo(expected.toString())
@@ -25,14 +25,14 @@ class OsRule : TestRule {
override fun evaluate() {
val annotation = description.annotations.filterIsInstance<WithOs>().firstOrNull()
annotation?.os?.propertyName?.let { osName ->
annotation?.os?.propertyName?.let {
retainOs = System.getProperty(OS_NAME_KEY)
System.setProperty(OS_NAME_KEY, osName)
System.setProperty(OS_NAME_KEY, it)
}
annotation?.arch?.let { arch ->
if (arch.isNotBlank()) {
annotation?.arch?.let {
if (it.isNotBlank()) {
retainArch = System.getProperty(OS_ARCH_KEY)
System.setProperty(OS_ARCH_KEY, arch)
System.setProperty(OS_ARCH_KEY, it)
}
}
try {
@@ -5,6 +5,8 @@
* LICENSE file in the root directory of this source tree.
*/
#import <React/RCTBridgeDelegate.h>
#import <React/RCTConvert.h>
#import <UIKit/UIKit.h>
#import "RCTDefaultReactNativeFactoryDelegate.h"
#import "RCTReactNativeFactory.h"
@@ -6,7 +6,6 @@
*/
#import "RCTAppDelegate.h"
#import <React/RCTBridgeDelegate.h>
#import <React/RCTLog.h>
#import <React/RCTRootView.h>
#import <React/RCTSurfacePresenterBridgeAdapter.h>
@@ -6,7 +6,6 @@
*
* @flow strict
* @format
* @deprecated
*/
'use strict';
@@ -6,7 +6,6 @@
*
* @flow strict
* @format
* @deprecated
*/
'use strict';
@@ -264,7 +264,7 @@ const Switch: component(
disabled,
onTintColor: trackColorForTrue,
style: StyleSheet.compose(
{alignSelf: 'flex-start' as const},
{height: 31, width: 51},
StyleSheet.compose(
style,
ios_backgroundColor == null
@@ -29,16 +29,6 @@ export const Commands: NativeCommands = codegenNativeCommands<NativeCommands>({
supportedCommands: ['hotspotUpdate', 'setPressed'],
});
/**
* `ViewNativeComponent` is an internal React Native host component, and is
* exported to provide lower-level access for libraries.
*
* @warning `<unstable_NativeView>` provides no semver guarantees and is not
* intended to be used in app code. Please use
* [`<View>`](https://reactnative.dev/docs/view) instead.
*/
// Additional note: Our long term plan is to reduce the overhead of the <Text>
// and <View> wrappers so that we no longer have any reason to export these APIs.
export default ViewNativeComponent;
export type ViewNativeComponentType = HostComponent<Props>;
@@ -6,7 +6,6 @@
*
* @flow
* @format
* @deprecated
*/
import NativeTiming from './NativeTiming';
@@ -6,7 +6,6 @@
*
* @flow strict
* @format
* @deprecated
*/
export * from '../../../src/private/specs_DEPRECATED/modules/NativeTiming';
@@ -6,7 +6,6 @@
*
* @flow
* @format
* @deprecated
*/
'use strict';
@@ -30,8 +30,7 @@ UIImage *RCTBlurredImageWithRadius(UIImage *inputImage, CGFloat radius)
}].CGImage;
}
vImage_Buffer buffer1;
vImage_Buffer buffer2;
vImage_Buffer buffer1, buffer2;
buffer1.width = buffer2.width = CGImageGetWidth(imageRef);
buffer1.height = buffer2.height = CGImageGetHeight(imageRef);
buffer1.rowBytes = buffer2.rowBytes = CGImageGetBytesPerRow(imageRef);
@@ -212,8 +212,7 @@ BOOL RCTUpscalingRequired(
sourceSize.height *= scale;
// Calculate aspect ratios if needed (don't bother if resizeMode == stretch)
CGFloat aspect = 0.0;
CGFloat targetAspect = 0.0;
CGFloat aspect = 0.0, targetAspect = 0.0;
if (resizeMode != RCTResizeModeStretch) {
aspect = sourceSize.width / sourceSize.height;
targetAspect = destSize.width / destSize.height;
+1 -5
View File
@@ -35,11 +35,7 @@ export interface SectionBase<ItemT, SectionT = DefaultSectionT> {
renderItem?: SectionListRenderItem<ItemT, SectionT> | undefined;
ItemSeparatorComponent?:
| React.ComponentType<any>
| React.ReactElement
| null
| undefined;
ItemSeparatorComponent?: React.ComponentType<any> | null | undefined;
keyExtractor?: ((item: ItemT, index: number) => string) | undefined;
}
@@ -90,15 +90,9 @@ uint32_t RCTInterpolateColorInRange(CGFloat value, NSArray<NSNumber *> *inputRan
CGFloat inputMin = inputRange[rangeIndex].doubleValue;
CGFloat inputMax = inputRange[rangeIndex + 1].doubleValue;
CGFloat redMin;
CGFloat greenMin;
CGFloat blueMin;
CGFloat alphaMin;
CGFloat redMin, greenMin, blueMin, alphaMin;
[outputRange[rangeIndex] getRed:&redMin green:&greenMin blue:&blueMin alpha:&alphaMin];
CGFloat redMax;
CGFloat greenMax;
CGFloat blueMax;
CGFloat alphaMax;
CGFloat redMax, greenMax, blueMax, alphaMax;
[outputRange[rangeIndex + 1] getRed:&redMax green:&greenMax blue:&blueMax alpha:&alphaMax];
return RCTColorFromComponents(
@@ -10,9 +10,9 @@
#import "RCTNetworkConversions.h"
#import <React/RCTLog.h>
#import <react/networking/NetworkReporter.h>
#import <jsinspector-modern/network/NetworkReporter.h>
using namespace facebook::react;
using namespace facebook::react::jsinspector_modern;
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
namespace {
@@ -50,7 +50,6 @@ Pod::Spec.new do |s|
add_dependency(s, "React-jsinspectorcdp", :framework_name => 'jsinspector_moderncdp')
add_dependency(s, "React-jsinspectornetwork", :framework_name => 'jsinspector_modernnetwork')
add_dependency(s, "React-NativeModulesApple", :additional_framework_paths => ["build/generated/ios"])
add_dependency(s, "React-networking", :framework_name => 'React_networking')
add_rn_third_party_dependencies(s)
add_rncore_dependency(s)
@@ -7,7 +7,7 @@
* @noformat
* @nolint
* @flow strict
* @generated SignedSource<<c0e57723772ea5f1aa8c3c897ac3c216>>
* @generated SignedSource<<deb7924d11c790f99448a1c2f0edddb9>>
*/
import type {
@@ -135,7 +135,6 @@ export type RenderRootOptions = {
error: mixed,
errorInfo: {+componentStack?: ?string},
) => void,
onDefaultTransitionIndicator?: () => void | (() => void),
};
/**
@@ -65,16 +65,6 @@ const virtualTextViewConfig = {
uiViewClassName: 'RCTVirtualText',
};
/**
* `NativeText` is an internal React Native host component, and is exported to
* provide lower-level access for libraries.
*
* @warning `<unstable_NativeText>` provides no semver guarantees and is not
* intended to be used in app code. Please use
* [`<Text>`](https://reactnative.dev/docs/text) instead.
*/
// Additional note: Our long term plan is to reduce the overhead of the <Text>
// and <View> wrappers so that we no longer have any reason to export these APIs.
export const NativeText: HostComponent<NativeTextProps> =
(createReactNativeComponentClass('RCTText', () =>
/* $FlowFixMe[incompatible-type] Natural Inference rollout. See
@@ -67,7 +67,7 @@ template <typename T>
facebook::react::LazyVector<T> RCTBridgingToVec(id value, T (^ctor)(id element))
{
NSArray *array = RCTBridgingToArray(value);
using _size_t = typename facebook::react::LazyVector<T>::size_type;
typedef typename facebook::react::LazyVector<T>::size_type _size_t;
_size_t size = static_cast<_size_t>(array.count);
return facebook::react::LazyVector<T>::fromUnsafeRawValue(array, size, ctor);
}
+1 -40
View File
@@ -68,17 +68,6 @@ let reactOSCompat = RNTarget(
path: "ReactCommon/oscompat"
)
let rctSwiftUI = RNTarget(
name: .rctSwiftUI,
path: "ReactApple/RCTSwiftUI"
)
let rctSwiftUIWrapper = RNTarget(
name: .rctSwiftUIWrapper,
path: "ReactApple/RCTSwiftUIWrapper",
dependencies: [.rctSwiftUI]
)
// React-rendererconsistency.podspec
let reactRendererConsistency = RNTarget(
name: .reactRendererConsistency,
@@ -222,18 +211,6 @@ let reactHermes = RNTarget(
]
)
/// React-networking.podspec
let reactNetworking = RNTarget(
name: .reactNetworking,
path: "ReactCommon/react/networking",
excludedPaths: ["tests"],
dependencies: [.reactNativeDependencies, .reactJsInspectorNetwork, .reactPerformanceTimeline],
defines: [
CXXSetting.define("REACT_NATIVE_DEBUGGER_ENABLED", to: "1", .when(configuration: BuildConfiguration.debug)),
CXXSetting.define("REACT_NATIVE_DEBUGGER_ENABLED_DEVONLY", to: "1", .when(configuration: BuildConfiguration.debug)),
]
)
/// React-performancecdpmetrics.podspec
let reactPerformanceCdpMetrics = RNTarget(
name: .reactPerformanceCdpMetrics,
@@ -327,13 +304,6 @@ let reactIdleCallbacksNativeModule = RNTarget(
dependencies: [.reactNativeDependencies, .reactDebug, .reactFeatureFlags, .reactUtils, .reactPerfLogger, .reactCxxReact, .reactTurboModuleCore]
)
/// React-webperformance.podspec
let reactWebPerformanceNativeModule = RNTarget(
name: .reactWebPerformanceNativeModule,
path: "ReactCommon/react/nativemodule/webperformance",
dependencies: [.reactNativeDependencies, .reactCxxReact, .reactTurboModuleCore, .reactPerformanceTimeline]
)
/// React-featureflagnativemodule.podspec
let reactFeatureflagsNativemodule = RNTarget(
name: .reactFeatureflagsNativemodule,
@@ -450,7 +420,7 @@ let reactFabric = RNTarget(
let reactRCTFabric = RNTarget(
name: .reactRCTFabric,
path: "React/Fabric",
dependencies: [.reactNativeDependencies, .reactCore, .reactRCTImage, .yoga, .reactRCTText, .jsi, .reactFabricComponents, .reactGraphics, .reactImageManager, .reactDebug, .reactUtils, .reactPerformanceTimeline, .reactRendererDebug, .reactRendererConsistency, .reactRuntimeScheduler, .reactRCTAnimation, .reactJsInspector, .reactJsInspectorNetwork, .reactJsInspectorTracing, .reactFabric, .reactFabricImage, .rctSwiftUIWrapper]
dependencies: [.reactNativeDependencies, .reactCore, .reactRCTImage, .yoga, .reactRCTText, .jsi, .reactFabricComponents, .reactGraphics, .reactImageManager, .reactDebug, .reactUtils, .reactPerformanceTimeline, .reactRendererDebug, .reactRendererConsistency, .reactRuntimeScheduler, .reactRCTAnimation, .reactJsInspector, .reactJsInspectorNetwork, .reactJsInspectorTracing, .reactFabric, .reactFabricImage]
)
/// React-FabricComponents.podspec
@@ -590,15 +560,12 @@ let targets = [
reactCore,
reactCoreRCTWebsocket,
reactFabric,
rctSwiftUI,
rctSwiftUIWrapper,
reactRCTFabric,
reactFabricComponents,
reactFabricImage,
reactNativeDependencies,
hermesPrebuilt,
reactJsiTooling,
reactNetworking,
reactPerformanceCdpMetrics,
reactPerformanceTimeline,
reactRuntimeScheduler,
@@ -623,7 +590,6 @@ let targets = [
reactTurboModuleCoreDefaults,
reactTurboModuleCoreMicrotasks,
reactIdleCallbacksNativeModule,
reactWebPerformanceNativeModule,
reactFeatureflagsNativemodule,
reactNativeModuleDom,
reactAppDelegate,
@@ -741,9 +707,6 @@ extension String {
static let logger = "React-logger"
static let mapbuffer = "React-Mapbuffer"
static let rctSwiftUI = "RCTSwiftUI"
static let rctSwiftUIWrapper = "RCTSwiftUIWrapper"
static let rctDeprecation = "RCT-Deprecation"
static let yoga = "Yoga"
static let reactUtils = "React-utils"
@@ -774,7 +737,6 @@ extension String {
static let hermesPrebuilt = "hermes-prebuilt"
static let reactJsiTooling = "React-jsitooling"
static let reactNetworking = "React-networking"
static let reactPerformanceCdpMetrics = "React-performancecdpmetrics"
static let reactPerformanceTimeline = "React-performancetimeline"
static let reactRuntimeScheduler = "React-runtimescheduler"
@@ -802,7 +764,6 @@ extension String {
static let reactTurboModuleCoreDefaults = "ReactCommon/turbomodule/core/defaults"
static let reactTurboModuleCoreMicrotasks = "ReactCommon/turbomodule/core/microtasks"
static let reactIdleCallbacksNativeModule = "React-idlecallbacksnativemodule"
static let reactWebPerformanceNativeModule = "React-webperformancenativemodule"
static let reactFeatureflagsNativemodule = "React-featureflagsnativemodule"
static let reactNativeModuleDom = "React-domnativemodule"
static let reactAppDelegate = "React-RCTAppDelegate"
@@ -69,7 +69,6 @@ RCT_EXTERN_C_END
* will be used as the JS module name. If omitted, the JS module name will
* match the Objective-C class name.
*/
#ifndef RCT_FIT_RM_OLD_RUNTIME
#define RCT_EXPORT_MODULE(js_name) \
RCT_EXTERN void RCTRegisterModule(Class); \
+(NSString *)moduleName \
@@ -81,17 +80,6 @@ RCT_EXTERN_C_END
RCTRegisterModule(self); \
}
#else
#define RCT_EXPORT_MODULE(js_name) \
RCT_EXTERN void RCTRegisterModule(Class); \
+(NSString *)moduleName \
{ \
return @ #js_name; \
}
#endif // RCT_FIT_RM_OLD_RUNTIME
/**
* Same as RCT_EXPORT_MODULE, but uses __attribute__((constructor)) for module
* registration. Useful for registering swift classes that forbids use of load
+3 -3
View File
@@ -721,13 +721,13 @@ NSData *__nullable RCTGzipData(NSData *__nullable input, float level)
void *libz = dlopen("/usr/lib/libz.dylib", RTLD_LAZY);
using DeflateInit2_ = int (*)(z_streamp, int, int, int, int, int, const char *, int);
typedef int (*DeflateInit2_)(z_streamp, int, int, int, int, int, const char *, int);
DeflateInit2_ deflateInit2_ = (DeflateInit2_)dlsym(libz, "deflateInit2_");
using Deflate = int (*)(z_streamp, int);
typedef int (*Deflate)(z_streamp, int);
Deflate deflate = (Deflate)dlsym(libz, "deflate");
using DeflateEnd = int (*)(z_streamp);
typedef int (*DeflateEnd)(z_streamp);
DeflateEnd deflateEnd = (DeflateEnd)dlsym(libz, "deflateEnd");
z_stream stream;
@@ -238,10 +238,11 @@ static NSDictionary *RCTExportedDimensions(CGFloat fontScale)
- (void)interfaceOrientationDidChange
{
#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST
UIWindow *window = RCTKeyWindow();
UIInterfaceOrientation nextOrientation = window.windowScene.interfaceOrientation;
UIApplication *application = RCTSharedApplication();
UIInterfaceOrientation nextOrientation = RCTKeyWindow().windowScene.interfaceOrientation;
BOOL isRunningInFullScreen = window ? CGRectEqualToRect(window.frame, window.screen.bounds) : YES;
BOOL isRunningInFullScreen =
CGRectEqualToRect(application.delegate.window.frame, application.delegate.window.screen.bounds);
// We are catching here two situations for multitasking view:
// a) The app is in Split View and the container gets resized -> !isRunningInFullScreen
// b) The app changes to/from fullscreen example: App runs in slide over mode and goes into fullscreen->
@@ -81,8 +81,7 @@
return;
}
CGFloat top = 0;
CGFloat left = 0;
CGFloat top = 0, left = 0;
if (contentSize.width < boundsSize.width) {
left = (boundsSize.width - contentSize.width) * 0.5f;
}
@@ -12,7 +12,6 @@
#import <objc/runtime.h>
#import <ranges>
#import <RCTSwiftUIWrapper/RCTSwiftUIContainerViewWrapper.h>
#import <React/RCTAssert.h>
#import <React/RCTBorderDrawing.h>
#import <React/RCTBoxShadow.h>
@@ -51,7 +50,6 @@ const CGFloat BACKGROUND_COLOR_ZPOSITION = -1024.0f;
UIView *_containerView;
BOOL _useCustomContainerView;
NSMutableSet<NSString *> *_accessibilityOrderNativeIDs;
RCTSwiftUIContainerViewWrapper *_swiftUIWrapper;
}
#ifdef RCT_DYNAMIC_FRAMEWORKS
@@ -578,10 +576,6 @@ const CGFloat BACKGROUND_COLOR_ZPOSITION = -1024.0f;
auto newTransform = _props->resolveTransform(layoutMetrics);
self.layer.transform = RCTCATransform3DFromTransformMatrix(newTransform);
}
if (_swiftUIWrapper != nullptr) {
[_swiftUIWrapper updateLayoutWithBounds:self.bounds];
}
}
- (BOOL)isJSResponder
@@ -799,95 +793,43 @@ static RCTBorderStyle RCTBorderStyleFromOutlineStyle(OutlineStyle outlineStyle)
((!_props->boxShadow.empty() || (clipToPaddingBox && nonZeroBorderWidth)) || _props->outlineWidth != 0);
}
// The view that is used as the receiver for all styling (borders, background,
// etc.). Most of the time, this is just `self`. When a view has a filter like
// `blur` applied, we need to wrap it in a SwiftUI view to render the effect.
// In this case, `effectiveContentView` will be the content view inside the
// SwiftUI wrapper.
- (UIView *)effectiveContentView
{
if (!ReactNativeFeatureFlags::enableSwiftUIBasedFilters()) {
return self;
}
UIView *effectiveContentView = self;
if (self.styleNeedsSwiftUIContainer) {
if (_swiftUIWrapper == nullptr) {
_swiftUIWrapper = [RCTSwiftUIContainerViewWrapper new];
UIView *swiftUIContentView = [[UIView alloc] init];
for (UIView *subview = nullptr in self.subviews) {
[swiftUIContentView addSubview:subview];
}
swiftUIContentView.clipsToBounds = self.clipsToBounds;
self.clipsToBounds = NO;
swiftUIContentView.layer.mask = self.layer.mask;
self.layer.mask = nil;
[_swiftUIWrapper updateContentView:swiftUIContentView];
[_swiftUIWrapper updateLayoutWithBounds:self.bounds];
[self addSubview:_swiftUIWrapper.hostingView];
[self transferVisualPropertiesFromView:self toView:swiftUIContentView];
}
effectiveContentView = _swiftUIWrapper.contentView;
} else {
if (_swiftUIWrapper != nullptr) {
UIView *swiftUIContentView = _swiftUIWrapper.contentView;
for (UIView *subview = nullptr in swiftUIContentView.subviews) {
[self addSubview:subview];
}
self.clipsToBounds = swiftUIContentView.clipsToBounds;
self.layer.mask = swiftUIContentView.layer.mask;
[self transferVisualPropertiesFromView:swiftUIContentView toView:self];
[_swiftUIWrapper.hostingView removeFromSuperview];
_swiftUIWrapper = nil;
}
}
return effectiveContentView;
}
// This UIView is the UIView that holds all subviews. It is sometimes not self
// because we want to render "overflow ink" that extends beyond the bounds of
// the view and is not affected by clipping.
- (UIView *)currentContainerView
{
UIView *effectiveContentView = self.effectiveContentView;
if (_useCustomContainerView) {
if (!_containerView) {
_containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
for (UIView *subview = nullptr in effectiveContentView.subviews) {
for (UIView *subview in self.subviews) {
[_containerView addSubview:subview];
}
_containerView.clipsToBounds = effectiveContentView.clipsToBounds;
effectiveContentView.clipsToBounds = NO;
_containerView.layer.mask = effectiveContentView.layer.mask;
effectiveContentView.layer.mask = nil;
[effectiveContentView addSubview:_containerView];
_containerView.clipsToBounds = self.clipsToBounds;
self.clipsToBounds = NO;
_containerView.layer.mask = self.layer.mask;
self.layer.mask = nil;
[self addSubview:_containerView];
}
effectiveContentView = _containerView;
return _containerView;
} else {
if (_containerView) {
for (UIView *subview in _containerView.subviews) {
[effectiveContentView addSubview:subview];
[self addSubview:subview];
}
effectiveContentView.clipsToBounds = _containerView.clipsToBounds;
effectiveContentView.layer.mask = _containerView.layer.mask;
self.clipsToBounds = _containerView.clipsToBounds;
self.layer.mask = _containerView.layer.mask;
[_containerView removeFromSuperview];
_containerView = nil;
}
return self;
}
return effectiveContentView;
}
- (void)invalidateLayer
{
CALayer *layer = self.effectiveContentView.layer;
CALayer *layer = self.layer;
if (CGSizeEqualToSize(layer.bounds.size, CGSizeZero)) {
return;
@@ -968,7 +910,7 @@ static RCTBorderStyle RCTBorderStyleFromOutlineStyle(OutlineStyle outlineStyle)
if (!_backgroundColorLayer) {
_backgroundColorLayer = [CALayer layer];
_backgroundColorLayer.zPosition = BACKGROUND_COLOR_ZPOSITION;
[layer addSublayer:_backgroundColorLayer];
[self.layer addSublayer:_backgroundColorLayer];
}
[self shapeLayerToMatchView:_backgroundColorLayer borderMetrics:borderMetrics];
_backgroundColorLayer.backgroundColor = backgroundColor.CGColor;
@@ -1044,43 +986,31 @@ static RCTBorderStyle RCTBorderStyleFromOutlineStyle(OutlineStyle outlineStyle)
// filter
[_filterLayer removeFromSuperlayer];
_filterLayer = nil;
if (_swiftUIWrapper != nullptr) {
[_swiftUIWrapper updateBlurRadius:@(0)];
}
self.layer.opacity = (float)_props->opacity;
if (!_props->filter.empty()) {
float multiplicativeBrightness = 1;
bool hasBrightnessFilter = false;
for (const auto &primitive : _props->filter) {
if (std::holds_alternative<Float>(primitive.parameters)) {
if (primitive.type == FilterType::Brightness) {
multiplicativeBrightness *= std::get<Float>(primitive.parameters);
hasBrightnessFilter = true;
} else if (primitive.type == FilterType::Opacity) {
self.layer.opacity *= std::get<Float>(primitive.parameters);
} else if (primitive.type == FilterType::Blur) {
if (_swiftUIWrapper != nullptr) {
Float blurRadius = std::get<Float>(primitive.parameters);
[_swiftUIWrapper updateBlurRadius:@(blurRadius)];
}
}
}
}
if (hasBrightnessFilter) {
_filterLayer = [CALayer layer];
[self shapeLayerToMatchView:_filterLayer borderMetrics:borderMetrics];
_filterLayer.compositingFilter = @"multiplyBlendMode";
_filterLayer.backgroundColor = [UIColor colorWithRed:multiplicativeBrightness
green:multiplicativeBrightness
blue:multiplicativeBrightness
alpha:self.layer.opacity]
.CGColor;
// So that this layer is always above any potential sublayers this view may
// add
_filterLayer.zPosition = CGFLOAT_MAX;
[layer addSublayer:_filterLayer];
}
_filterLayer = [CALayer layer];
[self shapeLayerToMatchView:_filterLayer borderMetrics:borderMetrics];
_filterLayer.compositingFilter = @"multiplyBlendMode";
_filterLayer.backgroundColor = [UIColor colorWithRed:multiplicativeBrightness
green:multiplicativeBrightness
blue:multiplicativeBrightness
alpha:self.layer.opacity]
.CGColor;
// So that this layer is always above any potential sublayers this view may
// add
_filterLayer.zPosition = CGFLOAT_MAX;
[self.layer addSublayer:_filterLayer];
}
// background image
@@ -1095,7 +1025,7 @@ static RCTBorderStyle RCTBorderStyleFromOutlineStyle(OutlineStyle outlineStyle)
[self shapeLayerToMatchView:backgroundImageLayer borderMetrics:borderMetrics];
backgroundImageLayer.masksToBounds = YES;
backgroundImageLayer.zPosition = BACKGROUND_COLOR_ZPOSITION;
[layer addSublayer:backgroundImageLayer];
[self.layer addSublayer:backgroundImageLayer];
[_backgroundImageLayers addObject:backgroundImageLayer];
} else if (std::holds_alternative<RadialGradient>(backgroundImage)) {
const auto &radialGradient = std::get<RadialGradient>(backgroundImage);
@@ -1104,7 +1034,7 @@ static RCTBorderStyle RCTBorderStyleFromOutlineStyle(OutlineStyle outlineStyle)
[self shapeLayerToMatchView:backgroundImageLayer borderMetrics:borderMetrics];
backgroundImageLayer.masksToBounds = YES;
backgroundImageLayer.zPosition = BACKGROUND_COLOR_ZPOSITION;
[layer addSublayer:backgroundImageLayer];
[self.layer addSublayer:backgroundImageLayer];
[_backgroundImageLayers addObject:backgroundImageLayer];
}
}
@@ -1126,7 +1056,7 @@ static RCTBorderStyle RCTBorderStyleFromOutlineStyle(OutlineStyle outlineStyle)
RCTUIEdgeInsetsFromEdgeInsets(borderMetrics.borderWidths),
self.layer.bounds.size);
shadowLayer.zPosition = _borderLayer.zPosition;
[layer addSublayer:shadowLayer];
[self.layer addSublayer:shadowLayer];
[_boxShadowLayers addObject:shadowLayer];
}
}
@@ -1480,66 +1410,6 @@ static NSString *RCTRecursiveAccessibilityLabel(UIView *view)
return RCTNSStringFromString([[self class] componentDescriptorProvider].name);
}
- (BOOL)styleNeedsSwiftUIContainer
{
if (!_props->filter.empty()) {
for (const auto &primitive : _props->filter) {
if (primitive.type == FilterType::Blur) {
return YES;
}
}
}
return NO;
}
- (void)transferVisualPropertiesFromView:(UIView *)sourceView toView:(UIView *)destinationView
{
// shadow
destinationView.layer.shadowColor = sourceView.layer.shadowColor;
sourceView.layer.shadowColor = nil;
destinationView.layer.shadowOffset = sourceView.layer.shadowOffset;
sourceView.layer.shadowOffset = CGSizeZero;
destinationView.layer.shadowOpacity = sourceView.layer.shadowOpacity;
sourceView.layer.shadowOpacity = 0;
destinationView.layer.shadowRadius = sourceView.layer.shadowRadius;
sourceView.layer.shadowRadius = 0;
// background
destinationView.layer.backgroundColor = sourceView.layer.backgroundColor;
sourceView.layer.backgroundColor = nil;
if (_backgroundColorLayer != nullptr) {
[destinationView.layer addSublayer:_backgroundColorLayer];
}
// border
destinationView.layer.borderColor = sourceView.layer.borderColor;
sourceView.layer.borderColor = nil;
destinationView.layer.borderWidth = sourceView.layer.borderWidth;
sourceView.layer.borderWidth = 0;
// corner
destinationView.layer.cornerRadius = sourceView.layer.cornerRadius;
sourceView.layer.cornerRadius = 0;
destinationView.layer.cornerCurve = sourceView.layer.cornerCurve;
// custom layers
if (_borderLayer != nullptr) {
[destinationView.layer addSublayer:_borderLayer];
}
if (_outlineLayer != nullptr) {
[destinationView.layer addSublayer:_outlineLayer];
}
if (_filterLayer != nullptr) {
[destinationView.layer addSublayer:_filterLayer];
}
for (CALayer *layer = nullptr in _backgroundImageLayers) {
[destinationView.layer addSublayer:layer];
}
for (CALayer *layer = nullptr in _boxShadowLayers) {
[destinationView.layer addSublayer:layer];
}
}
@end
#ifdef __cplusplus
@@ -32,7 +32,7 @@ std::unique_ptr<IWebSocket> RCTCxxInspectorPackagerConnectionDelegate::connectWe
std::weak_ptr<IWebSocketDelegate> delegate)
{
auto *adapter = [[RCTCxxInspectorWebSocketAdapter alloc] initWithURL:url delegate:delegate];
if (adapter == nullptr) {
if (!adapter) {
return nullptr;
}
return std::make_unique<WebSocket>(adapter);
@@ -34,7 +34,7 @@ NSString *NSStringFromUTF8StringView(std::string_view view)
@implementation RCTCxxInspectorWebSocketAdapter
- (instancetype)initWithURL:(const std::string &)url delegate:(std::weak_ptr<IWebSocketDelegate>)delegate
{
if ((self = [super init]) != nullptr) {
if ((self = [super init])) {
_delegate = delegate;
_webSocket = [[SRWebSocket alloc] initWithURL:[NSURL URLWithString:NSStringFromUTF8StringView(url)]];
_webSocket.delegate = self;
@@ -49,7 +49,7 @@ NSString *NSStringFromUTF8StringView(std::string_view view)
NSString *messageStr = NSStringFromUTF8StringView(message);
dispatch_async(dispatch_get_main_queue(), ^{
RCTCxxInspectorWebSocketAdapter *strongSelf = weakSelf;
if (strongSelf != nullptr) {
if (strongSelf) {
[strongSelf->_webSocket sendString:messageStr error:NULL];
}
});
@@ -63,7 +63,6 @@ Pod::Spec.new do |s|
s.dependency "Yoga"
s.dependency "React-RCTText"
s.dependency "React-jsi"
s.dependency "RCTSwiftUIWrapper"
add_dependency(s, "React-FabricImage")
add_dependency(s, "React-Fabric", :additional_framework_paths => [
@@ -92,9 +91,9 @@ Pod::Spec.new do |s|
add_dependency(s, "React-RCTAnimation", :framework_name => 'RCTAnimation')
add_dependency(s, "React-jsinspector", :framework_name => 'jsinspector_modern')
add_dependency(s, "React-jsinspectorcdp", :framework_name => 'jsinspector_moderncdp')
add_dependency(s, "React-jsinspectornetwork", :framework_name => 'jsinspector_modernnetwork')
add_dependency(s, "React-jsinspectortracing", :framework_name => 'jsinspector_moderntracing')
add_dependency(s, "React-performancecdpmetrics", :framework_name => 'React_performancecdpmetrics')
add_dependency(s, "React-networking", :framework_name => 'React_networking')
add_dependency(s, "React-renderercss")
add_dependency(s, "React-RCTFBReactNativeSpec")
@@ -80,9 +80,7 @@ static void RCTPathAddEllipticArc(
CGFloat endAngle,
BOOL clockwise)
{
CGFloat xScale = 1;
CGFloat yScale = 1;
CGFloat radius = 0;
CGFloat xScale = 1, yScale = 1, radius = 0;
if (size.width != 0) {
xScale = 1;
yScale = size.height / size.width;
@@ -50,7 +50,7 @@ static SEL selectorForType(NSString *type)
bridge:(RCTBridge *)bridge
eventDispatcher:(id<RCTEventDispatcherProtocol>)eventDispatcher
{
if ((self = [super init]) != nullptr) {
if ((self = [super init])) {
_bridge = bridge;
_eventDispatcher = eventDispatcher;
_managerClass = managerClass;
@@ -71,12 +71,12 @@ static SEL selectorForType(NSString *type)
- (RCTViewManager *)manager
{
if ((_manager == nullptr) && [self isBridgeMode]) {
if (!_manager && [self isBridgeMode]) {
_manager = [_bridge moduleForClass:_managerClass];
} else if ((_manager == nullptr) && (_bridgelessViewManager == nullptr)) {
} else if (!_manager && !_bridgelessViewManager) {
_bridgelessViewManager = [_bridge moduleForClass:_managerClass];
}
return (_manager != nullptr) ? _manager : _bridgelessViewManager;
return _manager ? _manager : _bridgelessViewManager;
}
RCT_NOT_IMPLEMENTED(-(instancetype)init)
@@ -106,7 +106,7 @@ RCT_NOT_IMPLEMENTED(-(instancetype)init)
{
json = RCTNilIfNull(json);
if (!isShadowView) {
if ((json == nullptr) && (_defaultView == nullptr)) {
if (!json && !_defaultView) {
// Only create default view if json is null
_defaultView = [self createViewWithTag:nil rootTag:nil];
}
@@ -130,11 +130,11 @@ static RCTPropBlock createEventSetter(
eventHandler = ^(NSDictionary *event) {
// The component no longer exists, we shouldn't send the event
id<RCTComponent> strongTarget = weakTarget;
if (strongTarget == nullptr) {
if (!strongTarget) {
return;
}
if (eventInterceptor != nullptr) {
if (eventInterceptor) {
eventInterceptor(propName, event, strongTarget.reactTag);
} else {
RCTComponentEvent *componentEvent = [[RCTComponentEvent alloc] initWithName:propName
@@ -158,13 +158,13 @@ static RCTPropBlock createNSInvocationSetter(NSMethodSignature *typeSignature, S
__block NSMutableData *defaultValue = nil;
return ^(id target, id json) {
if (target == nullptr) {
if (!target) {
return;
}
// Get default value
if (defaultValue == nullptr) {
if (json == nullptr) {
if (!defaultValue) {
if (!json) {
// We only set the defaultValue when we first pass a non-null
// value, so if the first value sent for a prop is null, it's
// a no-op (we'd be resetting it to its default when its
@@ -186,10 +186,10 @@ static RCTPropBlock createNSInvocationSetter(NSMethodSignature *typeSignature, S
// Get value
BOOL freeValueOnCompletion = NO;
void *value = defaultValue.mutableBytes;
if (json != nullptr) {
if (json) {
freeValueOnCompletion = YES;
value = malloc(typeSignature.methodReturnLength);
if (value == nullptr) {
if (!value) {
// CWE - 391 : Unchecked error condition
// https://www.cvedetails.com/cwe-details/391/Unchecked-Error-Condition.html
// https://eli.thegreenplace.net/2009/10/30/handling-out-of-memory-conditions-in-c
@@ -201,7 +201,7 @@ static RCTPropBlock createNSInvocationSetter(NSMethodSignature *typeSignature, S
}
// Set value
if (targetInvocation == nullptr) {
if (!targetInvocation) {
NSMethodSignature *signature = [target methodSignatureForSelector:setter];
targetInvocation = [NSInvocation invocationWithMethodSignature:signature];
targetInvocation.selector = setter;
@@ -252,7 +252,7 @@ static RCTPropBlock createNSInvocationSetter(NSMethodSignature *typeSignature, S
// Disect keypath
NSString *key = name;
NSArray<NSString *> *parts = [keyPath componentsSeparatedByString:@"."];
if (parts != nullptr) {
if (parts) {
key = parts.lastObject;
parts = [parts subarrayWithRange:(NSRange){0, parts.count - 1}];
}
@@ -275,7 +275,7 @@ static RCTPropBlock createNSInvocationSetter(NSMethodSignature *typeSignature, S
} else {
// Ordinary property handlers
NSMethodSignature *typeSignature = [[RCTConvert class] methodSignatureForSelector:type];
if (typeSignature == nullptr) {
if (!typeSignature) {
RCTLogError(@"No +[RCTConvert %@] function found.", NSStringFromSelector(type));
return ^(__unused id<RCTComponent> view, __unused id json) {
};
@@ -347,7 +347,7 @@ static RCTPropBlock createNSInvocationSetter(NSMethodSignature *typeSignature, S
{
RCTPropBlockDictionary *propBlocks = isShadowView ? _shadowPropBlocks : _viewPropBlocks;
RCTPropBlock propBlock = propBlocks[name];
if (propBlock == nullptr) {
if (!propBlock) {
propBlock = [self createPropBlock:name isShadowView:isShadowView];
#if RCT_DEBUG
@@ -381,7 +381,7 @@ static RCTPropBlock createNSInvocationSetter(NSMethodSignature *typeSignature, S
- (void)setProps:(NSDictionary<NSString *, id> *)props forView:(id<RCTComponent>)view isShadowView:(BOOL)isShadowView
{
if (view == nullptr) {
if (!view) {
return;
}
@@ -467,13 +467,13 @@ static RCTPropBlock createNSInvocationSetter(NSMethodSignature *typeSignature, S
// We need to handle both propConfig_* and propConfigShadow_* methods
const char *underscorePos = strchr(selectorName + strlen("propConfig"), '_');
if (underscorePos == nullptr) {
if (!underscorePos) {
continue;
}
NSString *name = @(underscorePos + 1);
NSString *type = ((NSArray<NSString *> * (*)(id, SEL)) objc_msgSend)(managerClass, selector)[0];
if (RCT_DEBUG && (propTypes[name] != nullptr) && ![propTypes[name] isEqualToString:type]) {
if (RCT_DEBUG && propTypes[name] && ![propTypes[name] isEqualToString:type]) {
RCTLogError(
@"Property '%@' of component '%@' redefined from '%@' "
"to '%@'",
@@ -1,16 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <UIKit/UIKit.h>
#import <React/RCTDefines.h>
NS_ASSUME_NONNULL_BEGIN
RCT_EXTERN UIFont *__nullable RCTGetLegacyDefaultFont(CGFloat fontSize, UIFontWeight fontWeight);
NS_ASSUME_NONNULL_END
+1 -3
View File
@@ -17,10 +17,8 @@ typedef CGFloat RCTFontWeight;
* provide a different base font, use this override. The font weight supplied to your
* handler will be one of "ultralight", "thin", "light", "regular", "medium",
* "semibold", "extrabold", "bold", "heavy", or "black".
*
* @deprecated Use RCTSetDefaultFontResolver
*/
RCT_EXTERN void RCTSetDefaultFontHandler(RCTFontHandler handler) __attribute__((deprecated));
RCT_EXTERN void RCTSetDefaultFontHandler(RCTFontHandler handler);
RCT_EXTERN BOOL RCTHasFontHandlerSet(void);
RCT_EXTERN RCTFontWeight RCTGetFontWeight(UIFont *font);
+2 -13
View File
@@ -6,8 +6,6 @@
*/
#import "RCTFont.h"
#import "RCTFont+Private.h"
#import "RCTAssert.h"
#import "RCTLog.h"
@@ -124,15 +122,6 @@ static NSString *FontWeightDescriptionFromUIFontWeight(UIFontWeight fontWeight)
return @"regular";
}
UIFont *RCTGetLegacyDefaultFont(CGFloat size, UIFontWeight fontWeight)
{
if (defaultFontHandler != nil) {
return defaultFontHandler(size, FontWeightDescriptionFromUIFontWeight(fontWeight));
} else {
return nil;
}
}
static UIFont *cachedSystemFont(CGFloat size, RCTFontWeight weight)
{
static NSCache<NSValue *, UIFont *> *fontCache = [NSCache new];
@@ -146,8 +135,8 @@ static UIFont *cachedSystemFont(CGFloat size, RCTFontWeight weight)
NSValue *cacheKey = [[NSValue alloc] initWithBytes:&key objCType:@encode(CacheKey)];
UIFont *font = [fontCache objectForKey:cacheKey];
if (font == nil) {
if (defaultFontHandler != nil) {
if (!font) {
if (defaultFontHandler) {
NSString *fontWeightDescription = FontWeightDescriptionFromUIFontWeight(weight);
font = defaultFontHandler(size, fontWeightDescription);
} else {
@@ -679,8 +679,7 @@ RCT_SCROLL_EVENT_HANDLER(scrollViewDidScrollToTop, onScrollToTop)
return;
}
CGFloat top = 0;
CGFloat left = 0;
CGFloat top = 0, left = 0;
if (contentSize.width < boundsSize.width) {
left = (boundsSize.width - contentSize.width) * 0.5f;
}
@@ -2354,14 +2354,12 @@ public class com/facebook/react/fabric/mounting/SurfaceMountingManager {
public fun sendAccessibilityEvent (II)V
public fun setJSResponder (IIZ)V
public fun stopSurface ()V
public fun storeSynchronousMountPropsOverride (ILcom/facebook/react/bridge/ReadableMap;)V
public fun sweepActiveTouchForTag (I)V
public fun updateEventEmitter (ILcom/facebook/react/fabric/events/EventEmitterWrapper;)V
public fun updateLayout (IIIIIIII)V
public fun updateOverflowInset (IIIII)V
public fun updatePadding (IIIII)V
public fun updateProps (ILcom/facebook/react/bridge/ReadableMap;)V
public fun updatePropsSynchronously (ILcom/facebook/react/bridge/ReadableMap;)V
public fun updateState (ILcom/facebook/react/uimanager/StateWrapper;)V
}
@@ -5246,7 +5244,6 @@ public class com/facebook/react/viewmanagers/VirtualViewExperimentalManagerDeleg
public abstract interface class com/facebook/react/viewmanagers/VirtualViewExperimentalManagerInterface : com/facebook/react/uimanager/ViewManagerWithGeneratedInterface {
public abstract fun setInitialHidden (Landroid/view/View;Z)V
public abstract fun setRemoveClippedSubviews (Landroid/view/View;Z)V
public abstract fun setRenderState (Landroid/view/View;I)V
}
@@ -6726,10 +6723,9 @@ public final class com/facebook/react/views/virtual/viewexperimental/ReactVirtua
public fun onLayoutChange (Landroid/view/View;IIIIIIII)V
public fun onModeChange (Lcom/facebook/react/views/virtual/VirtualViewMode;Landroid/graphics/Rect;)V
public synthetic fun recycleView$xplat_js_react_native_github_packages_react_native_ReactAndroid_src_main_java_com_facebook_react_views_view_viewAndroid ()V
public fun updateClippingRect (Ljava/util/Set;)V
}
public final class com/facebook/react/views/virtual/viewexperimental/ReactVirtualViewExperimentalManager : com/facebook/react/views/view/ReactClippingViewManager, com/facebook/react/viewmanagers/VirtualViewExperimentalManagerInterface {
public final class com/facebook/react/views/virtual/viewexperimental/ReactVirtualViewExperimentalManager : com/facebook/react/uimanager/ViewGroupManager, com/facebook/react/viewmanagers/VirtualViewExperimentalManagerInterface {
public static final field Companion Lcom/facebook/react/views/virtual/viewexperimental/ReactVirtualViewExperimentalManager$Companion;
public static final field REACT_CLASS Ljava/lang/String;
public fun <init> ()V
@@ -6741,7 +6737,6 @@ public final class com/facebook/react/views/virtual/viewexperimental/ReactVirtua
public fun setInitialHidden (Lcom/facebook/react/views/virtual/viewexperimental/ReactVirtualViewExperimental;Z)V
public synthetic fun setNativeId (Landroid/view/View;Ljava/lang/String;)V
public fun setNativeId (Lcom/facebook/react/views/virtual/viewexperimental/ReactVirtualViewExperimental;Ljava/lang/String;)V
public synthetic fun setRemoveClippedSubviews (Landroid/view/View;Z)V
public synthetic fun setRenderState (Landroid/view/View;I)V
public fun setRenderState (Lcom/facebook/react/views/virtual/viewexperimental/ReactVirtualViewExperimental;I)V
}
@@ -1,4 +1,5 @@
VERSION_NAME=1000.0.0
HERMES_VERSION_NAME=1000.0.0
react.internal.publishingGroup=com.facebook.react
react.internal.hermesPublishingGroup=com.facebook.hermes
@@ -88,7 +88,7 @@ val hermesVersionProvider: Provider<String> =
val hermesVersionFile =
File(
reactNativeRootDir,
if (hermesV1Enabled) "sdks/.hermesv1version" else "sdks/.hermesversion",
if (hermesV1Enabled) "sdks/.hermesv1version" else "\"sdks/.hermesversion\"",
)
if (hermesVersionFile.exists()) {
@@ -196,9 +196,11 @@ public class NativeAnimatedModule(reactContext: ReactApplicationContext) :
private val nodesManagerRef = AtomicReference<NativeAnimatedNodesManager?>()
@Volatile private var currentFrameNumber: Long = 0
private var batchingControlledByJS = false // TODO T71377544: delete
@Volatile private var currentBatchNumber: Long = 0 // frame number at last operations dispatch
@Volatile private var currentFrameNumber: Long = 0 // TODO T71377544: delete
@Volatile private var currentBatchNumber: Long = 0
private var initializedForFabric = false
private var initializedForNonFabric = false
@@ -280,19 +282,22 @@ public class NativeAnimatedModule(reactContext: ReactApplicationContext) :
var batchNumber = currentBatchNumber - 1
// The problem we're trying to solve here: we could be in the middle of queueing
// a batch of related animation operations when Fabric flushes a batch of MountItems.
// It's visually bad if we execute half of the animation ops and then wait another frame
// (or more) to execute the rest.
// See mFrameNumber. If the dispatchedFrameNumber drifts too far - that
// is, if no MountItems are scheduled for a while, which can happen if a tree
// is committed but there are no changes - bring these counts back in sync and
// execute any queued operations. This number is arbitrary, but we want it low
// enough that the user shouldn't be able to see this delay in most cases.
currentFrameNumber++
if ((currentFrameNumber - currentBatchNumber) > 2) {
currentBatchNumber = currentFrameNumber
batchNumber = currentBatchNumber
// TODO T71377544: delete this when the JS method is confirmed safe
if (!batchingControlledByJS) {
// The problem we're trying to solve here: we could be in the middle of queueing
// a batch of related animation operations when Fabric flushes a batch of MountItems.
// It's visually bad if we execute half of the animation ops and then wait another frame
// (or more) to execute the rest.
// See mFrameNumber. If the dispatchedFrameNumber drifts too far - that
// is, if no MountItems are scheduled for a while, which can happen if a tree
// is committed but there are no changes - bring these counts back in sync and
// execute any queued operations. This number is arbitrary, but we want it low
// enough that the user shouldn't be able to see this delay in most cases.
currentFrameNumber++
if ((currentFrameNumber - currentBatchNumber) > 2) {
currentBatchNumber = currentFrameNumber
batchNumber = currentBatchNumber
}
}
preOperations.executeBatch(batchNumber, nodesManager)
@@ -479,14 +484,14 @@ public class NativeAnimatedModule(reactContext: ReactApplicationContext) :
}
}
@Suppress("DEPRECATION")
override fun startOperationBatch() {
// no-op
batchingControlledByJS = true
currentBatchNumber++
}
@Suppress("DEPRECATION")
override fun finishOperationBatch() {
// no-op
batchingControlledByJS = false
currentBatchNumber++
}
override fun createAnimatedNode(tagDouble: Double, config: ReadableMap) {
@@ -774,8 +774,12 @@ public class NativeAnimatedNodesManager(
("Looks like animated nodes graph has ${reason}, there are $activeNodesCount but toposort visited only $updatedNodesCount")
)
if (eventListenerInitializedForFabric && cyclesDetected == 0) {
// TODO T71377544: investigate these SoftExceptions and see if we can remove entirely
// or fix the root cause
ReactSoftExceptionLogger.logSoftException(TAG, ReactNoCrashSoftException(ex))
} else if (eventListenerInitializedForFabric) {
// TODO T71377544: investigate these SoftExceptions and see if we can remove entirely
// or fix the root cause
ReactSoftExceptionLogger.logSoftException(TAG, ReactNoCrashSoftException(ex))
} else {
throw ex
@@ -96,7 +96,7 @@ public class CatalystInstanceImpl implements CatalystInstance {
private final TraceListener mTraceListener;
private final JavaScriptModuleRegistry mJSModuleRegistry;
private final JSBundleLoader mJSBundleLoader;
private final ArrayList<PendingJSCall> mJSCallsPendingInit = new ArrayList<>();
private final ArrayList<PendingJSCall> mJSCallsPendingInit = new ArrayList<PendingJSCall>();
private final Object mJSCallsPendingInitLock = new Object();
private final NativeModuleRegistry mNativeModuleRegistry;
@@ -25,7 +25,7 @@ public abstract class ReactContextBaseJavaModule : BaseJavaModule {
* this method whenever you actually need the Activity and make sure to check for `null`.
*/
@Deprecated(
"Deprecated in 0.80.0. Use getReactApplicationContext().getCurrentActivity() instead.",
"Deprecated in 0.80.0. Use getReactApplicationContext.getCurrentActivity() instead.",
ReplaceWith("reactApplicationContext.currentActivity"),
)
protected fun getCurrentActivity(): Activity? {
@@ -83,6 +83,6 @@ internal class BridgelessDevSupportManager(
}
fun tracingState(): TracingState {
return TracingState.ENABLEDINCDPMODE
return TracingState.DISABLED
}
}
@@ -68,7 +68,6 @@ import com.facebook.react.devsupport.interfaces.StackFrame
import com.facebook.react.devsupport.interfaces.TracingState
import com.facebook.react.devsupport.interfaces.TracingStateProvider
import com.facebook.react.devsupport.perfmonitor.PerfMonitorDevHelper
import com.facebook.react.devsupport.perfmonitor.PerfMonitorOverlayManager
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags
import com.facebook.react.internal.featureflags.ReactNativeNewArchitectureFeatureFlags
import com.facebook.react.modules.core.RCTNativeAppEventEmitter
@@ -78,7 +77,6 @@ import java.io.File
import java.net.MalformedURLException
import java.net.URL
import java.util.Locale
import javax.inject.Provider
public abstract class DevSupportManagerBase(
protected val applicationContext: Context,
@@ -184,7 +182,7 @@ public abstract class DevSupportManagerBase(
null
}
private var perfMonitorOverlayManager: PerfMonitorOverlayManager? = null
private var perfMonitorOverlayManager: PerfMonitorOverlayViewManager? = null
private var tracingStateProvider: TracingStateProvider? = null
init {
@@ -217,19 +215,19 @@ public abstract class DevSupportManagerBase(
if (
ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture() &&
ReactNativeFeatureFlags.perfMonitorV2Enabled() &&
reactInstanceDevHelper is PerfMonitorDevHelper
reactInstanceDevHelper is PerfMonitorDevHelper &&
perfMonitorOverlayManager == null
) {
perfMonitorOverlayManager =
PerfMonitorOverlayManager(
reactInstanceDevHelper,
Provider {
PerfMonitorOverlayViewManager(
Supplier {
val context = reactInstanceDevHelper.currentActivity
if (context == null || context.isFinishing) {
return@Provider null
return@Supplier null
}
context
},
{ openDebugger(DebuggerFrontendPanelName.PERFORMANCE.toString()) },
reactInstanceDevHelper.inspectorTarget,
)
}
}
@@ -387,14 +385,10 @@ public abstract class DevSupportManagerBase(
TracingState.ENABLEDINBACKGROUNDMODE ->
DevOptionHandler {
UiThreadUtil.runOnUiThread {
if (reactInstanceDevHelper is PerfMonitorDevHelper) {
reactInstanceDevHelper.inspectorTarget?.let {
if (it.pauseAndAnalyzeBackgroundTrace()) {
openDebugger(DebuggerFrontendPanelName.PERFORMANCE.toString())
}
}
}
if (reactInstanceDevHelper is PerfMonitorDevHelper)
reactInstanceDevHelper.inspectorTarget?.pauseAndAnalyzeBackgroundTrace()
}
openDebugger(DebuggerFrontendPanelName.PERFORMANCE.toString())
}
TracingState.DISABLED ->
DevOptionHandler {
@@ -554,11 +548,10 @@ public abstract class DevSupportManagerBase(
override fun onNewReactContextCreated(reactContext: ReactContext) {
resetCurrentContext(reactContext)
if (reactInstanceDevHelper is PerfMonitorDevHelper) {
if (perfMonitorOverlayManager != null && reactInstanceDevHelper is PerfMonitorDevHelper) {
perfMonitorOverlayManager?.let { manager ->
reactInstanceDevHelper.inspectorTarget?.addPerfMonitorListener(manager)
}
perfMonitorOverlayManager?.enable()
}
}
@@ -889,7 +882,6 @@ public abstract class DevSupportManagerBase(
override fun onPackagerDisconnected() {
isPackagerConnected = false
perfMonitorOverlayManager?.disable()
}
override fun onPackagerReloadCommand() {
@@ -0,0 +1,278 @@
/*
* 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.devsupport
import android.app.Dialog
import android.content.Context
import android.graphics.Color
import android.graphics.Typeface
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.GradientDrawable
import android.os.Handler
import android.os.Looper
import android.view.Gravity
import android.view.Window
import android.view.WindowManager
import android.widget.LinearLayout
import android.widget.TextView
import androidx.core.util.Supplier
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.facebook.react.R
import com.facebook.react.bridge.UiThreadUtil
import com.facebook.react.devsupport.interfaces.PerfMonitorOverlayManager
import com.facebook.react.devsupport.interfaces.TracingState
import com.facebook.react.devsupport.perfmonitor.PerfMonitorInspectorTargetBinding
import com.facebook.react.devsupport.perfmonitor.PerfMonitorUpdateListener
import com.facebook.react.uimanager.DisplayMetricsHolder
import com.facebook.react.uimanager.PixelUtil
import java.util.Locale
internal class PerfMonitorOverlayViewManager(
private val contextSupplier: Supplier<Context?>,
private val inspectorTarget: PerfMonitorInspectorTargetBinding?,
) : PerfMonitorOverlayManager, PerfMonitorUpdateListener {
private var initialized: Boolean = false
private var enabled: Boolean = false
private var hasInteractionData: Boolean = false
private var interactionDialog: Dialog? = null
private var buttonDialog: Dialog? = null
private var durationLabel: TextView? = null
private var ttl: Int = 0
private var hideAfterTimeoutHandler: Handler? = null
override fun enable() {
UiThreadUtil.runOnUiThread {
enabled = true
if (hasInteractionData) {
showOverlay()
}
}
}
override fun disable() {
UiThreadUtil.runOnUiThread {
enabled = false
hideOverlay()
}
}
override fun reset() {
UiThreadUtil.runOnUiThread {
hasInteractionData = false
hideOverlay()
}
}
override fun onRecordingStateChanged(state: TracingState) {
// recordingState = state
// view?.updateRecordingState(state)
}
override fun onNewFocusedEvent(data: PerfMonitorUpdateListener.LongTaskEventData) {
UiThreadUtil.runOnUiThread {
ensureInitialized()
durationLabel?.text = String.format(Locale.US, "%d ms", data.durationMs)
durationLabel?.setTextColor(getDurationHighlightColor(data.responsivenessScore))
hasInteractionData = true
ttl = data.ttl
hideAfterTimeoutHandler?.removeCallbacksAndMessages(null)
if (enabled) {
showOverlay()
// Schedule hiding overlay after ttl milliseconds
if (ttl > 0) {
if (hideAfterTimeoutHandler == null) {
hideAfterTimeoutHandler = Handler(Looper.getMainLooper())
}
hideAfterTimeoutHandler?.postDelayed({ hideOverlay() }, ttl.toLong())
}
}
}
}
private fun ensureInitialized() {
if (initialized) {
return
}
val context = contextSupplier.get() ?: return
DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(context)
createDialog(context)
createButton(context)
initialized = true
}
private fun showOverlay() {
interactionDialog?.show()
buttonDialog?.show()
}
private fun hideOverlay() {
interactionDialog?.hide()
buttonDialog?.hide()
}
private fun createDialog(context: Context) {
val containerLayout = createInnerLayout(context)
val longTaskLabel =
TextView(context).apply {
textSize = TEXT_SIZE_PRIMARY
text = "Long Task"
setTextColor(Color.WHITE)
typeface = TYPEFACE_BOLD
}
durationLabel =
TextView(context).apply {
textSize = TEXT_SIZE_PRIMARY
setTextColor(COLOR_TEXT_GREEN)
typeface = TYPEFACE_BOLD
}
containerLayout.addView(longTaskLabel)
containerLayout.addView(durationLabel)
val dialog =
createAnchoredDialog(context, dpToPx(140f), dpToPx(16f)).apply {
setContentView(containerLayout)
}
dialog.window?.apply {
attributes =
attributes?.apply {
flags =
flags or
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE or
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
}
}
this.interactionDialog = dialog
}
fun updateRecordingState(state: TracingState) {}
private fun createButton(context: Context) {
val buttonInner = createInnerLayout(context)
buttonInner.addView(
TextView(context).apply {
text = "Analyze"
textSize = TEXT_SIZE_PRIMARY
setTextColor(Color.WHITE)
typeface = TYPEFACE_BOLD
}
)
buttonInner.addView(
TextView(context).apply {
text = "cmd + A"
textSize = TEXT_SIZE_ACCESSORY
setTextColor(Color.WHITE)
alpha = 0.7f
typeface = TYPEFACE_BOLD
}
)
val buttonView =
LinearLayout(context).apply {
orientation = LinearLayout.VERTICAL
setPadding(
dpToPx(8f).toInt(),
dpToPx(16f).toInt(),
dpToPx(16f).toInt(),
dpToPx(8f).toInt(),
)
addView(buttonInner)
setOnClickListener { inspectorTarget?.pauseAndAnalyzeBackgroundTrace() }
}
val dialog =
createAnchoredDialog(context, dpToPx(0f), dpToPx(0f)).apply { setContentView(buttonView) }
dialog.window?.apply {
attributes =
attributes?.apply { flags = flags or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE }
}
this.buttonDialog = dialog
}
private fun createAnchoredDialog(context: Context, offsetX: Float, offsetY: Float): Dialog {
val dialog =
Dialog(context, R.style.NoAnimationDialog).apply {
requestWindowFeature(Window.FEATURE_NO_TITLE)
window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
window?.setDimAmount(0f)
setCancelable(false)
}
dialog.window?.apply {
attributes =
attributes?.apply {
width = WindowManager.LayoutParams.WRAP_CONTENT
height = WindowManager.LayoutParams.WRAP_CONTENT
gravity = Gravity.TOP or Gravity.END
x = offsetX.toInt()
y = offsetY.toInt()
}
}
dialog.window?.decorView?.let { decorView ->
ViewCompat.setOnApplyWindowInsetsListener(decorView) { view, windowInsets ->
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
val layoutParams = (view.layoutParams as WindowManager.LayoutParams)
layoutParams.y = insets.top + offsetY.toInt()
dialog.window?.attributes = layoutParams
WindowInsetsCompat.CONSUMED
}
}
return dialog
}
private fun createInnerLayout(context: Context): LinearLayout {
return LinearLayout(context).apply {
orientation = LinearLayout.HORIZONTAL
gravity = Gravity.CENTER_VERTICAL
val paddingHorizontal = dpToPx(14f).toInt()
val paddingVertical = dpToPx(8f).toInt()
setPadding(paddingHorizontal, paddingVertical, paddingHorizontal, paddingVertical)
layoutParams =
LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT,
)
background =
GradientDrawable().apply {
shape = GradientDrawable.RECTANGLE
setColor(Color.BLACK)
cornerRadius = dpToPx(14.5f)
alpha = (0.8 * 255).toInt()
setStroke(dpToPx(1f).toInt(), COLOR_OVERLAY_BORDER)
}
showDividers = LinearLayout.SHOW_DIVIDER_MIDDLE
dividerDrawable =
object : ColorDrawable(Color.TRANSPARENT) {
override fun getIntrinsicWidth(): Int = dpToPx(8f).toInt()
}
}
}
private fun getDurationHighlightColor(responsivenessScore: Int): Int {
return when (responsivenessScore) {
3 -> COLOR_TEXT_RED
2 -> COLOR_TEXT_YELLOW
else -> COLOR_TEXT_GREEN
}
}
private fun dpToPx(dp: Float): Float = PixelUtil.toPixelFromDIP(dp)
companion object {
private val COLOR_TEXT_GREEN = Color.parseColor("#4AEB2F")
private val COLOR_TEXT_YELLOW = Color.parseColor("#FFAA00")
private val COLOR_TEXT_RED = Color.parseColor("#FF0000")
private val COLOR_OVERLAY_BORDER = Color.parseColor("#6C6C6C")
private val TEXT_SIZE_PRIMARY = 13f
private val TEXT_SIZE_ACCESSORY = 9f
private val TYPEFACE_BOLD = Typeface.create("sans-serif", Typeface.BOLD)
}
}
@@ -0,0 +1,20 @@
/*
* 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.devsupport.interfaces
/** [Experimental] Interface to manage the V2 Perf Monitor overlay. */
internal interface PerfMonitorOverlayManager {
/** Enable the Perf Monitor overlay. Will be shown when updates are received. */
public fun enable()
/** Disable the Perf Monitor overlay. Will remain hidden when updates are received. */
public fun disable()
/** Reset the Perf Monitor overlay, e.g. after a reload. */
public fun reset()
}
@@ -7,21 +7,13 @@
package com.facebook.react.devsupport.perfmonitor
import com.facebook.react.devsupport.interfaces.TracingState
/**
* [Experimental] Interface implemented by [com.facebook.react.runtime.ReactHostInspectorTarget]
* exposing actions for the V2 Perf Monitor.
*/
internal interface PerfMonitorInspectorTargetBinding {
/** Get the current CDP or background performance tracing state. */
public fun getTracingState(): TracingState
/**
* Attempt to pause the current background performance trace, and open in DevTools. Returns true
* if there is an active session that can display the trace, false otherwise.
*/
public fun pauseAndAnalyzeBackgroundTrace(): Boolean
/** Attempt to pause the current background performance trace, and open in DevTools. */
public fun pauseAndAnalyzeBackgroundTrace()
/** Attempt to start a new background performance trace. */
public fun resumeBackgroundTrace()
@@ -1,83 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.react.devsupport.perfmonitor
import android.content.Context
import com.facebook.react.bridge.UiThreadUtil
import com.facebook.react.devsupport.interfaces.TracingState
import javax.inject.Provider
internal class PerfMonitorOverlayManager(
private val devHelper: PerfMonitorDevHelper,
private val contextProvider: Provider<Context?>,
private val onRequestOpenDevTools: () -> Unit,
) : PerfMonitorUpdateListener {
private var enabled: Boolean = false
private var initialized: Boolean = false
private var view: PerfMonitorOverlayView? = null
private var tracingState: TracingState = TracingState.ENABLEDINCDPMODE
private fun init() {
if (initialized || !enabled) {
return
}
UiThreadUtil.runOnUiThread {
val context = contextProvider.get() ?: return@runOnUiThread
view = PerfMonitorOverlayView(context, ::handleRecordingButtonPress)
// Start background tracing
devHelper.inspectorTarget?.resumeBackgroundTrace()
view?.show()
initialized = true
}
}
/** Enable the Perf Monitor overlay. Will be shown when updates are received. */
fun enable() {
enabled = true
init()
}
/** Disable the Perf Monitor overlay. Will remain hidden when updates are received. */
fun disable() {
UiThreadUtil.runOnUiThread { view?.hide() }
view = null
enabled = false
}
/** Reset the Perf Monitor overlay, e.g. after a reload. */
fun reset() {
// Update with current recording state
onRecordingStateChanged(
devHelper.inspectorTarget?.getTracingState() ?: TracingState.ENABLEDINCDPMODE
)
}
override fun onRecordingStateChanged(state: TracingState) {
tracingState = state
view?.updateRecordingState(state)
}
private fun handleRecordingButtonPress() {
when (tracingState) {
TracingState.ENABLEDINBACKGROUNDMODE -> {
devHelper.inspectorTarget?.let {
if (!it.pauseAndAnalyzeBackgroundTrace()) {
onRequestOpenDevTools()
}
}
}
TracingState.DISABLED -> {
devHelper.inspectorTarget?.resumeBackgroundTrace()
}
TracingState.ENABLEDINCDPMODE -> Unit
}
}
}
@@ -1,186 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.react.devsupport.perfmonitor
import android.app.Dialog
import android.content.Context
import android.graphics.Color
import android.graphics.Typeface
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.GradientDrawable
import android.view.Gravity
import android.view.Window
import android.view.WindowManager
import android.widget.LinearLayout
import android.widget.TextView
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.facebook.react.R
import com.facebook.react.devsupport.interfaces.TracingState
import com.facebook.react.uimanager.DisplayMetricsHolder
import com.facebook.react.uimanager.PixelUtil
internal class PerfMonitorOverlayView(
private val context: Context,
private val onButtonPress: () -> Unit,
) {
private val dialog: Dialog
private lateinit var statusLabel: TextView
private lateinit var tooltipLabel: TextView
private lateinit var statusIndicator: TextView
init {
DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(context)
dialog = createToolbarDialog()
}
fun show() {
dialog.show()
}
fun hide() {
dialog.hide()
}
fun updateRecordingState(state: TracingState) {
if (state == TracingState.ENABLEDINCDPMODE) {
dialog.hide()
return
}
if (state == TracingState.ENABLEDINBACKGROUNDMODE) {
(statusIndicator.background as GradientDrawable).setColor(Color.RED)
statusLabel.text = "Background Profiling Active"
tooltipLabel.text = "Press ☰ to open"
} else {
(statusIndicator.background as GradientDrawable).setColor(Color.GRAY)
statusLabel.text = "Background Profiling Stopped"
tooltipLabel.text = "Press ☰ to restart"
}
dialog.show()
}
private fun createToolbarDialog(): Dialog {
statusIndicator =
TextView(context).apply {
width = dpToPx(12f).toInt()
height = dpToPx(12f).toInt()
background =
GradientDrawable().apply {
shape = GradientDrawable.OVAL
setColor(Color.RED)
}
}
val textContainer =
LinearLayout(context).apply {
orientation = LinearLayout.VERTICAL
layoutParams =
LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT,
)
}
statusLabel =
TextView(context).apply {
textSize = TEXT_SIZE_PRIMARY
setTextColor(Color.WHITE)
typeface = TYPEFACE_BOLD
}
tooltipLabel =
TextView(context).apply {
textSize = TEXT_SIZE_ACCESSORY
setTextColor(Color.WHITE)
typeface = TYPEFACE_BOLD
}
textContainer.addView(statusLabel)
textContainer.addView(tooltipLabel)
val containerLayout = createInnerLayout()
containerLayout.setOnClickListener { onButtonPress() }
containerLayout.addView(statusIndicator)
containerLayout.addView(textContainer)
val dialog =
createAnchoredDialog(dpToPx(12f), dpToPx(12f)).apply { setContentView(containerLayout) }
dialog.window?.apply {
attributes =
attributes?.apply { flags = flags or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE }
}
return dialog
}
private fun createAnchoredDialog(offsetX: Float, offsetY: Float): Dialog {
val dialog =
Dialog(context, R.style.NoAnimationDialog).apply {
requestWindowFeature(Window.FEATURE_NO_TITLE)
window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
window?.setDimAmount(0f)
setCancelable(false)
}
dialog.window?.apply {
attributes =
attributes?.apply {
width = WindowManager.LayoutParams.WRAP_CONTENT
height = WindowManager.LayoutParams.WRAP_CONTENT
gravity = Gravity.TOP or Gravity.END
x = offsetX.toInt()
y = offsetY.toInt()
}
}
dialog.window?.decorView?.let { decorView ->
ViewCompat.setOnApplyWindowInsetsListener(decorView) { view, windowInsets ->
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
val layoutParams = (view.layoutParams as WindowManager.LayoutParams)
layoutParams.y = insets.top + offsetY.toInt()
dialog.window?.attributes = layoutParams
WindowInsetsCompat.CONSUMED
}
}
return dialog
}
private fun createInnerLayout(): LinearLayout {
return LinearLayout(context).apply {
orientation = LinearLayout.HORIZONTAL
gravity = Gravity.CENTER_VERTICAL
val paddingHorizontal = dpToPx(14f).toInt()
val paddingVertical = dpToPx(7f).toInt()
setPadding(paddingHorizontal, paddingVertical, paddingHorizontal, paddingVertical)
layoutParams =
LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT,
)
background =
GradientDrawable().apply {
shape = GradientDrawable.RECTANGLE
setColor(Color.BLACK)
cornerRadius = dpToPx(14.5f)
alpha = (0.8 * 255).toInt()
setStroke(dpToPx(1f).toInt(), COLOR_OVERLAY_BORDER)
}
showDividers = LinearLayout.SHOW_DIVIDER_MIDDLE
dividerDrawable =
object : ColorDrawable(Color.TRANSPARENT) {
override fun getIntrinsicWidth(): Int = dpToPx(8f).toInt()
}
}
}
private fun dpToPx(dp: Float): Float = PixelUtil.toPixelFromDIP(dp)
companion object {
private val COLOR_OVERLAY_BORDER = Color.parseColor("#6C6C6C")
private val TEXT_SIZE_PRIMARY = 12f
private val TEXT_SIZE_ACCESSORY = 10f
private val TYPEFACE_BOLD = Typeface.create("sans-serif", Typeface.BOLD)
}
}
@@ -10,6 +10,15 @@ import com.facebook.react.devsupport.interfaces.TracingState
/** [Experimental] An interface for subscribing to updates for the V2 Perf Monitor. */
internal interface PerfMonitorUpdateListener {
data class LongTaskEventData(
val durationMs: Int,
val responsivenessScore: Int,
val ttl: Int,
)
/** Called when a new active performance event should be displayed. */
fun onNewFocusedEvent(data: LongTaskEventData)
/** Called when the recording state of the background performance trace has changed. */
fun onRecordingStateChanged(state: TracingState)
}
@@ -99,6 +99,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -737,17 +738,11 @@ public class FabricUIManager
* vertical insets.
*/
private long getEncodedScreenSizeWithoutVerticalInsets(int surfaceId) {
ThemedReactContext context =
mMountingManager
.getSurfaceManagerEnforced(surfaceId, "getEncodedScreenSizeWithoutVerticalInsets")
.getContext();
if (context == null) {
FLog.w(TAG, "Couldn't get context from SurfaceMountingManager for surfaceId %d", surfaceId);
return 0;
} else {
return DisplayMetricsHolder.getEncodedScreenSizeWithoutVerticalInsets(
context.getCurrentActivity());
}
SurfaceMountingManager surfaceMountingManager = mMountingManager.getSurfaceManager(surfaceId);
Objects.requireNonNull(surfaceMountingManager);
ThemedReactContext context = Objects.requireNonNull(surfaceMountingManager.getContext());
return DisplayMetricsHolder.getEncodedScreenSizeWithoutVerticalInsets(
context.getCurrentActivity());
}
@Override
@@ -796,8 +791,7 @@ public class FabricUIManager
@Override
public void execute(MountingManager mountingManager) {
try {
mountingManager.storeSynchronousMountPropsOverride(reactTag, props);
mountingManager.updatePropsSynchronously(reactTag, props);
mountingManager.updateProps(reactTag, props);
} catch (Exception ex) {
// TODO T42943890: Fix animations in Fabric and remove this try/catch?
// There might always be race conditions between surface teardown and
@@ -265,23 +265,13 @@ internal class MountingManager(
}
@UiThread
fun storeSynchronousMountPropsOverride(reactTag: Int, props: ReadableMap?) {
fun updateProps(reactTag: Int, props: ReadableMap?) {
assertOnUiThread()
if (props == null) {
return
}
getSurfaceManagerForViewEnforced(reactTag).storeSynchronousMountPropsOverride(reactTag, props)
}
@UiThread
fun updatePropsSynchronously(reactTag: Int, props: ReadableMap?) {
assertOnUiThread()
if (props == null) {
return
}
getSurfaceManagerForViewEnforced(reactTag).updatePropsSynchronously(reactTag, props)
getSurfaceManagerForViewEnforced(reactTag).updateProps(reactTag, props)
}
/**
@@ -27,14 +27,10 @@ import com.facebook.react.bridge.ReactNoCrashSoftException;
import com.facebook.react.bridge.ReactSoftExceptionLogger;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableType;
import com.facebook.react.bridge.RetryableMountingLayerException;
import com.facebook.react.bridge.SoftAssertions;
import com.facebook.react.bridge.UiThreadUtil;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.WritableNativeArray;
import com.facebook.react.bridge.WritableNativeMap;
import com.facebook.react.common.annotations.UnstableReactNativeAPI;
import com.facebook.react.common.build.ReactBuildConfig;
import com.facebook.react.common.mapbuffer.MapBuffer;
@@ -57,10 +53,7 @@ import com.facebook.react.uimanager.ViewManagerRegistry;
import com.facebook.react.uimanager.events.EventCategoryDef;
import com.facebook.systrace.Systrace;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
@@ -103,11 +96,6 @@ public class SurfaceMountingManager {
// This is null *until* StopSurface is called.
private SparseArrayCompat<Object> mTagSetForStoppedSurface;
// This is to make sure direct manipulation result will not be overridden by React update.
@ThreadConfined(UI)
private final SparseArrayCompat<Map<String, Object>> mTagToSynchronousMountProps =
new SparseArrayCompat<>();
private final int mSurfaceId;
public SurfaceMountingManager(
@@ -694,110 +682,13 @@ public class SurfaceMountingManager {
}
}
private static void overridePropsReadableMap(
Map<String, Object> patchMap, WritableMap outputReadableMap) {
for (Map.Entry<String, Object> entry : patchMap.entrySet()) {
String propKey = entry.getKey();
if (outputReadableMap.hasKey(propKey)) {
Object propValue = entry.getValue();
if (propKey.equals("transform")) {
assert (outputReadableMap.getType(propKey) == ReadableType.Array
&& propValue instanceof ArrayList);
WritableArray array = new WritableNativeArray();
for (Object item : (ArrayList<?>) propValue) {
if (item instanceof HashMap) {
WritableNativeMap itemMap = new WritableNativeMap();
for (Map.Entry<String, Object> itemEntry :
((HashMap<String, Object>) item).entrySet()) {
if (itemEntry.getValue() instanceof String) {
itemMap.putString(itemEntry.getKey(), (String) itemEntry.getValue());
} else if (itemEntry.getValue() instanceof Number) {
itemMap.putDouble(
itemEntry.getKey(), ((Number) itemEntry.getValue()).doubleValue());
}
}
array.pushMap(itemMap);
}
}
outputReadableMap.putArray(propKey, array);
} else if (propKey.equals("opacity")) {
assert (outputReadableMap.getType(propKey) == ReadableType.Number
&& propValue instanceof Number);
outputReadableMap.putDouble(propKey, ((Number) propValue).doubleValue());
}
}
}
}
private static Map<String, Object> getHashMapFromPropsReadableMap(ReadableMap readableMap) {
HashMap<String, Object> outputMap = new HashMap<>();
Iterator<Map.Entry<String, Object>> iter = readableMap.getEntryIterator();
while (iter.hasNext()) {
Map.Entry<String, Object> entry = iter.next();
String propKey = entry.getKey();
Object propValue = entry.getValue();
if (propKey.equals("transform") && propValue instanceof ReadableArray) {
ArrayList<HashMap<String, Object>> arrayList = new ArrayList<>();
for (int i = 0; i < ((ReadableArray) propValue).size(); i++) {
ReadableMap map = ((ReadableArray) propValue).getMap(i);
if (map != null) {
arrayList.add(map.toHashMap());
}
}
outputMap.put(propKey, arrayList);
} else if (propKey.equals("opacity") && propValue instanceof Number) {
outputMap.put(propKey, ((Number) propValue).doubleValue());
}
}
return outputMap;
}
public void storeSynchronousMountPropsOverride(int reactTag, ReadableMap props) {
if (ReactNativeFeatureFlags.overrideBySynchronousMountPropsAtMountingAndroid()) {
Map<String, Object> propsMap = getHashMapFromPropsReadableMap(props);
if (mTagToSynchronousMountProps.containsKey(reactTag)) {
Map<String, Object> mergedPropsMap =
Assertions.assertNotNull(mTagToSynchronousMountProps.get(reactTag));
mergedPropsMap.putAll(propsMap);
mTagToSynchronousMountProps.put(reactTag, mergedPropsMap);
} else {
mTagToSynchronousMountProps.put(reactTag, propsMap);
}
}
}
public void updatePropsSynchronously(int reactTag, ReadableMap props) {
updateProps(reactTag, props, true);
}
public void updateProps(int reactTag, ReadableMap props) {
updateProps(reactTag, props, false);
}
@UiThread
private void updateProps(
int reactTag, ReadableMap props, Boolean shouldSkipSynchronousMountPropsOverride) {
if (isStopped()) {
return;
}
ViewState viewState = getViewState(reactTag);
if (ReactNativeFeatureFlags.overrideBySynchronousMountPropsAtMountingAndroid()
&& !shouldSkipSynchronousMountPropsOverride
&& mTagToSynchronousMountProps.containsKey(reactTag)) {
WritableMap modifiedProps = new WritableNativeMap();
modifiedProps.merge(props);
Map<String, Object> directPropsMap =
Assertions.assertNotNull(mTagToSynchronousMountProps.get(reactTag));
overridePropsReadableMap(directPropsMap, modifiedProps);
viewState.mCurrentProps = new ReactStylesDiffMap(modifiedProps);
} else {
viewState.mCurrentProps = new ReactStylesDiffMap(props);
}
viewState.mCurrentProps = new ReactStylesDiffMap(props);
View view = viewState.mView;
if (view == null) {
@@ -1166,11 +1057,6 @@ public class SurfaceMountingManager {
return;
}
if (ReactNativeFeatureFlags.overrideBySynchronousMountPropsAtMountingAndroid()
&& mTagToSynchronousMountProps.containsKey(reactTag)) {
mTagToSynchronousMountProps.remove(reactTag);
}
ViewState viewState = getNullableViewState(reactTag);
if (viewState == null) {
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<f089964c958dfcac00f83c3371ccbefc>>
* @generated SignedSource<<92a6edded037a504fc1c2c8ae88deae1>>
*/
/**
@@ -90,12 +90,6 @@ public object ReactNativeFeatureFlags {
@JvmStatic
public fun enableAccumulatedUpdatesInRawPropsAndroid(): Boolean = accessor.enableAccumulatedUpdatesInRawPropsAndroid()
/**
* Enables linear text rendering on Android wherever subpixel text rendering is enabled
*/
@JvmStatic
public fun enableAndroidLinearText(): Boolean = accessor.enableAndroidLinearText()
/**
* Enables various optimizations throughout the path of measuring text on Android.
*/
@@ -252,12 +246,6 @@ public object ReactNativeFeatureFlags {
@JvmStatic
public fun enableResourceTimingAPI(): Boolean = accessor.enableResourceTimingAPI()
/**
* When enabled, it will use SwiftUI for filter effects like blur on iOS.
*/
@JvmStatic
public fun enableSwiftUIBasedFilters(): Boolean = accessor.enableSwiftUIBasedFilters()
/**
* Enables View Culling: as soon as a view goes off screen, it can be reused anywhere in the UI and pieced together with other items to create new UI elements.
*/
@@ -312,12 +300,6 @@ public object ReactNativeFeatureFlags {
@JvmStatic
public fun enableVirtualViewWindowFocusDetection(): Boolean = accessor.enableVirtualViewWindowFocusDetection()
/**
* Enable Web Performance APIs (Performance Timeline, User Timings, etc.) by default.
*/
@JvmStatic
public fun enableWebPerformanceAPIsByDefault(): Boolean = accessor.enableWebPerformanceAPIsByDefault()
/**
* Uses the default event priority instead of the discreet event priority by default when dispatching events from Fabric to React.
*/
@@ -342,12 +324,6 @@ public object ReactNativeFeatureFlags {
@JvmStatic
public fun hideOffscreenVirtualViewsOnIOS(): Boolean = accessor.hideOffscreenVirtualViewsOnIOS()
/**
* Override props at mounting with synchronously mounted (i.e. direct manipulation) props from Native Animated.
*/
@JvmStatic
public fun overrideBySynchronousMountPropsAtMountingAndroid(): Boolean = accessor.overrideBySynchronousMountPropsAtMountingAndroid()
/**
* Enable the V2 in-app Performance Monitor. This flag is global and should not be changed across React Host lifetimes.
*/
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<912dec895495052328e7e52b94a6738a>>
* @generated SignedSource<<ebbc6602fc8e3fb4c510bbd47361a7f0>>
*/
/**
@@ -30,7 +30,6 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
private var disableTextLayoutManagerCacheAndroidCache: Boolean? = null
private var enableAccessibilityOrderCache: Boolean? = null
private var enableAccumulatedUpdatesInRawPropsAndroidCache: Boolean? = null
private var enableAndroidLinearTextCache: Boolean? = null
private var enableAndroidTextMeasurementOptimizationsCache: Boolean? = null
private var enableBridgelessArchitectureCache: Boolean? = null
private var enableCppPropsIteratorSetterCache: Boolean? = null
@@ -57,7 +56,6 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
private var enablePreparedTextLayoutCache: Boolean? = null
private var enablePropsUpdateReconciliationAndroidCache: Boolean? = null
private var enableResourceTimingAPICache: Boolean? = null
private var enableSwiftUIBasedFiltersCache: Boolean? = null
private var enableViewCullingCache: Boolean? = null
private var enableViewRecyclingCache: Boolean? = null
private var enableViewRecyclingForImageCache: Boolean? = null
@@ -67,12 +65,10 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
private var enableVirtualViewDebugFeaturesCache: Boolean? = null
private var enableVirtualViewRenderStateCache: Boolean? = null
private var enableVirtualViewWindowFocusDetectionCache: Boolean? = null
private var enableWebPerformanceAPIsByDefaultCache: Boolean? = null
private var fixMappingOfEventPrioritiesBetweenFabricAndReactCache: Boolean? = null
private var fuseboxEnabledReleaseCache: Boolean? = null
private var fuseboxNetworkInspectionEnabledCache: Boolean? = null
private var hideOffscreenVirtualViewsOnIOSCache: Boolean? = null
private var overrideBySynchronousMountPropsAtMountingAndroidCache: Boolean? = null
private var perfMonitorV2EnabledCache: Boolean? = null
private var preparedTextCacheSizeCache: Double? = null
private var preventShadowTreeCommitExhaustionCache: Boolean? = null
@@ -184,15 +180,6 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
return cached
}
override fun enableAndroidLinearText(): Boolean {
var cached = enableAndroidLinearTextCache
if (cached == null) {
cached = ReactNativeFeatureFlagsCxxInterop.enableAndroidLinearText()
enableAndroidLinearTextCache = cached
}
return cached
}
override fun enableAndroidTextMeasurementOptimizations(): Boolean {
var cached = enableAndroidTextMeasurementOptimizationsCache
if (cached == null) {
@@ -427,15 +414,6 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
return cached
}
override fun enableSwiftUIBasedFilters(): Boolean {
var cached = enableSwiftUIBasedFiltersCache
if (cached == null) {
cached = ReactNativeFeatureFlagsCxxInterop.enableSwiftUIBasedFilters()
enableSwiftUIBasedFiltersCache = cached
}
return cached
}
override fun enableViewCulling(): Boolean {
var cached = enableViewCullingCache
if (cached == null) {
@@ -517,15 +495,6 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
return cached
}
override fun enableWebPerformanceAPIsByDefault(): Boolean {
var cached = enableWebPerformanceAPIsByDefaultCache
if (cached == null) {
cached = ReactNativeFeatureFlagsCxxInterop.enableWebPerformanceAPIsByDefault()
enableWebPerformanceAPIsByDefaultCache = cached
}
return cached
}
override fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean {
var cached = fixMappingOfEventPrioritiesBetweenFabricAndReactCache
if (cached == null) {
@@ -562,15 +531,6 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
return cached
}
override fun overrideBySynchronousMountPropsAtMountingAndroid(): Boolean {
var cached = overrideBySynchronousMountPropsAtMountingAndroidCache
if (cached == null) {
cached = ReactNativeFeatureFlagsCxxInterop.overrideBySynchronousMountPropsAtMountingAndroid()
overrideBySynchronousMountPropsAtMountingAndroidCache = cached
}
return cached
}
override fun perfMonitorV2Enabled(): Boolean {
var cached = perfMonitorV2EnabledCache
if (cached == null) {
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<ba1e53d93b9fdaf298a034543bc44a57>>
* @generated SignedSource<<4410628511f112f3eef22434a05fa757>>
*/
/**
@@ -48,8 +48,6 @@ public object ReactNativeFeatureFlagsCxxInterop {
@DoNotStrip @JvmStatic public external fun enableAccumulatedUpdatesInRawPropsAndroid(): Boolean
@DoNotStrip @JvmStatic public external fun enableAndroidLinearText(): Boolean
@DoNotStrip @JvmStatic public external fun enableAndroidTextMeasurementOptimizations(): Boolean
@DoNotStrip @JvmStatic public external fun enableBridgelessArchitecture(): Boolean
@@ -102,8 +100,6 @@ public object ReactNativeFeatureFlagsCxxInterop {
@DoNotStrip @JvmStatic public external fun enableResourceTimingAPI(): Boolean
@DoNotStrip @JvmStatic public external fun enableSwiftUIBasedFilters(): Boolean
@DoNotStrip @JvmStatic public external fun enableViewCulling(): Boolean
@DoNotStrip @JvmStatic public external fun enableViewRecycling(): Boolean
@@ -122,8 +118,6 @@ public object ReactNativeFeatureFlagsCxxInterop {
@DoNotStrip @JvmStatic public external fun enableVirtualViewWindowFocusDetection(): Boolean
@DoNotStrip @JvmStatic public external fun enableWebPerformanceAPIsByDefault(): Boolean
@DoNotStrip @JvmStatic public external fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean
@DoNotStrip @JvmStatic public external fun fuseboxEnabledRelease(): Boolean
@@ -132,8 +126,6 @@ public object ReactNativeFeatureFlagsCxxInterop {
@DoNotStrip @JvmStatic public external fun hideOffscreenVirtualViewsOnIOS(): Boolean
@DoNotStrip @JvmStatic public external fun overrideBySynchronousMountPropsAtMountingAndroid(): Boolean
@DoNotStrip @JvmStatic public external fun perfMonitorV2Enabled(): Boolean
@DoNotStrip @JvmStatic public external fun preparedTextCacheSize(): Double
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<7601cbcde75ff19ef0fe67f6faef2549>>
* @generated SignedSource<<411732d441bacbef37c3474b9041202c>>
*/
/**
@@ -43,8 +43,6 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
override fun enableAccumulatedUpdatesInRawPropsAndroid(): Boolean = false
override fun enableAndroidLinearText(): Boolean = false
override fun enableAndroidTextMeasurementOptimizations(): Boolean = false
override fun enableBridgelessArchitecture(): Boolean = false
@@ -97,8 +95,6 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
override fun enableResourceTimingAPI(): Boolean = false
override fun enableSwiftUIBasedFilters(): Boolean = false
override fun enableViewCulling(): Boolean = false
override fun enableViewRecycling(): Boolean = false
@@ -117,8 +113,6 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
override fun enableVirtualViewWindowFocusDetection(): Boolean = false
override fun enableWebPerformanceAPIsByDefault(): Boolean = false
override fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean = false
override fun fuseboxEnabledRelease(): Boolean = false
@@ -127,8 +121,6 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
override fun hideOffscreenVirtualViewsOnIOS(): Boolean = false
override fun overrideBySynchronousMountPropsAtMountingAndroid(): Boolean = false
override fun perfMonitorV2Enabled(): Boolean = false
override fun preparedTextCacheSize(): Double = 200.0
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<3a13f8e35423b634ed4ef46fbac3c1e9>>
* @generated SignedSource<<2f65e0e9066a8c2c35c44ea7c73dbedc>>
*/
/**
@@ -34,7 +34,6 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
private var disableTextLayoutManagerCacheAndroidCache: Boolean? = null
private var enableAccessibilityOrderCache: Boolean? = null
private var enableAccumulatedUpdatesInRawPropsAndroidCache: Boolean? = null
private var enableAndroidLinearTextCache: Boolean? = null
private var enableAndroidTextMeasurementOptimizationsCache: Boolean? = null
private var enableBridgelessArchitectureCache: Boolean? = null
private var enableCppPropsIteratorSetterCache: Boolean? = null
@@ -61,7 +60,6 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
private var enablePreparedTextLayoutCache: Boolean? = null
private var enablePropsUpdateReconciliationAndroidCache: Boolean? = null
private var enableResourceTimingAPICache: Boolean? = null
private var enableSwiftUIBasedFiltersCache: Boolean? = null
private var enableViewCullingCache: Boolean? = null
private var enableViewRecyclingCache: Boolean? = null
private var enableViewRecyclingForImageCache: Boolean? = null
@@ -71,12 +69,10 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
private var enableVirtualViewDebugFeaturesCache: Boolean? = null
private var enableVirtualViewRenderStateCache: Boolean? = null
private var enableVirtualViewWindowFocusDetectionCache: Boolean? = null
private var enableWebPerformanceAPIsByDefaultCache: Boolean? = null
private var fixMappingOfEventPrioritiesBetweenFabricAndReactCache: Boolean? = null
private var fuseboxEnabledReleaseCache: Boolean? = null
private var fuseboxNetworkInspectionEnabledCache: Boolean? = null
private var hideOffscreenVirtualViewsOnIOSCache: Boolean? = null
private var overrideBySynchronousMountPropsAtMountingAndroidCache: Boolean? = null
private var perfMonitorV2EnabledCache: Boolean? = null
private var preparedTextCacheSizeCache: Double? = null
private var preventShadowTreeCommitExhaustionCache: Boolean? = null
@@ -198,16 +194,6 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
return cached
}
override fun enableAndroidLinearText(): Boolean {
var cached = enableAndroidLinearTextCache
if (cached == null) {
cached = currentProvider.enableAndroidLinearText()
accessedFeatureFlags.add("enableAndroidLinearText")
enableAndroidLinearTextCache = cached
}
return cached
}
override fun enableAndroidTextMeasurementOptimizations(): Boolean {
var cached = enableAndroidTextMeasurementOptimizationsCache
if (cached == null) {
@@ -468,16 +454,6 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
return cached
}
override fun enableSwiftUIBasedFilters(): Boolean {
var cached = enableSwiftUIBasedFiltersCache
if (cached == null) {
cached = currentProvider.enableSwiftUIBasedFilters()
accessedFeatureFlags.add("enableSwiftUIBasedFilters")
enableSwiftUIBasedFiltersCache = cached
}
return cached
}
override fun enableViewCulling(): Boolean {
var cached = enableViewCullingCache
if (cached == null) {
@@ -568,16 +544,6 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
return cached
}
override fun enableWebPerformanceAPIsByDefault(): Boolean {
var cached = enableWebPerformanceAPIsByDefaultCache
if (cached == null) {
cached = currentProvider.enableWebPerformanceAPIsByDefault()
accessedFeatureFlags.add("enableWebPerformanceAPIsByDefault")
enableWebPerformanceAPIsByDefaultCache = cached
}
return cached
}
override fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean {
var cached = fixMappingOfEventPrioritiesBetweenFabricAndReactCache
if (cached == null) {
@@ -618,16 +584,6 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
return cached
}
override fun overrideBySynchronousMountPropsAtMountingAndroid(): Boolean {
var cached = overrideBySynchronousMountPropsAtMountingAndroidCache
if (cached == null) {
cached = currentProvider.overrideBySynchronousMountPropsAtMountingAndroid()
accessedFeatureFlags.add("overrideBySynchronousMountPropsAtMountingAndroid")
overrideBySynchronousMountPropsAtMountingAndroidCache = cached
}
return cached
}
override fun perfMonitorV2Enabled(): Boolean {
var cached = perfMonitorV2EnabledCache
if (cached == null) {
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<4464982256b8ce543d9235fccbf67054>>
* @generated SignedSource<<f82b5905d822f8009c054a9443f86e39>>
*/
/**
@@ -27,8 +27,6 @@ public open class ReactNativeFeatureFlagsOverrides_RNOSS_Canary_Android : ReactN
override fun enableFabricRenderer(): Boolean = true
override fun enableWebPerformanceAPIsByDefault(): Boolean = true
override fun useNativeViewConfigsInBridgelessMode(): Boolean = true
override fun useTurboModuleInterop(): Boolean = true
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<143b568248e68033efaefc3f178ff6db>>
* @generated SignedSource<<e97601660cfd4f614ac934ba20ca4635>>
*/
/**
@@ -43,8 +43,6 @@ public interface ReactNativeFeatureFlagsProvider {
@DoNotStrip public fun enableAccumulatedUpdatesInRawPropsAndroid(): Boolean
@DoNotStrip public fun enableAndroidLinearText(): Boolean
@DoNotStrip public fun enableAndroidTextMeasurementOptimizations(): Boolean
@DoNotStrip public fun enableBridgelessArchitecture(): Boolean
@@ -97,8 +95,6 @@ public interface ReactNativeFeatureFlagsProvider {
@DoNotStrip public fun enableResourceTimingAPI(): Boolean
@DoNotStrip public fun enableSwiftUIBasedFilters(): Boolean
@DoNotStrip public fun enableViewCulling(): Boolean
@DoNotStrip public fun enableViewRecycling(): Boolean
@@ -117,8 +113,6 @@ public interface ReactNativeFeatureFlagsProvider {
@DoNotStrip public fun enableVirtualViewWindowFocusDetection(): Boolean
@DoNotStrip public fun enableWebPerformanceAPIsByDefault(): Boolean
@DoNotStrip public fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean
@DoNotStrip public fun fuseboxEnabledRelease(): Boolean
@@ -127,8 +121,6 @@ public interface ReactNativeFeatureFlagsProvider {
@DoNotStrip public fun hideOffscreenVirtualViewsOnIOS(): Boolean
@DoNotStrip public fun overrideBySynchronousMountPropsAtMountingAndroid(): Boolean
@DoNotStrip public fun perfMonitorV2Enabled(): Boolean
@DoNotStrip public fun preparedTextCacheSize(): Double
@@ -310,8 +310,8 @@ public open class JavaTimerManager(
}
}
}
timersToCall?.let { timers ->
javaScriptTimerExecutor.callTimers(timers)
timersToCall?.let {
javaScriptTimerExecutor.callTimers(it)
timersToCall = null
}
reactChoreographer.postFrameCallback(ReactChoreographer.CallbackType.TIMERS_EVENTS, this)
@@ -55,7 +55,7 @@ public class AndroidInfoModule(reactContext: ReactApplicationContext) :
constants["ServerHost"] =
AndroidInfoHelpers.getServerHost(reactApplicationContext.applicationContext)
}
constants["isTesting"] = "true" == System.getProperty(IS_TESTING)
constants["isTesting"] = "true" == System.getProperty(IS_TESTING) || isRunningScreenshotTest()
val isDisableAnimations = System.getProperty(IS_DISABLE_ANIMATIONS)
if (isDisableAnimations != null) {
constants["isDisableAnimations"] = "true" == isDisableAnimations
@@ -71,6 +71,15 @@ public class AndroidInfoModule(reactContext: ReactApplicationContext) :
override fun invalidate() {}
private fun isRunningScreenshotTest(): Boolean {
return try {
Class.forName("com.facebook.testing.react.screenshots.ReactAppScreenshotTestActivity")
true
} catch (ignored: ClassNotFoundException) {
false
}
}
public companion object {
public const val NAME: String = NativePlatformConstantsAndroidSpec.NAME
private const val IS_TESTING = "IS_TESTING"
@@ -81,6 +81,6 @@ internal class ReactHostImplDevHelper(private val delegate: ReactHostImpl) :
delegate.loadBundle(bundleLoader)
override fun getTracingState(): TracingState {
return delegate.reactHostInspectorTarget?.getTracingState() ?: TracingState.ENABLEDINCDPMODE
return delegate.reactHostInspectorTarget?.tracingState() ?: TracingState.DISABLED
}
}
@@ -37,13 +37,13 @@ internal class ReactHostInspectorTarget(reactHostImpl: ReactHostImpl) :
external fun startBackgroundTrace(): Boolean
external fun stopAndMaybeEmitBackgroundTrace(): Boolean
external fun stopAndStashBackgroundTrace()
external fun stopAndDiscardBackgroundTrace()
external fun tracingStateAsInt(): Int
override fun getTracingState(): TracingState {
fun tracingState(): TracingState {
return TracingState.entries[tracingStateAsInt()]
}
@@ -51,13 +51,11 @@ internal class ReactHostInspectorTarget(reactHostImpl: ReactHostImpl) :
perfMonitorListeners.add(listener)
}
override fun pauseAndAnalyzeBackgroundTrace(): Boolean {
val emitted = stopAndMaybeEmitBackgroundTrace()
override fun pauseAndAnalyzeBackgroundTrace() {
stopAndStashBackgroundTrace()
perfMonitorListeners.forEach { listener ->
listener.onRecordingStateChanged(TracingState.DISABLED)
}
return emitted
}
override fun resumeBackgroundTrace() {
@@ -67,6 +65,18 @@ internal class ReactHostInspectorTarget(reactHostImpl: ReactHostImpl) :
}
}
fun handleNativePerfMonitorMetricUpdate(
longTaskDurationMs: Int,
responsivenessScore: Int,
ttl: Int,
) {
perfMonitorListeners.forEach { listener ->
listener.onNewFocusedEvent(
PerfMonitorUpdateListener.LongTaskEventData(longTaskDurationMs, responsivenessScore, ttl)
)
}
}
override fun close() {
mHybridData.resetNative()
}
@@ -245,15 +245,7 @@ public object ReactScrollViewHelper {
@RequiresApi(Build.VERSION_CODES.N)
@JvmStatic
public fun removeScrollListener(listener: ScrollListener) {
// Avoid using removeIf, only available in API 26+
val toRemove = ArrayList<WeakReference<ScrollListener>>()
for (ref in scrollListeners) {
val target = ref.get()
if (target == null || target == listener) {
toRemove.add(ref)
}
}
scrollListeners.removeAll(toRemove)
scrollListeners.removeIf { it.get() == null || it.get() == listener }
}
@JvmStatic
@@ -264,15 +256,7 @@ public object ReactScrollViewHelper {
@RequiresApi(Build.VERSION_CODES.N)
@JvmStatic
public fun removeLayoutChangeListener(listener: LayoutChangeListener) {
// Avoid using removeIf, only available in API 26+
val toRemove = ArrayList<WeakReference<LayoutChangeListener>>()
for (ref in layoutChangeListeners) {
val target = ref.get()
if (target == null || target == listener) {
toRemove.add(ref)
}
}
layoutChangeListeners.removeAll(toRemove)
layoutChangeListeners.removeIf { it.get() == null || it.get() == listener }
}
/**
@@ -50,13 +50,11 @@ private fun rectsOverlap(rect1: Rect, rect2: Rect): Boolean {
internal class VirtualViewContainerState {
private val prerenderRatio: Double = ReactNativeFeatureFlags.virtualViewPrerenderRatio()
private val hysteresisRatio: Double = ReactNativeFeatureFlags.virtualViewHysteresisRatio()
private val virtualViews: MutableSet<VirtualView> = mutableSetOf()
private val emptyRect: Rect = Rect()
private val visibleRect: Rect = Rect()
private val prerenderRect: Rect = Rect()
private val hysteresisRect: Rect = Rect()
private val onWindowFocusChangeListener =
if (ReactNativeFeatureFlags.enableVirtualViewWindowFocusDetection()) {
ViewTreeObserver.OnWindowFocusChangeListener {
@@ -121,12 +119,11 @@ internal class VirtualViewContainerState {
(-prerenderRect.height() * prerenderRatio).toInt(),
)
val virtualViewsIt =
if (virtualView != null) listOf(virtualView) else virtualViews.toMutableSet()
val virtualViewsIt = if (virtualView != null) listOf(virtualView) else virtualViews
virtualViewsIt.forEach { vv ->
val rect = vv.containerRelativeRect
var mode: VirtualViewMode? = VirtualViewMode.Hidden
var mode = VirtualViewMode.Hidden
var thresholdRect = emptyRect
when {
rectsOverlap(rect, visibleRect) -> {
@@ -145,29 +142,14 @@ internal class VirtualViewContainerState {
mode = VirtualViewMode.Prerender
thresholdRect = prerenderRect
}
else -> {
if (hysteresisRatio > 0.0) {
hysteresisRect.set(prerenderRect)
hysteresisRect.inset(
(-visibleRect.width() * hysteresisRatio).toInt(),
(-visibleRect.height() * hysteresisRatio).toInt(),
)
if (rectsOverlap(rect, hysteresisRect)) {
mode = null
}
}
}
else -> {}
}
if (mode != null) {
vv.onModeChange(mode, thresholdRect)
debugLog(
"updateModes",
{
"virtualView=${vv.virtualViewID} mode=$mode rect=$rect thresholdRect=$thresholdRect"
},
)
}
debugLog(
"updateModes",
{ "virtualView=${vv.virtualViewID} mode=$mode rect=$rect thresholdRect=$thresholdRect" },
)
vv.onModeChange(mode, thresholdRect)
}
}
}

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