Compare commits

...
Author SHA1 Message Date
React Native Bot ed81a8db2b [LOCAL] Bump Podfile.lock 2025-10-21 18:10:08 +00:00
React Native Bot 57ff54492f Release 0.81.5
#publish-packages-to-npm&0.81-stable
2025-10-21 16:14:43 +00:00
Janic Duplessis 34137a82ca Allow extending ReactTextViewManager (#53980) 2025-10-21 15:22:09 +02:00
25harsh cf598f523b fix(iOS): Fix RCTDeviceInfo crash when application.delegate.window is nil (#53645)
Summary:
<!-- Explain the **motivation** for making this change. What existing problem does the pull request solve? -->

Fixes a crash in `RCTDeviceInfo.interfaceOrientationDidChange` when `application.delegate.window` is nil. This crash affects multiple modern iOS app architectures where the traditional window property may not be set:

- **SwiftUI apps using `main`** instead of traditional AppDelegate
- **Brownfield React Native integrations** where the host app manages windows
- **Scene-based lifecycle apps** (iOS 13+) using SceneDelegate
- **Custom window management** setups

**The Problem:**
```
*** Terminating app due to uncaught exception 'NSInvalidArgumentException',
reason: '-[MyApp.AppDelegate window]: unrecognized selector sent to instance'
```

This occurs when trying to access `.frame` on a nil window object during orientation changes. Modern iOS development patterns don't always require setting `application.delegate.window`, but React Native's RCTDeviceInfo assumes this property exists.

**The Solution:**
Replace direct `application.delegate.window` access with `RCTKeyWindow()` and add nil-safe fallback:

```objc
// Before (crashes in modern apps)
BOOL isRunningInFullScreen =
    CGRectEqualToRect(application.delegate.window.frame, application.delegate.window.screen.bounds);

// After (safe for all app configurations)
UIWindow *delegateWindow = RCTKeyWindow();
BOOL isRunningInFullScreen = delegateWindow ?
    CGRectEqualToRect(delegateWindow.frame, delegateWindow.screen.bounds) : YES;
```

This approach:
- Uses `RCTKeyWindow()` pattern already established elsewhere in RCTDeviceInfo
- Provides safe fallback defaulting to fullscreen when window state is unknown
- Maintains existing multitasking detection behavior (Split View, Slide Over)
- Is backward compatible with traditional React Native apps

## Changelog:
<!-- Help reviewers and the release process by writing your own changelog entry.
Pick one each for the category and type tags:
[ANDROID|GENERAL|IOS|INTERNAL] [BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY] - Message
For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests
-->

[IOS][FIXED] - Fix RCTDeviceInfo crash when application.delegate.window is nil in modern iOS app architectures

Pull Request resolved: https://github.com/facebook/react-native/pull/53645

Test Plan:
### Manual Testing

**1. SwiftUI main App Test:**
```bash
# Created SwiftUI app with main lifecycle
# Integrated React Native component
# Result: No crash during orientation changes, fullscreen detection works
 PASS: Orientation changes handled safely
 PASS: Multitasking detection stable
```

**2. Traditional React Native App:**
```bash
# Tested with standard RN template app
# Verified existing behavior unchanged
 PASS: Existing functionality preserved
 PASS: No regressions in dimension reporting
```

**3. Brownfield Integration:**
```bash
# Integrated RN in existing iOS app without window property
# Triggered orientation changes and multitasking transitions
 PASS: No crashes during orientation events
 PASS: Split View and Slide Over work correctly
```

**4. Scene-based Lifecycle App:**
```bash
# Created app using SceneDelegate for window management
# Tested orientation and multitasking scenarios
 PASS: Proper handling when SceneDelegate manages windows
 PASS: No crashes during app lifecycle transitions
```

### Edge Case Testing

**RCTKeyWindow() Returns Nil:**
- Confirmed defaults to `YES` (fullscreen)
- No crashes when no key window available
- Multitasking detection remains stable

**Multiple Window Scenarios:**
- Tested with iPad multiple windows
- Uses correct key window for measurements
- Proper behavior in complex window hierarchies

**Orientation During Transitions:**
- App backgrounding/foregrounding during orientation
- Multitasking mode changes during rotation
- No crashes or inconsistent states

### Automated Testing

```bash
# All existing tests pass
yarn test
 RCTDeviceInfoTests pass

# Code style compliance
yarn lint
 Follows React Native Objective-C guidelines
```

### Impact Verification

**Before Fix:**
- Crash in SwiftUI apps using main
- Crash in Scene-based lifecycle apps
- Crash in brownfield integrations

**After Fix:**
- All app architectures work safely
- Multitasking detection preserved
- Backward compatibility maintained
- No performance impact

Rollback Plan:

Reviewed By: javache

Differential Revision: D81931754

Pulled By: cipolleschi

fbshipit-source-id: c3ea1a2922b1d48ca6bc1fc32861b490322fd254
2025-10-20 13:41:47 +00:00
lukmccall 447a7a3527 Fix request permission is not always resolving in Android 16 (#53898)
Summary:
Fixes: https://github.com/facebook/react-native/issues/53887
Fixes: https://github.com/expo/expo/issues/39480

In the latest Android 16 update, requesting permissions does not always change the app's state (the `onPause` and `onResume` functions aren't called). For instance, when you deny permission 3 times, the last promise won't resolve until you move the app to the background. The current logic inside the `ReactActivityDelegate` assumes that Android will call `onResume` after receiving permission state information from the system, which is no longer the case.

Probably connected with [this commit](https://android.googlesource.com/platform/packages/modules/Permission/%2B/5dca0ccb26f2b99d706a1d3e9402f851e849c913)

## Changelog:

[ANDROID] [FIXED] - Fix request permission not always resolving in Android 16

Pull Request resolved: https://github.com/facebook/react-native/pull/53898

Test Plan:
- I've tested it in the RNTester by denying the camera permission three times.
- I've also checked if the patch works with the Expo permissions code.

Reviewed By: javache

Differential Revision: D83059478

Pulled By: cortinico

fbshipit-source-id: 7bf33b379a1b6606ad2da2f75d337bf951e3986b
2025-10-20 13:33:57 +00:00
Riccardo Cipolleschi 4106d54a6d fixed switch (#54155) 2025-10-20 15:28:01 +02:00
Christian Falch 779c768b6e fixed cp command to work with gnu coreutils (#54063)
Summary:
When using gnu coreutils, installation of ReactNativeDependenices on iOS fails at compile time with errors like in the following issue (in the Expo repo):

https://github.com/expo/expo/issues/38992

This is caused by a missing `.` in the end of the path name that the built-in MacOS cp command handles well, but that will create an extra Headers folder when using cp from gnu coreutils.

This commit fixes this by adding the missing `.`

## Changelog:

[IOS] [FIXED] - Fixed issue when using gnu coreutils cp command when using precompiled binaries causing compilation error

Pull Request resolved: https://github.com/facebook/react-native/pull/54063

Test Plan:
- Verify that you're running gnu coreutils (`cp --version`)
- Create new expo app `npx create-expo-app`
- Build on iOS - should error without this fix, should work with the fix.

Reviewed By: christophpurrer

Differential Revision: D83964083

Pulled By: javache

fbshipit-source-id: 46dc074ca9b7fc97fa5a37ef48d68a895e3310ff
2025-10-20 13:24:07 +00:00
Pieter De Baets 20e8bf3950 Fix useNativeTransformHelper behaviour when frame size is 0 (#53978)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53978

Inconsistency between the previous and old version of `processTransform` - if frameSize is 0, the transform was being ignored, which is not correct when considering a fixed transform origin and a rotation animation for example. Instead, always apply the transform origin if it's set.

Changelog: [Android][Fixed] Fixed representation of transforms when view is originally zero-sized

Reviewed By: mdvacca

Differential Revision: D83469083

fbshipit-source-id: e9ae1500f64c700708edb00b2d5871e3f224fb07
2025-10-20 13:20:31 +00:00
Nicola Corti e7e32f70b0 [LOCAL] Use REACT_NATIVE_BOT_GITHUB_TOKEN token for changelog and bump lockfiles 2025-09-17 11:45:38 +01:00
Gabriel Donadel 4a27725362 Update Podfile.lock
Changelog: [Internal]
2025-09-10 15:33:11 -03:00
React Native Bot 5cb9187034 Release 0.81.4
#publish-packages-to-npm&0.81-stable
2025-09-10 13:51:32 +00:00
Phil Pluckthun c3149f22a0 Remove outdated artifacts codegen early return (#53690)
Summary:
Follow-up to https://github.com/facebook/react-native/issues/53503 for a regression

When no React Native module is present this bail condition stops us from generating the artifacts podspec that's needed to complete build.

## Changelog:

[IOS] [FIXED] - Fix regression that skips artifacts code generation

Pull Request resolved: https://github.com/facebook/react-native/pull/53690

Test Plan:
- Create an app **without** any React Native modules, run `pod install`; without this fix the podspec will be missing and the build will fail
  - With expo this can be reproduced using `create-expo-app --template blank-typescript@next` on `react-native@0.81.2`
  - With the community CLI this can be reproduced using `npx react-native-community/cli@latest init test --skip-install --version 0.81.2` and uninstalling `react-native-safe-area-context`

Reviewed By: javache

Differential Revision: D82103491

Pulled By: cipolleschi

fbshipit-source-id: 3d9619b5a935ca920220824b3963a9a107f926ca
2025-09-10 12:30:45 +00:00
Phil Pluckthun bb73315a3f Use autolinking react-native-config output in iOS artifacts generator (#53503)
Summary:
Resolves https://github.com/facebook/react-native/issues/53501

This is a pretty major oversight of (presumably) the old autolinking refactor. The iOS autolinking's second stage, invoked in `use_react_native!` does not accept the `react-native-config` sub-command's `react-native-config` output. This is only invoked and used in the prior step, `use_native_modules`.

The second step instead invokes old code that does something _similar_ to the new autolinking in `scripts/generate-artifacts-executor`, and happens to align in most cases. (But it does "autolinking" from scratch). tl;dr: When the results don't match up, things go wrong.

Instead, we now write the autolinking (react native config) results to a file, then read the output back in the second step.

This doesn't affect Android/Gradle, which are implemented correctly.

[IOS] [FIXED] - Use autolinking-generated react-native-config output in second step of cocoapods linking that generates artifacts and generated source

Pull Request resolved: https://github.com/facebook/react-native/pull/53503

Test Plan:
- See https://github.com/facebook/react-native/issues/53501 for failing repro
- Clone for working repro: https://github.com/byCedric/react-native-codegen-ios-autolinking/tree/fix-54503
  - Note: Contains this PR's changes as a patch
  - `bun install`
  - `bun expo run:ios`

Reviewed By: cortinico

Differential Revision: D81490755

Pulled By: cipolleschi

fbshipit-source-id: eefe786a116404f4ed24bd7125dfb108a811f71e
2025-09-10 11:59:04 +00:00
Gabriel Donadel 97b23a3462 Update Podfile.lock
Changelog: [Internal]
2025-09-09 23:54:29 -03:00
React Native Bot 503f0e9ec9 Release 0.81.3
#publish-packages-to-npm&0.81-stable
2025-09-10 00:51:28 +00:00
Gabriel Donadel 537e3ad930 Revert "Use autolinking react-native-config output in iOS artifacts generator (#53503)"
This reverts commit a2eb29e5e7.
2025-09-09 19:14:11 -03:00
Gabriel Donadel 63619bcbad Update Podfile.lock
Changelog: [Internal]
2025-09-09 19:13:29 -03:00
React Native Bot 65119b0107 Release 0.81.2
#publish-packages-to-npm&0.81-stable
2025-09-09 16:43:27 +00:00
Nicola CortiandPieter De Baets a346096da8 [0.81] Backport useNativeEqualsInNativeReadableArrayAndroid and useNativeTransformHelperAndroid in the experimental channel (#53567)
* Use native implementation of equals in ReadableNativeArray (#52611)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/52611

We compare the current transform (represented as a ReadableArray) with the incoming one to know whether to invalidate. This can be expensive as it requires to materialize the entire transform data structure over JNI. Instead, we can delegate this comparison to native code, which can compare the underlying folly::dynamic directly.

Changelog: [Internal]

Reviewed By: NickGerleman

Differential Revision: D78340288

fbshipit-source-id: f44a054e234694c316fb080fe2dbc2017780123a

* Use native helpers to accelerate transform processing (#52603)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/52603

Processing transforms is expensive in Java, as it requires bridging the entire ReadableNativeArray/Map. Instead, we can use the existing parser logic `resolveTransform` logic to perform this operation in C++.

Ideally, we actually re-use the existing parsed transform from Props, that could be something we revisit after Props 2.0.

As a follow-up, we should consider also moving the matrix decomposition logic from MatrixMathHelper here, and make that the only information we send back to Java.

Changelog: [Internal]

Reviewed By: NickGerleman

Differential Revision: D78298588

fbshipit-source-id: a698ac8587ccfb2be04665747082398ccdde9294

* Add TransformHelper.cpp to `reactnativejni_common` (#52640)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/52640

Not having `TransformHelper.cpp` included in CMake is causing the C++ code to fail compiling.
This diff fixes it.

Changelog:
[Internal] [Changed] -

Reviewed By: cipolleschi, javache

Differential Revision: D78414015

fbshipit-source-id: 4900427a86eb38bfec10e5e385296d89c73e9051

* [LOCAL] Unbreak compilation due to CMake dependencies

---------

Co-authored-by: Pieter De Baets <pieterdb@meta.com>
2025-09-09 15:25:02 +02:00
Nicola Corti ed92bd67f4 [0.81] Backport: Create a debugOptimized buildType for Android (#53568)
* Migrate RNTester to use `{usesCleartextTraffic}` Manifest Placeholder (#52620)

Summary:
This creates a `debugOptimized` build type for React Native Android, meaning that we can run C++ optimization on the debug build, while still having the debugger enabled. This is aimed at improving the developer experience for folks developing on low-end devices or emulators.

Users that intend to debug can still use the `debug` variant where the full debug symbols are shipped.

## Changelog:

[ANDROID] [ADDED] - Create a debugOptimized buildType for Android

Pull Request resolved: https://github.com/facebook/react-native/pull/52620

Test Plan:
Tested locally with RNTester by doing:

```
./gradlew installDebugOptimized
```

This is the output of the 3 generated .aar. The size difference is a proof that we're correctly stripping out the C++ debug symbols:

<img width="193" height="54" alt="Screenshot 2025-07-15 at 17 49 50" src="https://github.com/user-attachments/assets/584a0e8d-2d17-40d4-ac29-da09049d6554" />
<img width="235" height="51" alt="Screenshot 2025-07-15 at 17 49 39" src="https://github.com/user-attachments/assets/eda8f9e7-3509-4334-8c16-990e55caa04d" />
<img width="184" height="52" alt="Screenshot 2025-07-15 at 17 49 32" src="https://github.com/user-attachments/assets/a5c94385-bc00-4484-b43e-088ee039827f" />

Rollback Plan:

Reviewed By: cipolleschi

Differential Revision: D78351347

Pulled By: cortinico

fbshipit-source-id: 568a484ba8d2ee6e089cabc95451938e853fbc54

* Create a debugOptimized buildType for Android (#52648)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/52648

This creates a `debugOptimized` build type for React Native Android, meaning that we can run C++ optimization on the debug build, while still having the debugger enabled. This is aimed at improving the developer experience for folks developing on low-end devices or emulators.

Users that intend to debug can still use the `debug` variant where the full debug symbols are shipped.

Changelog:

[ANDROID] [ADDED] - Create a debugOptimized buildType for Android

Reviewed By: cipolleschi

Differential Revision: D78425138

fbshipit-source-id: c1e9ea3608e7df10fb871a5584352f0747cf560b
2025-09-09 15:22:13 +02:00
Phil Pluckthun 366f2ad505 Replace execSync with spawnSync for tarball extraction paths that need to be escaped (#53540)
Summary:
Follow-up to https://github.com/facebook/react-native/issues/53194

This wasn't previously visible in testing without prebuilds and without a release build. This doesn't show up in debug builds.

When testing more against paths that contain spaces, I noticed that release builds can still run into trouble due to the use of `execSync` without escaping paths. While, in other scripts that aren't used in user-projects (afaict), we often escape with quotes and rely on `execSync` calling the shell (due to its `shell: true` default), in some scripts we don't have quote escapes.

That said, since paths could in theory contain quotes, adding quotes wouldn't be sufficient. Instead, since the affected `tar` calls are really trivial, we can instead use `spawnSync` with the `shell: false` default, which escapes arguments automatically.

## Changelog:

[IOS] [FIXED] - fix Node scripts related to prebuilt tarball extraction for paths containing whitespaces

Pull Request resolved: https://github.com/facebook/react-native/pull/53540

Test Plan: - Create a project in a folder `with spaces` and build a release build

Reviewed By: cipolleschi, cortinico

Differential Revision: D81406841

Pulled By: robhogan

fbshipit-source-id: 08bb06b2cd2b15dc17c2f95fab9024129deca6f3
2025-09-09 13:09:05 +00:00
Phil Pluckthun a2eb29e5e7 Use autolinking react-native-config output in iOS artifacts generator (#53503)
Summary:
Resolves https://github.com/facebook/react-native/issues/53501

This is a pretty major oversight of (presumably) the old autolinking refactor. The iOS autolinking's second stage, invoked in `use_react_native!` does not accept the `react-native-config` sub-command's `react-native-config` output. This is only invoked and used in the prior step, `use_native_modules`.

The second step instead invokes old code that does something _similar_ to the new autolinking in `scripts/generate-artifacts-executor`, and happens to align in most cases. (But it does "autolinking" from scratch). tl;dr: When the results don't match up, things go wrong.

Instead, we now write the autolinking (react native config) results to a file, then read the output back in the second step.

This doesn't affect Android/Gradle, which are implemented correctly.

[IOS] [FIXED] - Use autolinking-generated react-native-config output in second step of cocoapods linking that generates artifacts and generated source

Pull Request resolved: https://github.com/facebook/react-native/pull/53503

Test Plan:
- See https://github.com/facebook/react-native/issues/53501 for failing repro
- Clone for working repro: https://github.com/byCedric/react-native-codegen-ios-autolinking/tree/fix-54503
  - Note: Contains this PR's changes as a patch
  - `bun install`
  - `bun expo run:ios`

Reviewed By: cortinico

Differential Revision: D81490755

Pulled By: cipolleschi

fbshipit-source-id: eefe786a116404f4ed24bd7125dfb108a811f71e
2025-09-09 10:05:03 -03:00
101 changed files with 1359 additions and 457 deletions
+1
View File
@@ -10,6 +10,7 @@ jobs:
- name: Checkout
uses: actions/checkout@v4
with:
token: ${{ secrets.REACT_NATIVE_BOT_GITHUB_TOKEN }}
fetch-depth: 0
fetch-tags: true
- name: Install dependencies
+2
View File
@@ -10,6 +10,7 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v4
with:
token: ${{ secrets.REACT_NATIVE_BOT_GITHUB_TOKEN }}
fetch-depth: 0
fetch-tags: true
- name: Install dependencies
@@ -22,6 +23,7 @@ jobs:
- name: Generate Changelog
uses: actions/github-script@v6
with:
github-token: ${{ secrets.REACT_NATIVE_BOT_GITHUB_TOKEN }}
script: |
const {generateChangelog} = require('./.github/workflow-scripts/generateChangelog');
const version = '${{ github.ref_name }}';
+2 -2
View File
@@ -52,8 +52,8 @@
"@electron/packager": "^18.3.6",
"@jest/create-cache-key-function": "^29.7.0",
"@microsoft/api-extractor": "^7.52.2",
"@react-native/metro-babel-transformer": "0.81.1",
"@react-native/metro-config": "0.81.1",
"@react-native/metro-babel-transformer": "0.81.5",
"@react-native/metro-config": "0.81.5",
"@tsconfig/node22": "22.0.2",
"@types/react": "^19.1.0",
"@typescript-eslint/parser": "^7.1.1",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/assets-registry",
"version": "0.81.1",
"version": "0.81.5",
"description": "Asset support code for React Native.",
"license": "MIT",
"repository": {
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/babel-plugin-codegen",
"version": "0.81.1",
"version": "0.81.5",
"description": "Babel plugin to generate native module and view manager code for React Native.",
"license": "MIT",
"repository": {
@@ -26,7 +26,7 @@
],
"dependencies": {
"@babel/traverse": "^7.25.3",
"@react-native/codegen": "0.81.1"
"@react-native/codegen": "0.81.5"
},
"devDependencies": {
"@babel/core": "^7.25.2"
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/community-cli-plugin",
"version": "0.81.1",
"version": "0.81.5",
"description": "Core CLI commands for React Native",
"keywords": [
"react-native",
@@ -22,7 +22,7 @@
"dist"
],
"dependencies": {
"@react-native/dev-middleware": "0.81.1",
"@react-native/dev-middleware": "0.81.5",
"debug": "^4.4.0",
"invariant": "^2.2.4",
"metro": "^0.83.1",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/core-cli-utils",
"version": "0.81.1",
"version": "0.81.5",
"description": "React Native CLI library for Frameworks to build on",
"license": "MIT",
"main": "./src/index.flow.js",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/debugger-frontend",
"version": "0.81.1",
"version": "0.81.5",
"description": "Debugger frontend for React Native based on Chrome DevTools",
"keywords": [
"react-native",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/debugger-shell",
"version": "0.81.1",
"version": "0.81.5",
"description": "Experimental debugger shell for React Native for use with @react-native/debugger-frontend",
"keywords": [
"react-native",
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/dev-middleware",
"version": "0.81.1",
"version": "0.81.5",
"description": "Dev server middleware for React Native",
"keywords": [
"react-native",
@@ -23,7 +23,7 @@
],
"dependencies": {
"@isaacs/ttlcache": "^1.4.1",
"@react-native/debugger-frontend": "0.81.1",
"@react-native/debugger-frontend": "0.81.5",
"chrome-launcher": "^0.15.2",
"chromium-edge-launcher": "^0.2.0",
"connect": "^3.6.5",
@@ -1,6 +1,6 @@
{
"name": "@react-native/eslint-config",
"version": "0.81.1",
"version": "0.81.5",
"description": "ESLint config for React Native",
"license": "MIT",
"repository": {
@@ -22,7 +22,7 @@
"dependencies": {
"@babel/core": "^7.25.2",
"@babel/eslint-parser": "^7.25.1",
"@react-native/eslint-plugin": "0.81.1",
"@react-native/eslint-plugin": "0.81.5",
"@typescript-eslint/eslint-plugin": "^7.1.1",
"@typescript-eslint/parser": "^7.1.1",
"eslint-config-prettier": "^8.5.0",
@@ -1,6 +1,6 @@
{
"name": "@react-native/eslint-plugin",
"version": "0.81.1",
"version": "0.81.5",
"description": "ESLint rules for @react-native/eslint-config",
"license": "MIT",
"repository": {
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/eslint-plugin-specs",
"version": "0.81.1",
"version": "0.81.5",
"description": "ESLint rules to validate NativeModule and Component Specs",
"license": "MIT",
"repository": {
@@ -26,7 +26,7 @@
"dependencies": {
"@babel/core": "^7.25.2",
"@babel/plugin-transform-flow-strip-types": "^7.25.2",
"@react-native/codegen": "0.81.1",
"@react-native/codegen": "0.81.5",
"make-dir": "^2.1.0",
"pirates": "^4.0.1",
"source-map-support": "0.5.0"
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/gradle-plugin",
"version": "0.81.1",
"version": "0.81.5",
"description": "Gradle Plugin for React Native",
"license": "MIT",
"repository": {
@@ -100,10 +100,10 @@ abstract class ReactExtension @Inject constructor(val project: Project) {
* Allows to specify the debuggable variants (by default just 'debug'). Variants in this list will
* not be bundled (the bundle file will not be created and won't be copied over).
*
* Default: ['debug']
* Default: ['debug', 'debugOptimized']
*/
val debuggableVariants: ListProperty<String> =
objects.listProperty(String::class.java).convention(listOf("debug"))
objects.listProperty(String::class.java).convention(listOf("debug", "debugOptimized"))
/** Hermes Config */
@@ -18,6 +18,7 @@ import com.facebook.react.tasks.GenerateEntryPointTask
import com.facebook.react.tasks.GeneratePackageListTask
import com.facebook.react.utils.AgpConfiguratorUtils.configureBuildConfigFieldsForApp
import com.facebook.react.utils.AgpConfiguratorUtils.configureBuildConfigFieldsForLibraries
import com.facebook.react.utils.AgpConfiguratorUtils.configureBuildTypesForApp
import com.facebook.react.utils.AgpConfiguratorUtils.configureDevServerLocation
import com.facebook.react.utils.AgpConfiguratorUtils.configureNamespaceForLibraries
import com.facebook.react.utils.BackwardCompatUtils.configureBackwardCompatibilityReactMap
@@ -84,6 +85,7 @@ class ReactPlugin : Plugin<Project> {
configureAutolinking(project, extension)
configureCodegen(project, extension, rootExtension, isLibrary = false)
configureResources(project, extension)
configureBuildTypesForApp(project)
}
// Library Only Configuration
@@ -19,6 +19,7 @@ import java.net.Inet4Address
import java.net.NetworkInterface
import javax.xml.parsers.DocumentBuilder
import javax.xml.parsers.DocumentBuilderFactory
import kotlin.plus
import org.gradle.api.Action
import org.gradle.api.Project
import org.gradle.api.plugins.AppliedPlugin
@@ -27,6 +28,36 @@ import org.w3c.dom.Element
@Suppress("UnstableApiUsage")
internal object AgpConfiguratorUtils {
fun configureBuildTypesForApp(project: Project) {
val action =
Action<AppliedPlugin> {
project.extensions
.getByType(ApplicationAndroidComponentsExtension::class.java)
.finalizeDsl { ext ->
ext.buildTypes {
val debug =
getByName("debug").apply {
manifestPlaceholders["usesCleartextTraffic"] = "true"
}
getByName("release").apply {
manifestPlaceholders["usesCleartextTraffic"] = "false"
}
maybeCreate("debugOptimized").apply {
manifestPlaceholders["usesCleartextTraffic"] = "true"
initWith(debug)
externalNativeBuild {
cmake {
arguments("-DCMAKE_BUILD_TYPE=Release")
matchingFallbacks += listOf("release")
}
}
}
}
}
}
project.pluginManager.withPlugin("com.android.application", action)
}
fun configureBuildConfigFieldsForApp(project: Project, extension: ReactExtension) {
val action =
Action<AppliedPlugin> {
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/metro-config",
"version": "0.81.1",
"version": "0.81.5",
"description": "Metro configuration for React Native.",
"license": "MIT",
"repository": {
@@ -26,8 +26,8 @@
"dist"
],
"dependencies": {
"@react-native/js-polyfills": "0.81.1",
"@react-native/metro-babel-transformer": "0.81.1",
"@react-native/js-polyfills": "0.81.5",
"@react-native/metro-babel-transformer": "0.81.5",
"metro-config": "^0.83.1",
"metro-runtime": "^0.83.1"
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/new-app-screen",
"version": "0.81.1",
"version": "0.81.5",
"description": "NewAppScreen component for React Native",
"keywords": [
"react-native"
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/normalize-colors",
"version": "0.81.1",
"version": "0.81.5",
"description": "Color normalization for React Native.",
"license": "MIT",
"repository": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/js-polyfills",
"version": "0.81.1",
"version": "0.81.5",
"description": "Polyfills for React Native.",
"license": "MIT",
"repository": {
@@ -1,6 +1,6 @@
{
"name": "@react-native/babel-preset",
"version": "0.81.1",
"version": "0.81.5",
"description": "Babel preset for React Native applications",
"repository": {
"type": "git",
@@ -66,7 +66,7 @@
"@babel/plugin-transform-typescript": "^7.25.2",
"@babel/plugin-transform-unicode-regex": "^7.24.7",
"@babel/template": "^7.25.0",
"@react-native/babel-plugin-codegen": "0.81.1",
"@react-native/babel-plugin-codegen": "0.81.5",
"babel-plugin-syntax-hermes-parser": "0.29.1",
"babel-plugin-transform-flow-enums": "^0.0.2",
"react-refresh": "^0.14.0"
@@ -1,6 +1,6 @@
{
"name": "@react-native/metro-babel-transformer",
"version": "0.81.1",
"version": "0.81.5",
"description": "Babel transformer for React Native applications.",
"repository": {
"type": "git",
@@ -27,7 +27,7 @@
],
"dependencies": {
"@babel/core": "^7.25.2",
"@react-native/babel-preset": "0.81.1",
"@react-native/babel-preset": "0.81.5",
"hermes-parser": "0.29.1",
"nullthrows": "^1.1.1"
},
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/codegen",
"version": "0.81.1",
"version": "0.81.5",
"description": "Code generation tools for React Native",
"license": "MIT",
"repository": {
@@ -1,6 +1,6 @@
{
"name": "@react-native/compatibility-check",
"version": "0.81.1",
"version": "0.81.5",
"description": "Check a React Native app's boundary between JS and Native for incompatibilities",
"license": "MIT",
"repository": {
@@ -29,7 +29,7 @@
"dist"
],
"dependencies": {
"@react-native/codegen": "0.81.1"
"@react-native/codegen": "0.81.5"
},
"devDependencies": {
"flow-remove-types": "^2.237.2",
@@ -1,6 +1,6 @@
{
"name": "@react-native/popup-menu-android",
"version": "0.81.1",
"version": "0.81.5",
"description": "PopupMenu for the Android platform",
"main": "index.js",
"files": [
@@ -21,7 +21,7 @@
},
"license": "MIT",
"devDependencies": {
"@react-native/codegen": "0.81.1"
"@react-native/codegen": "0.81.5"
},
"peerDependencies": {
"@types/react": "^19.1.0",
@@ -26,8 +26,8 @@
],
"devDependencies": {
"@babel/core": "^7.25.2",
"@react-native/babel-preset": "0.81.1",
"react-native": "0.81.1"
"@react-native/babel-preset": "0.81.5",
"react-native": "0.81.5"
},
"peerDependencies": {
"react": "*",
+1 -1
View File
@@ -17,6 +17,6 @@ export const version: $ReadOnly<{
}> = {
major: 0,
minor: 81,
patch: 1,
patch: 5,
prerelease: null,
};
+5 -1
View File
@@ -432,7 +432,11 @@ CGSize RCTSwitchSize(void)
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
RCTUnsafeExecuteOnMainQueueSync(^{
rctSwitchSize = [UISwitch new].intrinsicContentSize;
CGSize switchSize = [UISwitch new].intrinsicContentSize;
// Apple does not take into account the thumb border when returning the
// width of the UISwitch component, so we are adding 2 pixels for the border
// which is not customizable and it is the same for legacy and liquid glass.
rctSwitchSize = CGSizeMake(switchSize.width + 2, switchSize.height);
});
});
return rctSwitchSize;
@@ -23,7 +23,7 @@ NSDictionary* RCTGetReactNativeVersion(void)
__rnVersion = @{
RCTVersionMajor: @(0),
RCTVersionMinor: @(81),
RCTVersionPatch: @(1),
RCTVersionPatch: @(5),
RCTVersionPrerelease: [NSNull null],
};
});
@@ -238,11 +238,10 @@ static NSDictionary *RCTExportedDimensions(CGFloat fontScale)
- (void)interfaceOrientationDidChange
{
#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST
UIApplication *application = RCTSharedApplication();
UIInterfaceOrientation nextOrientation = RCTKeyWindow().windowScene.interfaceOrientation;
UIWindow *window = RCTKeyWindow();
UIInterfaceOrientation nextOrientation = window.windowScene.interfaceOrientation;
BOOL isRunningInFullScreen =
CGRectEqualToRect(application.delegate.window.frame, application.delegate.window.screen.bounds);
BOOL isRunningInFullScreen = window ? CGRectEqualToRect(window.frame, window.screen.bounds) : YES;
// 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->
@@ -8,10 +8,29 @@
#import "RCTSwitchManager.h"
#import <React/RCTUIManager.h>
#import <React/RCTUtils.h>
#import "RCTBridge.h"
#import "RCTShadowView.h"
#import "RCTSwitch.h"
#import "UIView+React.h"
@interface RCTSwitchShadowView : RCTShadowView
@end
@implementation RCTSwitchShadowView
- (instancetype)init
{
if (self = [super init]) {
self.intrinsicContentSize = RCTSwitchSize();
}
return self;
}
@end
@implementation RCTSwitchManager
RCT_EXPORT_MODULE()
@@ -33,6 +52,11 @@ RCT_EXPORT_MODULE()
}
}
- (RCTShadowView *)shadowView
{
return [RCTSwitchShadowView new];
}
RCT_EXPORT_METHOD(setValue : (nonnull NSNumber *)viewTag toValue : (BOOL)value)
{
[self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
@@ -598,7 +598,7 @@ android {
publishing {
multipleVariants {
withSourcesJar()
includeBuildTypeValues("debug", "release")
includeBuildTypeValues("debug", "release", "debugOptimized")
}
}
@@ -606,6 +606,15 @@ android {
unitTests { isIncludeAndroidResources = true }
targetSdk = libs.versions.targetSdk.get().toInt()
}
buildTypes {
create("debugOptimized") {
initWith(getByName("debug"))
externalNativeBuild {
cmake { arguments("-DCMAKE_BUILD_TYPE=Release", "-DREACT_NATIVE_DEBUG_OPTIMIZED=True") }
}
}
}
}
tasks.withType<KotlinCompile>().configureEach {
@@ -1,4 +1,4 @@
VERSION_NAME=0.81.1
VERSION_NAME=0.81.5
react.internal.publishingGroup=com.facebook.react
android.useAndroidX=true
@@ -306,6 +306,12 @@ android {
}
}
}
buildTypes {
create("debugOptimized") {
initWith(getByName("debug"))
externalNativeBuild { cmake { arguments("-DCMAKE_BUILD_TYPE=Release") } }
}
}
}
sourceSets.getByName("main") {
@@ -21,6 +21,7 @@ import com.facebook.infer.annotation.Assertions;
import com.facebook.infer.annotation.Nullsafe;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.common.LifecycleState;
import com.facebook.react.interfaces.fabric.ReactSurface;
import com.facebook.react.internal.featureflags.ReactNativeNewArchitectureFeatureFlags;
import com.facebook.react.modules.core.PermissionListener;
@@ -247,7 +248,7 @@ public class ReactActivityDelegate {
public void onRequestPermissionsResult(
final int requestCode, final String[] permissions, final int[] grantResults) {
mPermissionsCallback =
Callback permissionsCallback =
args -> {
if (mPermissionListener != null
&& mPermissionListener.onRequestPermissionsResult(
@@ -255,6 +256,29 @@ public class ReactActivityDelegate {
mPermissionListener = null;
}
};
LifecycleState lifecycle;
if (isFabricEnabled()) {
ReactHost reactHost = getReactHost();
lifecycle = reactHost != null ? reactHost.getLifecycleState() : LifecycleState.BEFORE_CREATE;
} else {
ReactNativeHost reactNativeHost = getReactNativeHost();
if (!reactNativeHost.hasInstance()) {
lifecycle = LifecycleState.BEFORE_CREATE;
} else {
lifecycle = reactNativeHost.getReactInstanceManager().getLifecycleState();
}
}
// If the permission request didn't show a dialog to the user, we can call the callback
// immediately.
// Otherwise, we need to wait until onResume to call it.
if (lifecycle == LifecycleState.RESUMED) {
permissionsCallback.invoke();
return;
}
mPermissionsCallback = permissionsCallback;
}
protected Context getContext() {
@@ -8,6 +8,7 @@
package com.facebook.react.bridge
import com.facebook.proguard.annotations.DoNotStrip
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags
import java.util.ArrayList
import java.util.Arrays
import kotlin.jvm.JvmStatic
@@ -65,9 +66,16 @@ public open class ReadableNativeArray protected constructor() : NativeArray(), R
if (other !is ReadableNativeArray) {
return false
}
return localArray.contentDeepEquals(other.localArray)
return if (ReactNativeFeatureFlags.useNativeEqualsInNativeReadableArrayAndroid()) {
nativeEquals(other)
} else {
localArray.contentDeepEquals(other.localArray)
}
}
private external fun nativeEquals(other: ReadableNativeArray): Boolean
override fun toArrayList(): ArrayList<Any?> {
val arrayList = ArrayList<Any?>()
repeat(size()) { i ->
@@ -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<<3e4d74a17c15742d35db9e4247f3e1c1>>
* @generated SignedSource<<c52f3977ea07f976e36177f13c1ec684>>
*/
/**
@@ -342,6 +342,18 @@ public object ReactNativeFeatureFlags {
@JvmStatic
public fun useFabricInterop(): Boolean = accessor.useFabricInterop()
/**
* Use a native implementation of equals in NativeReadableArray.
*/
@JvmStatic
public fun useNativeEqualsInNativeReadableArrayAndroid(): Boolean = accessor.useNativeEqualsInNativeReadableArrayAndroid()
/**
* Use a native implementation of TransformHelper
*/
@JvmStatic
public fun useNativeTransformHelperAndroid(): Boolean = accessor.useNativeTransformHelperAndroid()
/**
* When enabled, the native view configs are used in bridgeless mode.
*/
@@ -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<<e7c1c6d184681d98320aac2a23c06288>>
* @generated SignedSource<<8e0125e82b359e6a175ffc49a4df5537>>
*/
/**
@@ -72,6 +72,8 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
private var updateRuntimeShadowNodeReferencesOnCommitCache: Boolean? = null
private var useAlwaysAvailableJSErrorHandlingCache: Boolean? = null
private var useFabricInteropCache: Boolean? = null
private var useNativeEqualsInNativeReadableArrayAndroidCache: Boolean? = null
private var useNativeTransformHelperAndroidCache: Boolean? = null
private var useNativeViewConfigsInBridgelessModeCache: Boolean? = null
private var useOptimizedEventBatchingOnAndroidCache: Boolean? = null
private var useRawPropsJsiValueCache: Boolean? = null
@@ -548,6 +550,24 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
return cached
}
override fun useNativeEqualsInNativeReadableArrayAndroid(): Boolean {
var cached = useNativeEqualsInNativeReadableArrayAndroidCache
if (cached == null) {
cached = ReactNativeFeatureFlagsCxxInterop.useNativeEqualsInNativeReadableArrayAndroid()
useNativeEqualsInNativeReadableArrayAndroidCache = cached
}
return cached
}
override fun useNativeTransformHelperAndroid(): Boolean {
var cached = useNativeTransformHelperAndroidCache
if (cached == null) {
cached = ReactNativeFeatureFlagsCxxInterop.useNativeTransformHelperAndroid()
useNativeTransformHelperAndroidCache = cached
}
return cached
}
override fun useNativeViewConfigsInBridgelessMode(): Boolean {
var cached = useNativeViewConfigsInBridgelessModeCache
if (cached == null) {
@@ -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<<ba62d616188ed439c85c66cfd055810d>>
* @generated SignedSource<<a5d9d11cc2a6529641243dc47a61f201>>
*/
/**
@@ -132,6 +132,10 @@ public object ReactNativeFeatureFlagsCxxInterop {
@DoNotStrip @JvmStatic public external fun useFabricInterop(): Boolean
@DoNotStrip @JvmStatic public external fun useNativeEqualsInNativeReadableArrayAndroid(): Boolean
@DoNotStrip @JvmStatic public external fun useNativeTransformHelperAndroid(): Boolean
@DoNotStrip @JvmStatic public external fun useNativeViewConfigsInBridgelessMode(): Boolean
@DoNotStrip @JvmStatic public external fun useOptimizedEventBatchingOnAndroid(): Boolean
@@ -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<<12c2727291b635ef7c3163d153669c2c>>
* @generated SignedSource<<10d708ce4449eede46d750a1ed48d02e>>
*/
/**
@@ -127,6 +127,10 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
override fun useFabricInterop(): Boolean = true
override fun useNativeEqualsInNativeReadableArrayAndroid(): Boolean = false
override fun useNativeTransformHelperAndroid(): Boolean = false
override fun useNativeViewConfigsInBridgelessMode(): Boolean = false
override fun useOptimizedEventBatchingOnAndroid(): Boolean = false
@@ -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<<3ea9946ef21c8ac8bb9bb63712636e89>>
* @generated SignedSource<<b04948c792c5db63decf1df80d3a867e>>
*/
/**
@@ -76,6 +76,8 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
private var updateRuntimeShadowNodeReferencesOnCommitCache: Boolean? = null
private var useAlwaysAvailableJSErrorHandlingCache: Boolean? = null
private var useFabricInteropCache: Boolean? = null
private var useNativeEqualsInNativeReadableArrayAndroidCache: Boolean? = null
private var useNativeTransformHelperAndroidCache: Boolean? = null
private var useNativeViewConfigsInBridgelessModeCache: Boolean? = null
private var useOptimizedEventBatchingOnAndroidCache: Boolean? = null
private var useRawPropsJsiValueCache: Boolean? = null
@@ -604,6 +606,26 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
return cached
}
override fun useNativeEqualsInNativeReadableArrayAndroid(): Boolean {
var cached = useNativeEqualsInNativeReadableArrayAndroidCache
if (cached == null) {
cached = currentProvider.useNativeEqualsInNativeReadableArrayAndroid()
accessedFeatureFlags.add("useNativeEqualsInNativeReadableArrayAndroid")
useNativeEqualsInNativeReadableArrayAndroidCache = cached
}
return cached
}
override fun useNativeTransformHelperAndroid(): Boolean {
var cached = useNativeTransformHelperAndroidCache
if (cached == null) {
cached = currentProvider.useNativeTransformHelperAndroid()
accessedFeatureFlags.add("useNativeTransformHelperAndroid")
useNativeTransformHelperAndroidCache = cached
}
return cached
}
override fun useNativeViewConfigsInBridgelessMode(): Boolean {
var cached = useNativeViewConfigsInBridgelessModeCache
if (cached == null) {
@@ -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<<58da46268043f086730132430735b720>>
* @generated SignedSource<<0bafb0a2fb79c4220d21f1736894af14>>
*/
/**
@@ -24,4 +24,8 @@ public open class ReactNativeFeatureFlagsOverrides_RNOSS_Experimental_Android :
// but that is more expensive than just duplicating the defaults here.
override fun preventShadowTreeCommitExhaustion(): Boolean = true
override fun useNativeEqualsInNativeReadableArrayAndroid(): Boolean = true
override fun useNativeTransformHelperAndroid(): 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<<1e81de36735c6c9286b228c75c9a0228>>
* @generated SignedSource<<21704207ce520def05b05f89dfba1048>>
*/
/**
@@ -127,6 +127,10 @@ public interface ReactNativeFeatureFlagsProvider {
@DoNotStrip public fun useFabricInterop(): Boolean
@DoNotStrip public fun useNativeEqualsInNativeReadableArrayAndroid(): Boolean
@DoNotStrip public fun useNativeTransformHelperAndroid(): Boolean
@DoNotStrip public fun useNativeViewConfigsInBridgelessMode(): Boolean
@DoNotStrip public fun useOptimizedEventBatchingOnAndroid(): Boolean
@@ -14,7 +14,7 @@ public object ReactNativeVersion {
public val VERSION: Map<String, Any?> = mapOf(
"major" to 0,
"minor" to 81,
"patch" to 1,
"patch" to 5,
"prerelease" to null
)
}
@@ -8,10 +8,12 @@
package com.facebook.react.uimanager
import com.facebook.common.logging.FLog
import com.facebook.react.bridge.NativeArray
import com.facebook.react.bridge.ReadableArray
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.bridge.ReadableType
import com.facebook.react.common.ReactConstants
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags
public object TransformHelper {
@@ -69,6 +71,14 @@ public object TransformHelper {
transformOrigin: ReadableArray?,
allowPercentageResolution: Boolean
) {
if (allowPercentageResolution &&
ReactNativeFeatureFlags.useNativeTransformHelperAndroid() &&
transforms is NativeArray &&
transformOrigin is NativeArray?) {
nativeProcessTransform(transforms, result, viewWidth, viewHeight, transformOrigin)
return
}
val helperMatrix = helperMatrix.get()!!
MatrixMathHelper.resetIdentityMatrix(result)
val offsets =
@@ -220,4 +230,13 @@ public object TransformHelper {
return doubleArrayOf(newTranslateX, newTranslateY, newTranslateZ)
}
@JvmStatic
private external fun nativeProcessTransform(
transforms: NativeArray,
result: DoubleArray,
viewWidth: Float,
viewHeight: Float,
transformOrigin: NativeArray?
)
}
@@ -51,7 +51,7 @@ import kotlin.math.min
* constructed in superclass.
*/
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
public class ReactTextShadowNode
public open class ReactTextShadowNode
@JvmOverloads
public constructor(reactTextViewManagerCallback: ReactTextViewManagerCallback? = null) :
ReactBaseTextShadowNode(reactTextViewManagerCallback) {
@@ -29,7 +29,7 @@ import java.util.HashMap
*/
@ReactModule(name = ReactTextViewManager.REACT_CLASS)
@OptIn(UnstableReactNativeAPI::class)
public class ReactTextViewManager
public open class ReactTextViewManager
@JvmOverloads
public constructor(
protected var reactTextViewManagerCallback: ReactTextViewManagerCallback? = null
@@ -92,7 +92,7 @@ public constructor(
override fun createShadowNodeInstance(): ReactTextShadowNode =
ReactTextShadowNode(reactTextViewManagerCallback)
public fun createShadowNodeInstance(
public open fun createShadowNodeInstance(
reactTextViewManagerCallback: ReactTextViewManagerCallback?
): ReactTextShadowNode = ReactTextShadowNode(reactTextViewManagerCallback)
@@ -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<<cf7b6ff66c614ca2acc6667a80c5590d>>
* @generated SignedSource<<bbad4ee8cacd33099874d0c3078ea716>>
*/
/**
@@ -351,6 +351,18 @@ class ReactNativeFeatureFlagsJavaProvider
return method(javaProvider_);
}
bool useNativeEqualsInNativeReadableArrayAndroid() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("useNativeEqualsInNativeReadableArrayAndroid");
return method(javaProvider_);
}
bool useNativeTransformHelperAndroid() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("useNativeTransformHelperAndroid");
return method(javaProvider_);
}
bool useNativeViewConfigsInBridgelessMode() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("useNativeViewConfigsInBridgelessMode");
@@ -657,6 +669,16 @@ bool JReactNativeFeatureFlagsCxxInterop::useFabricInterop(
return ReactNativeFeatureFlags::useFabricInterop();
}
bool JReactNativeFeatureFlagsCxxInterop::useNativeEqualsInNativeReadableArrayAndroid(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::useNativeEqualsInNativeReadableArrayAndroid();
}
bool JReactNativeFeatureFlagsCxxInterop::useNativeTransformHelperAndroid(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::useNativeTransformHelperAndroid();
}
bool JReactNativeFeatureFlagsCxxInterop::useNativeViewConfigsInBridgelessMode(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::useNativeViewConfigsInBridgelessMode();
@@ -879,6 +901,12 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
makeNativeMethod(
"useFabricInterop",
JReactNativeFeatureFlagsCxxInterop::useFabricInterop),
makeNativeMethod(
"useNativeEqualsInNativeReadableArrayAndroid",
JReactNativeFeatureFlagsCxxInterop::useNativeEqualsInNativeReadableArrayAndroid),
makeNativeMethod(
"useNativeTransformHelperAndroid",
JReactNativeFeatureFlagsCxxInterop::useNativeTransformHelperAndroid),
makeNativeMethod(
"useNativeViewConfigsInBridgelessMode",
JReactNativeFeatureFlagsCxxInterop::useNativeViewConfigsInBridgelessMode),
@@ -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<<dae981c66bf0751fd2863937ecf255d8>>
* @generated SignedSource<<57f2dcf4b71512c6b15e8021258d6036>>
*/
/**
@@ -186,6 +186,12 @@ class JReactNativeFeatureFlagsCxxInterop
static bool useFabricInterop(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static bool useNativeEqualsInNativeReadableArrayAndroid(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static bool useNativeTransformHelperAndroid(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static bool useNativeViewConfigsInBridgelessMode(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
@@ -25,4 +25,6 @@ target_link_libraries(
reactnative
)
target_compile_reactnative_options(hermes_executor PRIVATE)
target_compile_options(hermes_executor PRIVATE $<$<CONFIG:Debug>:-DHERMES_ENABLE_DEBUGGER=1>)
if(${CMAKE_BUILD_TYPE} MATCHES Debug OR REACT_NATIVE_DEBUG_OPTIMIZED)
target_compile_options(hermes_executor PRIVATE -DHERMES_ENABLE_DEBUGGER=1)
endif()
@@ -31,13 +31,14 @@ add_library(
OnLoad-common.cpp
ReadableNativeArray.cpp
ReadableNativeMap.cpp
TransformHelper.cpp
WritableNativeArray.cpp
WritableNativeMap.cpp
)
target_merge_so(reactnativejni_common)
target_include_directories(reactnativejni_common PUBLIC ../../)
target_link_libraries(reactnativejni_common fbjni folly_runtime react_cxxreact)
target_link_libraries(reactnativejni_common fbjni folly_runtime react_cxxreact yoga react_renderer_graphics)
target_compile_reactnative_options(reactnativejni_common PRIVATE)
target_compile_options(reactnativejni_common PRIVATE -Wno-unused-lambda-capture)
@@ -21,6 +21,10 @@ class NativeArray : public jni::HybridClass<NativeArray> {
jni::local_ref<jstring> toString();
const folly::dynamic& getArray() const {
return array_;
}
RN_EXPORT folly::dynamic consume();
// Whether this array has been added to another array or map and no longer
@@ -11,6 +11,7 @@
#include "JReactMarker.h"
#include "NativeArray.h"
#include "NativeMap.h"
#include "TransformHelper.h"
#include "WritableNativeArray.h"
#include "WritableNativeMap.h"
@@ -27,6 +28,7 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
ReadableNativeMap::registerNatives();
WritableNativeArray::registerNatives();
WritableNativeMap::registerNatives();
TransformHelper::registerNatives();
});
}
@@ -40,10 +40,16 @@ local_ref<JArrayClass<jobject>> ReadableNativeArray::importTypeArray() {
return jarray;
}
bool ReadableNativeArray::equals(
jni::alias_ref<ReadableNativeArray::javaobject> other) {
return array_ == other->cthis()->array_;
}
void ReadableNativeArray::registerNatives() {
registerHybrid({
makeNativeMethod("importArray", ReadableNativeArray::importArray),
makeNativeMethod("importTypeArray", ReadableNativeArray::importTypeArray),
makeNativeMethod("nativeEquals", ReadableNativeArray::equals),
});
}
@@ -35,6 +35,7 @@ class ReadableNativeArray
static void mapException(std::exception_ptr ex);
static void registerNatives();
bool equals(jni::alias_ref<ReadableNativeArray::javaobject> other);
jni::local_ref<jni::JArrayClass<jobject>> importArray();
jni::local_ref<jni::JArrayClass<jobject>> importTypeArray();
};
@@ -0,0 +1,62 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "TransformHelper.h"
#include <react/renderer/components/view/BaseViewProps.h>
#include <react/renderer/components/view/conversions.h>
#include "NativeArray.h"
using namespace facebook::jni;
namespace facebook::react {
namespace {
void processTransform(
jni::alias_ref<jclass> /*unused*/,
NativeArray* jTransforms,
jni::alias_ref<jni::JArrayDouble> jResult,
float viewWidth,
float viewHeight,
NativeArray* jTransformOrigin) {
// Assuming parsing transforms doesn't require a real PropsParserContext
static ContextContainer contextContainer;
static PropsParserContext context(0, contextContainer);
RawValue transformValue(jTransforms->getArray());
Transform transform;
fromRawValue(context, transformValue, transform);
TransformOrigin transformOrigin;
if (jTransformOrigin != nullptr) {
RawValue transformOriginValue(jTransformOrigin->getArray());
fromRawValue(context, transformOriginValue, transformOrigin);
}
auto result = BaseViewProps::resolveTransform(
Size{.width = viewWidth, .height = viewHeight},
transform,
transformOrigin);
// Convert from matrix of floats to double matrix
constexpr size_t MatrixSize = std::tuple_size_v<decltype(result.matrix)>;
std::array<double, MatrixSize> doubleTransform{};
std::copy(
result.matrix.begin(), result.matrix.end(), doubleTransform.begin());
jResult->setRegion(0, MatrixSize, doubleTransform.data());
}
} // namespace
void TransformHelper::registerNatives() {
javaClassLocal()->registerNatives({
makeNativeMethod("nativeProcessTransform", processTransform),
});
}
} // namespace facebook::react
@@ -0,0 +1,22 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include <fbjni/fbjni.h>
namespace facebook::react {
class TransformHelper : public jni::JavaClass<TransformHelper> {
public:
static auto constexpr* kJavaDescriptor =
"Lcom/facebook/react/uimanager/TransformHelper;";
static void registerNatives();
};
} // namespace facebook::react
@@ -27,4 +27,6 @@ target_link_libraries(hermesinstancejni
)
target_compile_reactnative_options(hermesinstancejni PRIVATE)
target_compile_options(hermesinstancejni PRIVATE $<$<CONFIG:Debug>:-DHERMES_ENABLE_DEBUGGER=1>)
if(${CMAKE_BUILD_TYPE} MATCHES Debug OR REACT_NATIVE_DEBUG_OPTIMIZED)
target_compile_options(hermesinstancejni PRIVATE -DHERMES_ENABLE_DEBUGGER=1)
endif ()
@@ -17,7 +17,9 @@ add_library(rninstance
)
target_compile_reactnative_options(rninstance PRIVATE)
target_compile_options(rninstance PRIVATE $<$<CONFIG:Debug>:-DHERMES_ENABLE_DEBUGGER=1>)
if(${CMAKE_BUILD_TYPE} MATCHES Debug OR REACT_NATIVE_DEBUG_OPTIMIZED)
target_compile_options(rninstance PRIVATE -DHERMES_ENABLE_DEBUGGER=1)
endif ()
target_merge_so(rninstance)
target_include_directories(rninstance PUBLIC .)
@@ -14,14 +14,14 @@
#define REACT_NATIVE_VERSION_MAJOR 0
#define REACT_NATIVE_VERSION_MINOR 81
#define REACT_NATIVE_VERSION_PATCH 1
#define REACT_NATIVE_VERSION_PATCH 5
namespace facebook::react {
constexpr struct {
int32_t Major = 0;
int32_t Minor = 81;
int32_t Patch = 1;
int32_t Patch = 5;
std::string_view Prerelease = "";
} ReactNativeVersion;
@@ -26,7 +26,7 @@ target_link_libraries(hermes_executor_common
)
target_compile_reactnative_options(hermes_executor_common PRIVATE)
if(${CMAKE_BUILD_TYPE} MATCHES Debug)
if(${CMAKE_BUILD_TYPE} MATCHES Debug OR REACT_NATIVE_DEBUG_OPTIMIZED)
target_compile_options(
hermes_executor_common
PRIVATE
@@ -17,7 +17,7 @@ add_library(hermes_inspector_modern
target_compile_reactnative_options(hermes_inspector_modern PRIVATE)
if(${CMAKE_BUILD_TYPE} MATCHES Debug)
if(${CMAKE_BUILD_TYPE} MATCHES Debug OR REACT_NATIVE_DEBUG_OPTIMIZED)
target_compile_options(
hermes_inspector_modern
PRIVATE
@@ -27,7 +27,9 @@ target_link_libraries(jsinspector
runtimeexecutor
)
target_compile_reactnative_options(jsinspector PRIVATE)
target_compile_options(jsinspector PRIVATE
$<$<CONFIG:Debug>:-DREACT_NATIVE_DEBUGGER_ENABLED=1>
$<$<CONFIG:Debug>:-DREACT_NATIVE_DEBUGGER_ENABLED_DEVONLY=1>
)
if(${CMAKE_BUILD_TYPE} MATCHES Debug OR REACT_NATIVE_DEBUG_OPTIMIZED)
target_compile_options(jsinspector PRIVATE
-DREACT_NATIVE_DEBUGGER_ENABLED=1
-DREACT_NATIVE_DEBUGGER_ENABLED_DEVONLY=1
)
endif ()
@@ -21,6 +21,6 @@ endif()
target_compile_reactnative_options(react_debug PRIVATE)
target_compile_options(react_debug PRIVATE -Wpedantic)
if(NOT ${CMAKE_BUILD_TYPE} MATCHES Debug)
if(NOT ${CMAKE_BUILD_TYPE} MATCHES Debug AND NOT REACT_NATIVE_DEBUG_OPTIMIZED)
target_compile_options(react_debug PUBLIC -DNDEBUG)
endif()
@@ -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<<f73bbcd926a835c09b70d814c6662dbb>>
* @generated SignedSource<<2cabd888b74b84201ff027457efc6007>>
*/
/**
@@ -234,6 +234,14 @@ bool ReactNativeFeatureFlags::useFabricInterop() {
return getAccessor().useFabricInterop();
}
bool ReactNativeFeatureFlags::useNativeEqualsInNativeReadableArrayAndroid() {
return getAccessor().useNativeEqualsInNativeReadableArrayAndroid();
}
bool ReactNativeFeatureFlags::useNativeTransformHelperAndroid() {
return getAccessor().useNativeTransformHelperAndroid();
}
bool ReactNativeFeatureFlags::useNativeViewConfigsInBridgelessMode() {
return getAccessor().useNativeViewConfigsInBridgelessMode();
}
@@ -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<<da14545268455bfd4cd35e5c2ecf81ee>>
* @generated SignedSource<<e26a0c35f1499abf24e46275bbcbe06d>>
*/
/**
@@ -299,6 +299,16 @@ class ReactNativeFeatureFlags {
*/
RN_EXPORT static bool useFabricInterop();
/**
* Use a native implementation of equals in NativeReadableArray.
*/
RN_EXPORT static bool useNativeEqualsInNativeReadableArrayAndroid();
/**
* Use a native implementation of TransformHelper
*/
RN_EXPORT static bool useNativeTransformHelperAndroid();
/**
* When enabled, the native view configs are used in bridgeless mode.
*/
@@ -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<<681bff71eb87886a108f67b3162b030c>>
* @generated SignedSource<<7ae9a203a94e3a22197bc9eda69b741c>>
*/
/**
@@ -965,6 +965,42 @@ bool ReactNativeFeatureFlagsAccessor::useFabricInterop() {
return flagValue.value();
}
bool ReactNativeFeatureFlagsAccessor::useNativeEqualsInNativeReadableArrayAndroid() {
auto flagValue = useNativeEqualsInNativeReadableArrayAndroid_.load();
if (!flagValue.has_value()) {
// This block is not exclusive but it is not necessary.
// If multiple threads try to initialize the feature flag, we would only
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(52, "useNativeEqualsInNativeReadableArrayAndroid");
flagValue = currentProvider_->useNativeEqualsInNativeReadableArrayAndroid();
useNativeEqualsInNativeReadableArrayAndroid_ = flagValue;
}
return flagValue.value();
}
bool ReactNativeFeatureFlagsAccessor::useNativeTransformHelperAndroid() {
auto flagValue = useNativeTransformHelperAndroid_.load();
if (!flagValue.has_value()) {
// This block is not exclusive but it is not necessary.
// If multiple threads try to initialize the feature flag, we would only
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(53, "useNativeTransformHelperAndroid");
flagValue = currentProvider_->useNativeTransformHelperAndroid();
useNativeTransformHelperAndroid_ = flagValue;
}
return flagValue.value();
}
bool ReactNativeFeatureFlagsAccessor::useNativeViewConfigsInBridgelessMode() {
auto flagValue = useNativeViewConfigsInBridgelessMode_.load();
@@ -974,7 +1010,7 @@ bool ReactNativeFeatureFlagsAccessor::useNativeViewConfigsInBridgelessMode() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(52, "useNativeViewConfigsInBridgelessMode");
markFlagAsAccessed(54, "useNativeViewConfigsInBridgelessMode");
flagValue = currentProvider_->useNativeViewConfigsInBridgelessMode();
useNativeViewConfigsInBridgelessMode_ = flagValue;
@@ -992,7 +1028,7 @@ bool ReactNativeFeatureFlagsAccessor::useOptimizedEventBatchingOnAndroid() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(53, "useOptimizedEventBatchingOnAndroid");
markFlagAsAccessed(55, "useOptimizedEventBatchingOnAndroid");
flagValue = currentProvider_->useOptimizedEventBatchingOnAndroid();
useOptimizedEventBatchingOnAndroid_ = flagValue;
@@ -1010,7 +1046,7 @@ bool ReactNativeFeatureFlagsAccessor::useRawPropsJsiValue() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(54, "useRawPropsJsiValue");
markFlagAsAccessed(56, "useRawPropsJsiValue");
flagValue = currentProvider_->useRawPropsJsiValue();
useRawPropsJsiValue_ = flagValue;
@@ -1028,7 +1064,7 @@ bool ReactNativeFeatureFlagsAccessor::useShadowNodeStateOnClone() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(55, "useShadowNodeStateOnClone");
markFlagAsAccessed(57, "useShadowNodeStateOnClone");
flagValue = currentProvider_->useShadowNodeStateOnClone();
useShadowNodeStateOnClone_ = flagValue;
@@ -1046,7 +1082,7 @@ bool ReactNativeFeatureFlagsAccessor::useTurboModuleInterop() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(56, "useTurboModuleInterop");
markFlagAsAccessed(58, "useTurboModuleInterop");
flagValue = currentProvider_->useTurboModuleInterop();
useTurboModuleInterop_ = flagValue;
@@ -1064,7 +1100,7 @@ bool ReactNativeFeatureFlagsAccessor::useTurboModules() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(57, "useTurboModules");
markFlagAsAccessed(59, "useTurboModules");
flagValue = currentProvider_->useTurboModules();
useTurboModules_ = flagValue;
@@ -1082,7 +1118,7 @@ double ReactNativeFeatureFlagsAccessor::virtualViewPrerenderRatio() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(58, "virtualViewPrerenderRatio");
markFlagAsAccessed(60, "virtualViewPrerenderRatio");
flagValue = currentProvider_->virtualViewPrerenderRatio();
virtualViewPrerenderRatio_ = flagValue;
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<e5a8a196b35c010d92d3f616979891a9>>
* @generated SignedSource<<74560113d0b23c05d7822eeba1c0dee4>>
*/
/**
@@ -84,6 +84,8 @@ class ReactNativeFeatureFlagsAccessor {
bool updateRuntimeShadowNodeReferencesOnCommit();
bool useAlwaysAvailableJSErrorHandling();
bool useFabricInterop();
bool useNativeEqualsInNativeReadableArrayAndroid();
bool useNativeTransformHelperAndroid();
bool useNativeViewConfigsInBridgelessMode();
bool useOptimizedEventBatchingOnAndroid();
bool useRawPropsJsiValue();
@@ -102,7 +104,7 @@ class ReactNativeFeatureFlagsAccessor {
std::unique_ptr<ReactNativeFeatureFlagsProvider> currentProvider_;
bool wasOverridden_;
std::array<std::atomic<const char*>, 59> accessedFeatureFlags_;
std::array<std::atomic<const char*>, 61> accessedFeatureFlags_;
std::atomic<std::optional<bool>> commonTestFlag_;
std::atomic<std::optional<bool>> animatedShouldSignalBatch_;
@@ -156,6 +158,8 @@ class ReactNativeFeatureFlagsAccessor {
std::atomic<std::optional<bool>> updateRuntimeShadowNodeReferencesOnCommit_;
std::atomic<std::optional<bool>> useAlwaysAvailableJSErrorHandling_;
std::atomic<std::optional<bool>> useFabricInterop_;
std::atomic<std::optional<bool>> useNativeEqualsInNativeReadableArrayAndroid_;
std::atomic<std::optional<bool>> useNativeTransformHelperAndroid_;
std::atomic<std::optional<bool>> useNativeViewConfigsInBridgelessMode_;
std::atomic<std::optional<bool>> useOptimizedEventBatchingOnAndroid_;
std::atomic<std::optional<bool>> useRawPropsJsiValue_;
@@ -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<<9832c18e4c7ccf232b7222e2356f99d9>>
* @generated SignedSource<<1a54000b8eb51cb91304902c7f722d45>>
*/
/**
@@ -235,6 +235,14 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider {
return true;
}
bool useNativeEqualsInNativeReadableArrayAndroid() override {
return false;
}
bool useNativeTransformHelperAndroid() override {
return false;
}
bool useNativeViewConfigsInBridgelessMode() override {
return false;
}
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<19f0a48bcfa8f8ffaf634e85301adc7e>>
* @generated SignedSource<<244db790cc754f31402981967cd902b5>>
*/
/**
@@ -513,6 +513,24 @@ class ReactNativeFeatureFlagsDynamicProvider : public ReactNativeFeatureFlagsDef
return ReactNativeFeatureFlagsDefaults::useFabricInterop();
}
bool useNativeEqualsInNativeReadableArrayAndroid() override {
auto value = values_["useNativeEqualsInNativeReadableArrayAndroid"];
if (!value.isNull()) {
return value.getBool();
}
return ReactNativeFeatureFlagsDefaults::useNativeEqualsInNativeReadableArrayAndroid();
}
bool useNativeTransformHelperAndroid() override {
auto value = values_["useNativeTransformHelperAndroid"];
if (!value.isNull()) {
return value.getBool();
}
return ReactNativeFeatureFlagsDefaults::useNativeTransformHelperAndroid();
}
bool useNativeViewConfigsInBridgelessMode() override {
auto value = values_["useNativeViewConfigsInBridgelessMode"];
if (!value.isNull()) {
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<f33ea0f19a27ec6124d8dbf1a043b4ce>>
* @generated SignedSource<<a045579d42e45fa80831856734a063aa>>
*/
/**
@@ -30,6 +30,14 @@ class ReactNativeFeatureFlagsOverridesOSSExperimental : public ReactNativeFeatur
bool preventShadowTreeCommitExhaustion() override {
return true;
}
bool useNativeEqualsInNativeReadableArrayAndroid() override {
return true;
}
bool useNativeTransformHelperAndroid() override {
return true;
}
};
} // namespace facebook::react
@@ -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<<815769cc8d08e19b2598dd1862ed5060>>
* @generated SignedSource<<2387ed12fe46fb5b606ad13a17511f03>>
*/
/**
@@ -77,6 +77,8 @@ class ReactNativeFeatureFlagsProvider {
virtual bool updateRuntimeShadowNodeReferencesOnCommit() = 0;
virtual bool useAlwaysAvailableJSErrorHandling() = 0;
virtual bool useFabricInterop() = 0;
virtual bool useNativeEqualsInNativeReadableArrayAndroid() = 0;
virtual bool useNativeTransformHelperAndroid() = 0;
virtual bool useNativeViewConfigsInBridgelessMode() = 0;
virtual bool useOptimizedEventBatchingOnAndroid() = 0;
virtual bool useRawPropsJsiValue() = 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<<474a64af739969acebb4bb9bb1005168>>
* @generated SignedSource<<45e1b08fd2438b27af82591b5cfa5744>>
*/
/**
@@ -304,6 +304,16 @@ bool NativeReactNativeFeatureFlags::useFabricInterop(
return ReactNativeFeatureFlags::useFabricInterop();
}
bool NativeReactNativeFeatureFlags::useNativeEqualsInNativeReadableArrayAndroid(
jsi::Runtime& /*runtime*/) {
return ReactNativeFeatureFlags::useNativeEqualsInNativeReadableArrayAndroid();
}
bool NativeReactNativeFeatureFlags::useNativeTransformHelperAndroid(
jsi::Runtime& /*runtime*/) {
return ReactNativeFeatureFlags::useNativeTransformHelperAndroid();
}
bool NativeReactNativeFeatureFlags::useNativeViewConfigsInBridgelessMode(
jsi::Runtime& /*runtime*/) {
return ReactNativeFeatureFlags::useNativeViewConfigsInBridgelessMode();
@@ -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<<bfaa3cc7ab3eeff306337b06b7ae978a>>
* @generated SignedSource<<d1862a9ce3cfeda5d140941fcd3b25bc>>
*/
/**
@@ -140,6 +140,10 @@ class NativeReactNativeFeatureFlags
bool useFabricInterop(jsi::Runtime& runtime);
bool useNativeEqualsInNativeReadableArrayAndroid(jsi::Runtime& runtime);
bool useNativeTransformHelperAndroid(jsi::Runtime& runtime);
bool useNativeViewConfigsInBridgelessMode(jsi::Runtime& runtime);
bool useOptimizedEventBatchingOnAndroid(jsi::Runtime& runtime);
@@ -550,10 +550,14 @@ BorderMetrics BaseViewProps::resolveBorderMetrics(
Transform BaseViewProps::resolveTransform(
const LayoutMetrics& layoutMetrics) const {
const auto& frameSize = layoutMetrics.frame.size;
return resolveTransform(frameSize, transform, transformOrigin);
}
Transform BaseViewProps::resolveTransform(
const Size& frameSize,
const Transform& transform,
const TransformOrigin& transformOrigin) {
auto transformMatrix = Transform{};
if (frameSize.width == 0 && frameSize.height == 0) {
return transformMatrix;
}
// transform is matrix
if (transform.operations.size() == 1 &&
@@ -562,8 +566,7 @@ Transform BaseViewProps::resolveTransform(
} else {
for (const auto& operation : transform.operations) {
transformMatrix = transformMatrix *
Transform::FromTransformOperation(
operation, layoutMetrics.frame.size, transform);
Transform::FromTransformOperation(operation, frameSize, transform);
}
}
@@ -115,6 +115,11 @@ class BaseViewProps : public YogaStylableProps, public AccessibilityProps {
Transform resolveTransform(const LayoutMetrics& layoutMetrics) const;
bool getClipsContentToBounds() const;
static Transform resolveTransform(
const Size& frameSize,
const Transform& transform,
const TransformOrigin& transformOrigin);
#if RN_DEBUG_STRING_CONVERTIBLE
SharedDebugStringConvertibleList getDebugProps() const override;
#endif
@@ -0,0 +1,377 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <gtest/gtest.h>
#include <react/renderer/components/view/BaseViewProps.h>
namespace facebook::react {
namespace {
// For transforms involving rotations, use this helper to fix floating point
// accuracies
void expectTransformsEqual(const Transform& t1, const Transform& t2) {
for (int i = 0; i < 16; i++) {
EXPECT_NEAR(t1.matrix[i], t2.matrix[i], 0.0001);
}
}
} // namespace
class ResolveTransformTest : public ::testing::Test {
protected:
TransformOrigin createTransformOriginPoints(float x, float y, float z = 0) {
TransformOrigin origin;
origin.xy[0] = ValueUnit(x, UnitType::Point);
origin.xy[1] = ValueUnit(y, UnitType::Point);
origin.z = z;
return origin;
}
TransformOrigin createTransformOriginPercent(float x, float y, float z = 0) {
TransformOrigin origin;
origin.xy[0] = ValueUnit(x, UnitType::Percent);
origin.xy[1] = ValueUnit(y, UnitType::Percent);
origin.z = z;
return origin;
}
};
TEST_F(ResolveTransformTest, EmptyFrameNoTransformOrigin) {
Size frameSize{.width = 0, .height = 0};
Transform transform = Transform::Translate(10.0, 20.0, 0.0);
TransformOrigin transformOrigin; // Default (not set)
auto result =
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
// With empty frame size and no transform origin, should just apply the
// transform directly
EXPECT_EQ(result.matrix, transform.matrix);
}
TEST_F(ResolveTransformTest, EmptyFrameTransformOriginPoints) {
Size frameSize{.width = 0, .height = 0};
Transform transform = Transform::Translate(10.0, 20.0, 0.0);
TransformOrigin transformOrigin = createTransformOriginPoints(5, 8);
auto result =
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
// Should handle transform origin even with empty frame size
EXPECT_EQ(result.matrix, Transform::Translate(10.0, 20.0, 0.0).matrix);
}
TEST_F(ResolveTransformTest, EmptyFrameTransformOriginPercent) {
Size frameSize{.width = 0, .height = 0};
Transform transform = Transform::Translate(10.0, 20.0, 0.0);
TransformOrigin transformOrigin = createTransformOriginPercent(50, 50);
auto result =
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
// Transform origin does not affect translate transform
EXPECT_EQ(result.matrix, Transform::Translate(10.0, 20.0, 0.0).matrix);
}
TEST_F(ResolveTransformTest, NonEmptyFrameNoTransformOrigin) {
Size frameSize{.width = 100, .height = 200};
Transform transform = Transform::Translate(10.0, 20.0, 0.0);
TransformOrigin transformOrigin; // Default (not set)
auto result =
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
// Transform origin does not affect translate transform
EXPECT_EQ(result.matrix, Transform::Translate(10.0, 20.0, 0.0).matrix);
}
TEST_F(ResolveTransformTest, NonEmptyFrameTransformOriginPoints) {
Size frameSize{.width = 100, .height = 200};
Transform transform = Transform::Scale(2.0, 1.5, 0.);
TransformOrigin transformOrigin = createTransformOriginPoints(25, 50);
auto result =
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
auto expected = Transform::Translate(25.0, 25.0, 0.0) * transform;
EXPECT_EQ(result.matrix, expected.matrix);
}
TEST_F(ResolveTransformTest, NonEmptyFrameTransformOriginPercent) {
Size frameSize{.width = 100, .height = 200};
Transform transform = Transform::Scale(2.0, 1.5, 0.);
TransformOrigin transformOrigin =
createTransformOriginPercent(25, 75); // 25% width, 75% height
auto result =
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
// Should resolve percentages: 25% of 100 = 25, 75% of 200 = 150
auto expected = Transform::Translate(25.0, -25.0, 0.0) * transform;
EXPECT_EQ(result.matrix, expected.matrix);
}
TEST_F(ResolveTransformTest, IdentityTransformWithOrigin) {
Size frameSize{.width = 100, .height = 200};
Transform transform = Transform::Identity();
TransformOrigin transformOrigin = createTransformOriginPoints(25, 50);
auto result =
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
// Even with identity transform, transform origin should still apply
// translations but they should cancel out, resulting in identity
EXPECT_EQ(result.matrix, transform.matrix);
}
TEST_F(ResolveTransformTest, MultipleTransformOperations) {
Size frameSize{.width = 100, .height = 200};
Transform transform = Transform::Identity();
transform = transform * Transform::Translate(10.0, 20.0, 0.0);
transform = transform * Transform::Scale(2.0, 1.5, 0.0);
TransformOrigin transformOrigin = createTransformOriginPercent(50, 50);
auto result =
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
EXPECT_EQ(result.matrix, transform.matrix);
}
TEST_F(ResolveTransformTest, VariousTransformOriginPositions) {
Size frameSize{.width = 100, .height = 200};
Transform transform = Transform::Scale(2.0, 2.0, 0.);
// Test origin at top-left (0, 0)
TransformOrigin topLeft = createTransformOriginPoints(0, 0);
auto resultTopLeft =
BaseViewProps::resolveTransform(frameSize, transform, topLeft);
auto expected = Transform::Translate(50.0, 100.0, 0.0) * transform;
EXPECT_EQ(resultTopLeft.matrix, expected.matrix);
// Test origin at center (50%, 50%)
TransformOrigin center = createTransformOriginPercent(50, 50);
auto resultCenter =
BaseViewProps::resolveTransform(frameSize, transform, center);
EXPECT_EQ(resultCenter.matrix, transform.matrix);
// Test origin at bottom-right (100%, 100%)
TransformOrigin bottomRight = createTransformOriginPercent(100, 100);
auto resultBottomRight =
BaseViewProps::resolveTransform(frameSize, transform, bottomRight);
expected = Transform::Translate(-50.0, -100.0, 0.0) * transform;
EXPECT_EQ(resultBottomRight.matrix, expected.matrix);
}
// Test with z-component in transform origin
TEST_F(ResolveTransformTest, TransformOriginWithZComponent) {
Size frameSize{.width = 100, .height = 200};
Transform transform = Transform::Scale(1.5, 1.5, 0.);
TransformOrigin transformOrigin;
transformOrigin.xy[0] = ValueUnit(50, UnitType::Point);
transformOrigin.xy[1] = ValueUnit(100, UnitType::Point);
transformOrigin.z = 10.0f;
auto result =
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
auto expected = Transform::Translate(0.0, 0.0, 10.0) * transform;
EXPECT_EQ(result.matrix, expected.matrix);
}
TEST_F(ResolveTransformTest, ArbitraryTransformMatrix) {
Size frameSize{.width = 100, .height = 200};
Transform transform;
transform.operations.push_back({
.type = TransformOperationType::Arbitrary,
.x = ValueUnit(0, UnitType::Point),
.y = ValueUnit(0, UnitType::Point),
.z = ValueUnit(0, UnitType::Point),
});
// Set custom matrix
transform.matrix = {{2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 10, 20, 0, 1}};
TransformOrigin transformOrigin = createTransformOriginPoints(25, 50);
auto result =
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
auto expected = Transform::Translate(25.0, 50.0, 0.0) * transform;
EXPECT_EQ(result.matrix, expected.matrix);
}
// Test rotation with empty frame size and no transform origin
TEST_F(ResolveTransformTest, RotationEmptyFrameNoTransformOrigin) {
Size frameSize{.width = 0, .height = 0};
Transform transform = Transform::RotateZ(M_PI / 4.0); // 45 degrees
TransformOrigin transformOrigin; // Default (not set)
auto result =
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
// With empty frame size and no transform origin, should just apply the
// rotation directly
expectTransformsEqual(result, transform);
}
// Test rotation with empty frame size and transform origin in points
TEST_F(ResolveTransformTest, RotationEmptyFrameTransformOriginPoints) {
Size frameSize{.width = 0, .height = 0};
Transform transform = Transform::RotateZ(M_PI / 4.0); // 45 degrees
TransformOrigin transformOrigin = createTransformOriginPoints(10, 20);
auto result =
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
// With empty frame size, center is (0, 0), so origin offset is (10, 20)
auto expected = Transform::Translate(10.0, 20.0, 0.0) * transform *
Transform::Translate(-10.0, -20.0, 0.0);
expectTransformsEqual(result, expected);
}
// Test rotation with empty frame size and transform origin in percentages
TEST_F(ResolveTransformTest, RotationEmptyFrameTransformOriginPercent) {
Size frameSize{.width = 0, .height = 0};
Transform transform = Transform::RotateZ(M_PI / 6.0); // 30 degrees
TransformOrigin transformOrigin = createTransformOriginPercent(50, 50);
auto result =
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
// With 0 frame size, percentages resolve to 0, so no origin offset
expectTransformsEqual(result, transform);
}
// Test rotation with non-empty frame size and no transform origin
TEST_F(ResolveTransformTest, RotationNonEmptyFrameNoTransformOrigin) {
Size frameSize{.width = 100, .height = 200};
Transform transform = Transform::RotateZ(M_PI / 3.0); // 60 degrees
TransformOrigin transformOrigin; // Default (not set)
auto result =
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
// Without transform origin, rotation should happen around default center
expectTransformsEqual(result, transform);
}
// Test rotation with non-empty frame size and transform origin in points
TEST_F(ResolveTransformTest, RotationNonEmptyFrameTransformOriginPoints) {
Size frameSize{.width = 100, .height = 200};
Transform transform = Transform::RotateZ(M_PI / 4.0); // 45 degrees
TransformOrigin transformOrigin = createTransformOriginPoints(25, 50);
auto result =
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
// Center of 100x200 frame is (50, 100), origin at (25, 50) means offset of
// (-25, -50)
auto expected = Transform::Translate(-25.0, -50.0, 0.0) * transform *
Transform::Translate(25.0, 50.0, 0.0);
expectTransformsEqual(result, expected);
}
// Test rotation with non-empty frame size and transform origin in percentages
TEST_F(ResolveTransformTest, RotationNonEmptyFrameTransformOriginPercent) {
Size frameSize{.width = 100, .height = 200};
Transform transform = Transform::RotateZ(M_PI / 2.0); // 90 degrees
TransformOrigin transformOrigin =
createTransformOriginPercent(25, 75); // 25% width, 75% height
auto result =
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
// Should resolve percentages: 25% of 100 = 25, 75% of 200 = 150
// Center is (50, 100), so origin offset is (25-50, 150-100) = (-25, 50)
auto expected = Transform::Translate(-25.0, 50.0, 0.0) * transform *
Transform::Translate(25.0, -50.0, 0.0);
expectTransformsEqual(result, expected);
}
// Test rotation with mixed transform origin units
TEST_F(ResolveTransformTest, RotationMixedTransformOriginUnits) {
Size frameSize{.width = 100, .height = 200};
Transform transform = Transform::RotateZ(M_PI); // 180 degrees
TransformOrigin transformOrigin;
transformOrigin.xy[0] = ValueUnit(30, UnitType::Point); // 30 points
transformOrigin.xy[1] = ValueUnit(25, UnitType::Percent); // 25% of 200 = 50
transformOrigin.z = 0;
auto result =
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
// Center is (50, 100), origin is (30, 50), so offset is (-20, -50)
auto expected = Transform::Translate(-20.0, -50.0, 0.0) * transform *
Transform::Translate(20.0, 50.0, 0.0);
expectTransformsEqual(result, expected);
}
// Test multiple rotations (RotateX, RotateY, RotateZ)
TEST_F(ResolveTransformTest, MultipleRotationsWithTransformOrigin) {
Size frameSize{.width = 100, .height = 100};
Transform transform = Transform::Rotate(M_PI / 6.0, M_PI / 4.0, M_PI / 3.0);
TransformOrigin transformOrigin = createTransformOriginPercent(50, 50);
auto result =
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
expectTransformsEqual(result, transform);
}
// Test rotation with z-component in transform origin
TEST_F(ResolveTransformTest, RotationWithZTransformOrigin) {
Size frameSize{.width = 100, .height = 200};
Transform transform = Transform::RotateZ(M_PI / 4.0); // 45 degrees
TransformOrigin transformOrigin;
transformOrigin.xy[0] = ValueUnit(50, UnitType::Point);
transformOrigin.xy[1] = ValueUnit(100, UnitType::Point);
transformOrigin.z = 15.0f;
auto result =
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
// Center is (50, 100), origin is (50, 100, 15), so offset is (0, 0, 15)
auto expected = Transform::Translate(0.0, 0.0, 15.0) * transform *
Transform::Translate(0.0, 0.0, -15.0);
expectTransformsEqual(result, expected);
}
// Test rotation at different origin positions (corners vs center)
TEST_F(ResolveTransformTest, RotationDifferentOriginPositions) {
Size frameSize{.width = 100, .height = 100};
Transform transform = Transform::RotateZ(M_PI / 2.0); // 90 degrees
// Test rotation around top-left corner (0, 0)
TransformOrigin topLeft = createTransformOriginPoints(0, 0);
auto resultTopLeft =
BaseViewProps::resolveTransform(frameSize, transform, topLeft);
auto expectedTopLeft = Transform::Translate(-50.0, -50.0, 0.0) * transform *
Transform::Translate(50.0, 50.0, 0.0);
expectTransformsEqual(resultTopLeft, expectedTopLeft);
// Test rotation around center (50%, 50%)
TransformOrigin center = createTransformOriginPercent(50, 50);
auto resultCenter =
BaseViewProps::resolveTransform(frameSize, transform, center);
expectTransformsEqual(resultCenter, transform);
// Test rotation around bottom-right corner (100%, 100%)
TransformOrigin bottomRight = createTransformOriginPercent(100, 100);
auto resultBottomRight =
BaseViewProps::resolveTransform(frameSize, transform, bottomRight);
auto expectedBottomRight = Transform::Translate(50.0, 50.0, 0.0) * transform *
Transform::Translate(-50.0, -50.0, 0.0);
expectTransformsEqual(resultBottomRight, expectedBottomRight);
}
} // namespace facebook::react
@@ -16,7 +16,9 @@ add_library(bridgeless
${bridgeless_SRC}
)
target_compile_reactnative_options(bridgeless PRIVATE)
target_compile_options(bridgeless PRIVATE $<$<CONFIG:Debug>:-DHERMES_ENABLE_DEBUGGER=1>)
if(${CMAKE_BUILD_TYPE} MATCHES Debug OR REACT_NATIVE_DEBUG_OPTIMIZED)
target_compile_options(bridgeless PRIVATE -DHERMES_ENABLE_DEBUGGER=1)
endif ()
target_include_directories(bridgeless PUBLIC .)
react_native_android_selector(fabricjni fabricjni "")
@@ -29,7 +29,7 @@ target_link_libraries(bridgelesshermes
)
target_compile_reactnative_options(bridgelesshermes PRIVATE)
if(${CMAKE_BUILD_TYPE} MATCHES Debug)
if(${CMAKE_BUILD_TYPE} MATCHES Debug OR REACT_NATIVE_DEBUG_OPTIMIZED)
target_compile_options(
bridgelesshermes
PRIVATE
+8 -8
View File
@@ -1,6 +1,6 @@
{
"name": "react-native",
"version": "0.81.1",
"version": "0.81.5",
"description": "A framework for building native apps using React",
"license": "MIT",
"repository": {
@@ -162,13 +162,13 @@
},
"dependencies": {
"@jest/create-cache-key-function": "^29.7.0",
"@react-native/assets-registry": "0.81.1",
"@react-native/codegen": "0.81.1",
"@react-native/community-cli-plugin": "0.81.1",
"@react-native/gradle-plugin": "0.81.1",
"@react-native/js-polyfills": "0.81.1",
"@react-native/normalize-colors": "0.81.1",
"@react-native/virtualized-lists": "0.81.1",
"@react-native/assets-registry": "0.81.5",
"@react-native/codegen": "0.81.5",
"@react-native/community-cli-plugin": "0.81.5",
"@react-native/gradle-plugin": "0.81.5",
"@react-native/js-polyfills": "0.81.5",
"@react-native/normalize-colors": "0.81.5",
"@react-native/virtualized-lists": "0.81.5",
"abort-controller": "^3.0.0",
"anser": "^1.4.9",
"ansi-regex": "^5.0.0",
@@ -40,6 +40,12 @@ def list_native_modules!(config_command)
packages = config["dependencies"]
ios_project_root = Pathname.new(config["project"]["ios"]["sourceDir"])
react_native_path = Pathname.new(config["reactNativePath"])
codegen_output_path = ios_project_root.join("build/generated/autolinking/autolinking.json")
# Write autolinking react-native-config output to codegen folder
FileUtils.mkdir_p(File.dirname(codegen_output_path))
File.write(codegen_output_path, json)
found_pods = []
packages.each do |package_name, package|
@@ -87,7 +87,7 @@ class CodegenUtils
codegen_path = file_manager.join(ios_folder, codegen_dir)
return if !dir_manager.exist?(codegen_path)
FileUtils.rm_rf(dir_manager.glob("#{codegen_path}/*"))
FileUtils.rm_rf("#{codegen_path}")
base_provider_path = file_manager.join(rn_path, 'React', 'Fabric', 'RCTThirdPartyFabricComponentsProvider')
FileUtils.rm_rf("#{base_provider_path}.h")
FileUtils.rm_rf("#{base_provider_path}.mm")
@@ -361,7 +361,7 @@ exports[`execute test-app "ReactAppDependencyProvider.podspec" should match snap
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
version = \\"0.81.1\\"
version = \\"0.81.5\\"
source = { :git => 'https://github.com/facebook/react-native.git' }
if version == '1000.0.0'
# This is an unpublished version, use the latest commit hash of the react-native repo, which were presumably in.
@@ -399,7 +399,7 @@ exports[`execute test-app "ReactCodegen.podspec" should match snapshot 1`] = `
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
version = \\"0.81.1\\"
version = \\"0.81.5\\"
source = { :git => 'https://github.com/facebook/react-native.git' }
if version == '1000.0.0'
# This is an unpublished version, use the latest commit hash of the react-native repo, which were presumably in.
@@ -840,7 +840,7 @@ exports[`execute test-app-legacy "ReactAppDependencyProvider.podspec" should mat
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
version = \\"0.81.1\\"
version = \\"0.81.5\\"
source = { :git => 'https://github.com/facebook/react-native.git' }
if version == '1000.0.0'
# This is an unpublished version, use the latest commit hash of the react-native repo, which were presumably in.
@@ -878,7 +878,7 @@ exports[`execute test-app-legacy "ReactCodegen.podspec" should match snapshot 1`
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
version = \\"0.81.1\\"
version = \\"0.81.5\\"
source = { :git => 'https://github.com/facebook/react-native.git' }
if version == '1000.0.0'
# This is an unpublished version, use the latest commit hash of the react-native repo, which were presumably in.
@@ -86,16 +86,19 @@ function execute(
buildCodegenIfNeeded();
}
const reactNativeConfig = readReactNativeConfig(projectRoot);
const reactNativeConfig = readReactNativeConfig(
projectRoot,
baseOutputPath,
);
const codegenEnabledLibraries = findCodegenEnabledLibraries(
pkgJson,
projectRoot,
baseOutputPath,
reactNativeConfig,
);
if (codegenEnabledLibraries.length === 0) {
codegenLog('No codegen-enabled libraries found.', true);
return;
}
let platforms =
@@ -110,10 +113,6 @@ function execute(
({name}) => !disabledLibraries.includes(name),
);
if (!libraries.length) {
continue;
}
const outputPath = computeOutputPath(
projectRoot,
baseOutputPath,
@@ -97,15 +97,40 @@ function cleanupEmptyFilesAndFolders(filepath /*: string */) {
}
}
function readReactNativeConfig(projectRoot /*: string */) /*: $FlowFixMe */ {
const rnConfigFilePath = path.resolve(projectRoot, 'react-native.config.js');
function readGeneratedAutolinkingOutput(
baseOutputPath /*: string */,
) /*: $FlowFixMe */ {
// NOTE: Generated by scripts/cocoapods/autolinking.rb in list_native_modules (called by use_native_modules)
const autolinkingGeneratedPath = path.resolve(
baseOutputPath,
'build/generated/autolinking/autolinking.json',
);
if (fs.existsSync(autolinkingGeneratedPath)) {
// $FlowFixMe[unsupported-syntax]
return require(autolinkingGeneratedPath);
} else {
codegenLog(
`Could not find generated autolinking output at: ${autolinkingGeneratedPath}`,
);
return null;
}
}
if (!fs.existsSync(rnConfigFilePath)) {
function readReactNativeConfig(
projectRoot /*: string */,
baseOutputPath /*: string */,
) /*: $FlowFixMe */ {
const autolinkingOutput = readGeneratedAutolinkingOutput(baseOutputPath);
const rnConfigFilePath = path.resolve(projectRoot, 'react-native.config.js');
if (autolinkingOutput) {
return autolinkingOutput;
} else if (fs.existsSync(rnConfigFilePath)) {
// $FlowIgnore[unsupported-syntax]
return require(rnConfigFilePath);
} else {
codegenLog(`Could not find React Native config at: ${rnConfigFilePath}`);
return {};
}
// $FlowIgnore[unsupported-syntax]
return require(rnConfigFilePath);
}
/**
@@ -114,17 +139,23 @@ function readReactNativeConfig(projectRoot /*: string */) /*: $FlowFixMe */ {
function findCodegenEnabledLibraries(
pkgJson /*: $FlowFixMe */,
projectRoot /*: string */,
baseOutputPath /*: string */,
reactNativeConfig /*: $FlowFixMe */,
) /*: Array<$FlowFixMe> */ {
const projectLibraries = findProjectRootLibraries(pkgJson, projectRoot);
if (pkgJsonIncludesGeneratedCode(pkgJson)) {
return projectLibraries;
} else {
return [
...projectLibraries,
...findExternalLibraries(pkgJson, projectRoot),
const libraries = [...projectLibraries];
// If we ran autolinking, we shouldn't try to run our own "autolinking-like"
// library discovery
if (!readGeneratedAutolinkingOutput(baseOutputPath)) {
libraries.push(...findExternalLibraries(pkgJson, projectRoot));
}
libraries.push(
...findLibrariesFromReactNativeConfig(projectRoot, reactNativeConfig),
];
);
return libraries;
}
}
@@ -595,6 +595,27 @@ const definitions: FeatureFlagDefinitions = {
},
ossReleaseStage: 'none',
},
useNativeEqualsInNativeReadableArrayAndroid: {
defaultValue: false,
metadata: {
dateAdded: '2025-07-15',
description:
'Use a native implementation of equals in NativeReadableArray.',
expectedReleaseValue: true,
purpose: 'experimentation',
},
ossReleaseStage: 'experimental',
},
useNativeTransformHelperAndroid: {
defaultValue: false,
metadata: {
dateAdded: '2025-07-15',
description: 'Use a native implementation of TransformHelper',
expectedReleaseValue: true,
purpose: 'experimentation',
},
ossReleaseStage: 'experimental',
},
useNativeViewConfigsInBridgelessMode: {
defaultValue: false,
metadata: {
+4 -2
View File
@@ -10,7 +10,7 @@
'use strict';
const {execSync} = require('child_process');
const {spawnSync} = require('child_process');
const fs = require('fs');
const yargs = require('yargs');
@@ -67,7 +67,9 @@ function replaceRNCoreConfiguration(
fs.mkdirSync(finalLocation, {recursive: true});
console.log('Extracting the tarball', tarballURLPath);
execSync(`tar -xf ${tarballURLPath} -C ${finalLocation}`);
spawnSync('tar', ['-xf', tarballURLPath, '-C', finalLocation], {
stdio: 'inherit',
});
}
function updateLastBuildConfiguration(configuration /*: string */) {
@@ -10,7 +10,7 @@
'use strict';
const {execSync} = require('child_process');
const {spawnSync} = require('child_process');
const fs = require('fs');
const yargs = require('yargs');
@@ -62,7 +62,9 @@ function replaceHermesConfiguration(configuration, version, podsRoot) {
fs.mkdirSync(finalLocation, {recursive: true});
console.log('Extracting the tarball');
execSync(`tar -xf ${tarballURLPath} -C ${finalLocation}`);
spawnSync('tar', ['-xf', tarballURLPath, '-C', finalLocation], {
stdio: 'inherit',
});
}
function updateLastBuildConfiguration(configuration) {
@@ -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<<999a8d329cdab258ac64c03b24f1a516>>
* @generated SignedSource<<f17b8e4e33228e19b346837e7a33a2dd>>
* @flow strict
* @noformat
*/
@@ -103,6 +103,8 @@ export type ReactNativeFeatureFlags = $ReadOnly<{
updateRuntimeShadowNodeReferencesOnCommit: Getter<boolean>,
useAlwaysAvailableJSErrorHandling: Getter<boolean>,
useFabricInterop: Getter<boolean>,
useNativeEqualsInNativeReadableArrayAndroid: Getter<boolean>,
useNativeTransformHelperAndroid: Getter<boolean>,
useNativeViewConfigsInBridgelessMode: Getter<boolean>,
useOptimizedEventBatchingOnAndroid: Getter<boolean>,
useRawPropsJsiValue: Getter<boolean>,
@@ -404,6 +406,14 @@ export const useAlwaysAvailableJSErrorHandling: Getter<boolean> = createNativeFl
* Should this application enable the Fabric Interop Layer for Android? If yes, the application will behave so that it can accept non-Fabric components and render them on Fabric. This toggle is controlling extra logic such as custom event dispatching that are needed for the Fabric Interop Layer to work correctly.
*/
export const useFabricInterop: Getter<boolean> = createNativeFlagGetter('useFabricInterop', true);
/**
* Use a native implementation of equals in NativeReadableArray.
*/
export const useNativeEqualsInNativeReadableArrayAndroid: Getter<boolean> = createNativeFlagGetter('useNativeEqualsInNativeReadableArrayAndroid', false);
/**
* Use a native implementation of TransformHelper
*/
export const useNativeTransformHelperAndroid: Getter<boolean> = createNativeFlagGetter('useNativeTransformHelperAndroid', false);
/**
* When enabled, the native view configs are used in bridgeless mode.
*/
@@ -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<<1b84b6e04c214f6c2798010372937990>>
* @generated SignedSource<<8b4f1275a16d5b83f5594da1eb89c6c1>>
* @flow strict
* @noformat
*/
@@ -77,6 +77,8 @@ export interface Spec extends TurboModule {
+updateRuntimeShadowNodeReferencesOnCommit?: () => boolean;
+useAlwaysAvailableJSErrorHandling?: () => boolean;
+useFabricInterop?: () => boolean;
+useNativeEqualsInNativeReadableArrayAndroid?: () => boolean;
+useNativeTransformHelperAndroid?: () => boolean;
+useNativeViewConfigsInBridgelessMode?: () => boolean;
+useOptimizedEventBatchingOnAndroid?: () => boolean;
+useRawPropsJsiValue?: () => boolean;
@@ -62,7 +62,7 @@ Pod::Spec.new do |spec|
exit 0
fi
cp -R "$HEADERS_PATH/" Headers
cp -R "$HEADERS_PATH/." Headers
mkdir -p framework/packages/react-native
cp -R "$XCFRAMEWORK_PATH/../." framework/packages/react-native/
find "$XCFRAMEWORK_PATH/.." -type f -exec rm {} +
@@ -10,7 +10,7 @@
'use strict';
const {execSync} = require('child_process');
const {spawnSync} = require('child_process');
const fs = require('fs');
const yargs = require('yargs');
@@ -66,7 +66,9 @@ function replaceRNDepsConfiguration(
fs.mkdirSync(finalLocation, {recursive: true});
console.log('Extracting the tarball', tarballURLPath);
execSync(`tar -xf ${tarballURLPath} -C ${finalLocation}`);
spawnSync('tar', ['-xf', tarballURLPath, '-C', finalLocation], {
stdio: 'inherit',
});
// Now we need to remove the extra third-party folder as we do in the podspec's prepare-script
// We need to take the ReactNativeDependencies.xcframework folder and move it up one level
File diff suppressed because it is too large Load Diff
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<application android:usesCleartextTraffic="true" tools:targetApi="28" tools:ignore="GoogleAppIndexingWarning" />
</manifest>
@@ -50,6 +50,7 @@
</queries>
<application
android:usesCleartextTraffic="${usesCleartextTraffic}"
android:name=".RNTesterApplication"
android:allowBackup="true"
android:banner="@drawable/tv_banner"
+2 -2
View File
@@ -27,8 +27,8 @@
},
"dependencies": {
"@react-native/oss-library-example": "0.81.0-main",
"@react-native/new-app-screen": "0.81.1",
"@react-native/popup-menu-android": "0.81.1",
"@react-native/new-app-screen": "0.81.5",
"@react-native/popup-menu-android": "0.81.5",
"flow-enums-runtime": "^0.0.6",
"invariant": "^2.2.4",
"nullthrows": "^1.1.1"
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/typescript-config",
"version": "0.81.1",
"version": "0.81.5",
"description": "Default TypeScript configuration for React Native apps",
"license": "MIT",
"repository": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/virtualized-lists",
"version": "0.81.1",
"version": "0.81.5",
"description": "Virtualized lists for React Native.",
"license": "MIT",
"repository": {
+6 -6
View File
@@ -13,17 +13,17 @@
},
"dependencies": {
"react": "19.1.0",
"react-native": "0.81.1"
"react-native": "0.81.5"
},
"devDependencies": {
"@babel/core": "^7.25.2",
"@babel/preset-env": "^7.25.3",
"@babel/runtime": "^7.25.0",
"@react-native/babel-preset": "0.81.1",
"@react-native/core-cli-utils": "0.81.1",
"@react-native/eslint-config": "0.81.1",
"@react-native/metro-config": "0.81.1",
"@react-native/typescript-config": "0.81.1",
"@react-native/babel-preset": "0.81.5",
"@react-native/core-cli-utils": "0.81.5",
"@react-native/eslint-config": "0.81.5",
"@react-native/metro-config": "0.81.5",
"@react-native/typescript-config": "0.81.5",
"@types/jest": "^29.5.14",
"commander": "^12.0.0",
"eslint": "^8.19.0",

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