Compare commits

...
128 Commits
Author SHA1 Message Date
Nicola Corti 75dc002a52 Move React Native publishing URLs to Central Portal (#51693)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/51693

This moves React Native to use the Central Portal URLs rather than the legacy OSSRH ones.
See https://github.com/gradle-nexus/publish-plugin for more context.

Changelog:
[Internal] [Changed] -

Reviewed By: cipolleschi

Differential Revision: D75673984

fbshipit-source-id: 1de6746809eed72f232eac0c3fb4d809c2046620
2025-06-16 10:47:18 +01:00
distiller 6304cce015 [0.72.17] Bump version numbers 2024-08-19 14:00:35 +00:00
Riccardo Cipolleschi ce34674382 [LOCAL] bump podfile.lock 2024-08-19 14:55:54 +01:00
Riccardo Cipolleschi ab7e77c024 Revert "[LOCAL] Bump Hermes"
This reverts commit ccdb8b58db.
2024-08-19 11:20:32 +01:00
Riccardo Cipolleschi cedd6385b5 Revert "[0.72.17] Bump version numbers"
This reverts commit bb8ddab2a8.
2024-08-19 11:16:12 +01:00
Riccardo Cipolleschi ccdb8b58db [LOCAL] Bump Hermes 2024-08-19 10:32:17 +01:00
Siddharth 123cec3de5 update podfile.lock 2024-08-16 16:39:17 -07:00
distiller bb8ddab2a8 [0.72.17] Bump version numbers 2024-08-16 22:40:57 +00:00
Siddharth Kulkarni 524a48dce6 update Podfile.lock 2024-08-01 14:16:45 -07:00
distiller 337dcaa54a [0.72.16] Bump version numbers 2024-08-01 20:14:59 +00:00
siddharthkul da0f8ac060 Fix Privacy Manifest file path by providing targets 2024-07-23 08:59:35 -07:00
Riccardo Cipolleschi 350779af17 [CI] Move machines to M1 for 0.72 2024-07-22 11:17:43 -07:00
Rui Ying b5b3f3c43d Handle the case where the file reference doesn't have a path (#44410) 2024-07-22 11:17:10 -07:00
Alfonso Curbelo e24be3072c update Podfile.lock 2024-06-13 10:21:01 -04:00
Distiller 4cee0a4c06 [0.72.15] Bump version numbers 2024-06-12 13:29:08 +00:00
Alfonso Curbelo 5c77748632 Fix bad cherry-pick conflict in react_native_pods (2) 2024-06-10 12:56:28 -04:00
Alfonso Curbelo b7c2a1c88d Fix bad cherry-pick conflict in react_native_pods 2024-06-10 11:48:12 -04:00
Renaud Chaput 38ad610021 Fix Privacy Manifest generator when it does not contain a NSPrivacyAccessedAPITypes key (#44628)
Summary:
XCode privacy files might not contain a `NSPrivacyAccessedAPITypes` key, which causes the following error:

```
[!] An error occurred while processing the post-install hook of the Podfile.

undefined method `each' for nil

node_modules/react-native/scripts/cocoapods/privacy_manifest_utils.rb:111:in `block (4 levels) in get_used_required_reason_apis'
node_modules/react-native/scripts/cocoapods/privacy_manifest_utils.rb:106:in `each'
node_modules/react-native/scripts/cocoapods/privacy_manifest_utils.rb:106:in `block (3 levels) in get_used_required_reason_apis'
```

<!-- 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] - Privacy Manifest aggregation failing due to no `NSPrivacyAccessedAPITypes` key

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

Test Plan: I tested this patch on our own app and it solved the issue.

Reviewed By: christophpurrer

Differential Revision: D57618425

Pulled By: cipolleschi

fbshipit-source-id: 1a36ab5a1bb45b8507d3663b782c95258d97c8a4
2024-06-10 10:09:18 -04:00
aleqsio 48e9e62846 Implement privacy manifest aggregation (#44214)
Summary:
As of now, Apple does not respect privacy manifests added as cocoapods resource bundles. This forces react-native developers to manually copy `.xcprivacy` files content for each native dependency that accesses restricted reason APIs to the root file.

This PR adds an aggregation step that crawls through pod dependencies to collect all reasons into the root privacy info file.

[IOS][ADDED] – Add privacy manifest aggregation.

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

Test Plan:
When run on RNTester, it appends aggregated entries (while keeping existing ones) to existing .xcprivacy file without modifing .pbxproj:
![image](https://github.com/facebook/react-native/assets/5597580/1d07a07d-bbec-4266-a599-a8d629078971)

When run on RNTester with the xcprivacy file removed from xcode beforehand, it creates a new .xcprivacy file, and adds it to Compile Bundle Resources in the same way as in the new template:
![image](https://github.com/facebook/react-native/assets/5597580/f80a3b4e-e41a-4906-8e2f-06cca0bc225a)

When run on RNTester with an empty .xcprivacy file, it appends aggregated entries from pods AND reasons for react-native core.

When run with `privacy_file_aggregation_enabled: false` in `use_react_native`, it falls back to existing behavior:
![image](https://github.com/facebook/react-native/assets/5597580/4519bba1-c80e-4cd0-b19c-bbbebfa8493b)

Reviewed By: cipolleschi

Differential Revision: D56481045

Pulled By: philIip

fbshipit-source-id: 1841bad821511c734d0cc0fcff5065ed92af76d8
2024-06-10 10:05:23 -04:00
hurali97 d724007364 [LOCAL] update podfile.lock 2024-04-30 17:41:59 +05:00
Distiller 33865b9899 [0.72.14] Bump version numbers 2024-04-30 09:08:10 +00:00
Muhammad Hur Ali 9322b5cabf Merge pull request #44317 from facebook/hur/pick-pr-42978-for-072
add privacy manifest to hello world template
2024-04-29 20:25:54 +05:00
hurali97 d357a61ead pick 42978 add privacy manifest to hello world template 2024-04-29 20:19:59 +05:00
hurali97 ee14572e24 [LOCAL] Bump Hermes 2024-04-29 14:50:45 +05:00
Riccardo Cipolleschi ae4c62a933 Fix Symbol not found: (_JSGlobalContextSetInspectable) (#44185)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/44185

This change will fix a symbol not found for JSC Runtime.

The `if` check was not a compile time check, therefore the symbol ended up in the binary even if it is not available.

Following this post on [Apple forum](https://forums.developer.apple.com/forums/thread/749534), this changes should do the trick.

## Changelog
[iOS][Fixed] - Fix Symbol not found: (_JSGlobalContextSetInspectable)

Reviewed By: hash3r

Differential Revision: D56425834

fbshipit-source-id: a37af51b078bd47a938e6b65d9d8e0f7506e746f
2024-04-29 14:44:07 +05:00
Alan Hughes 21010037e1 Bump Podfile.lock 2024-04-18 21:50:41 +01:00
Distiller 9a369f4036 [0.72.13] Bump version numbers 2024-04-18 15:37:03 +00:00
Phillip Pan f3ecc0bf73 add privacy manifest to pod install
Summary:
Changelog: [iOS][Added]

this creates the RN privacy manifest in the ios build step if user has not created one yet. the reasons have been added for the following APIs:

NSPrivacyAccessedAPICategoryFileTimestamp
- C617.1: We use fstat and stat in a few places in the C++ layer. We use these to read information about the JavaScript files in RN.

NSPrivacyAccessedAPICategoryUserDefaults
- CA92.1: We access NSUserDefaults in a few places.
1) To store RTL preferences
2) As part of caching server URLs for developer mode
3) A generic native module that wraps NSUserDefaults

NSPrivacyAccessedAPICategorySystemBootTime
- 35F9.1: Best guess reason from RR API pulled in by boost

Reviewed By: cipolleschi

Differential Revision: D53687232

fbshipit-source-id: 6dffb1a6013f8f29438a49752e47ed75c13f4a5c
2024-04-16 09:16:16 +01:00
Evert Eti 250ab8211c Fix possible deadlock in dispatchViewUpdates (#43643)
Summary:
In https://github.com/th3rdwave/react-native-safe-area-context/issues/448 it was noticed that from 0.72 (https://github.com/facebook/react-native/commit/bc766ec7f8b18ddc0ff72a2fff5783eeeff24857 https://github.com/facebook/react-native/pull/35889) it was possible to get a deadlock in dispatchViewUpdates. ([More details](https://github.com/th3rdwave/react-native-safe-area-context/issues/448#issuecomment-1871155936))

This deadlock resulted in a laggy experience for all users using https://github.com/th3rdwave/react-native-safe-area-context/ on Android.

To avoid this problem, the author of the original fix [proposed](https://github.com/th3rdwave/react-native-safe-area-context/issues/448#issuecomment-1872121172) this solution which was tested by Discord and many other users.

It would be great to have this backported to 0.72 and 0.73 because of the large userbase using react-native-safe-area-context since it's recommended by expo and react-navigation.

<!-- Help reviewers and the release process by writing your own changelog entry.

Pick one each for the category and type tags:

[ANDROID] [FIXED] - Fixed possible deadlock in dispatchViewUpdates

For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests
-->

[ANDROID] [FIXED] - Fixed possible deadlock in dispatchViewUpdates

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

Test Plan:
The original memory leak remains fixed, and can be verified in https://github.com/feiyin0719/RNMemoryLeakAndroid.

To verify the deadlock is gone, every app using https://github.com/th3rdwave/react-native-safe-area-context will work smoothly and not log any excessive `Timed out waiting for layout`
(https://github.com/17Amir17/SafeAreaContext)

Reviewed By: arushikesarwani94

Differential Revision: D55339059

Pulled By: zeyap

fbshipit-source-id: c067997364fbec734510ce99b9994e89d044384a
2024-04-09 15:16:38 +01:00
Alfonso Curbelo d5648f8e79 Podfile.lock bump 2024-03-11 14:27:09 -04:00
Distiller b418498807 [0.72.12] Bump version numbers 2024-03-11 15:52:02 +00:00
Rick Hanlon dd311c9782 Fix component stacks for tsx, ts, and jsx files (#43370)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43370

Component stacks with files ending in .ts, .tsx, or .jsx were skipped in LogBox reporting. This diff fixes the regex.

Changelog:
[General][Fixed] - Support .tsx, .ts, and .jsx in component stacks

Reviewed By: yungsters

Differential Revision: D54638526

fbshipit-source-id: a5271daaa7b687e8e075be3f94ab9b9c03f79b66
2024-03-08 12:55:14 -05:00
Alfonso Curbelo 1d69e2fbac Merge pull request #43344 from facebook/cipolleschi/fix-flipper-072
[RN][iOS][0.72] Fix flipper for Xcode 15.3
2024-03-07 17:14:12 -05:00
Riccardo Cipolleschi a316e0154e [RN][iOS][0.72] Fix flipper for Xcode 15.3 2024-03-06 19:34:56 +00:00
Riccardo Cipolleschi 0724c2769a [RN][IOS] Fix flags for new arch 2024-02-29 18:32:47 +00:00
Riccardo Cipolleschi a215805eb7 [RN][iOS]Rename BUILD_FROM_SOURCE to RCT_BUILD_HERMES_FROM_SOURCE 2024-02-29 18:32:36 +00:00
Distiller e8e03a4240 [0.72.11] Bump version numbers 2024-02-28 16:59:38 +00:00
hurali97 a0142432a7 bumped packages versions
#publish-packages-to-npm
2024-02-27 13:17:04 +05:00
Luna Wei 2f77e408a3 local - delete test_windows, choco -y 2024-02-26 13:18:51 -08:00
Szymon Rybczak c57a29a08c Upgrade CLI to 11.4.1 (#43096) 2024-02-19 12:56:25 -08:00
Ken Tominaga a4282a91c3 Fix overriding EXCLUDED_ARCHS when installing Hermes on RN v0.72 (#43002) 2024-02-16 15:57:47 -08:00
LIM Albert 5de1d4f932 Call super.onRequestPermissionsResult in ReactActivity (#42478)
Summary:
This change allows activities to handle onRequestPermissionsResult callbacks (eg: registerForActivityResult)

Fixes #42403

[Android][Changed] - Call super.onRequestPermissionsResult in ReactActivity's onRequestPermissionsResult()

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

Test Plan:
**Without super.onRequestPermissionsResult() call**

![before](https://github.com/facebook/react-native/assets/8672580/553ff597-c077-4831-a4d3-51846a253536)

**With super.onRequestPermissionsResult() call**

![after](https://github.com/facebook/react-native/assets/8672580/c7d588d2-5846-4083-a02f-59b5f915442c)

Reviewed By: cipolleschi

Differential Revision: D52952198

Pulled By: cortinico

fbshipit-source-id: 53b5dac65f6b5409d87b5fe7f8be659d7b48f70d
2024-02-16 15:56:02 -08:00
huangtaibin c8e9836c18 Fix crash in getChildDrawingOrder (#40859)
Summary:
Problem Causes: In ReactViewGroup, there is a conflict between the zIndex attribute and the removeClippedSubviews optimization attribute. When both are used at the same time, the array mDrawingOrderIndices in ViewGroupDrawingOrderHelper that records the rendering order of subviews is not reset when super is called in the updateSubviewClipStatus method to add and remove subviews.

Solution:�Because there are many third-party components that inherit from or depend on ReactViewGroup, all methods for adding and removing subviews in ViewGroup need to be override in ReactViewGroup, and ViewGroupDrawingOrderHelper corresponding to handleAddView and handleRemoveView needs to be called in these methods. And all the precautions for directly calling super to add and remove subviews are changed to calling the overridden method by ReactViewGroup.

Special Note: All addView related methods in ViewGroup will eventually be called to the addView(View child, int index, LayoutParams params) method, except addViewInLayout. Regarding the method of adding subviews, we only need to override  addView(View child, int index, LayoutParams params) and addViewInLayout(View child, int index, LayoutParams params,boolean preventRequestLayout) in ReactViewGroup.

## Changelog:
[Android] [Fixed] - Fix the crash in ReactViewGroup of https://github.com/facebook/react-native/issues/30785

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

Reviewed By: NickGerleman

Differential Revision: D50321718

Pulled By: javache

fbshipit-source-id: 7fa7069937b8c2afb9f30dd10554370b1be5d515
2024-02-16 15:37:22 -08:00
Riccardo Cipolleschi 6939021518 [RN][iOS] Improve Swift support for 3rd party libs (#42075) 2024-02-16 15:31:39 -08:00
Luna Wei c3fda24003 Local: Update rn-tester podfile 2024-02-16 15:22:04 -08:00
Rob Hogan ddff36f770 Update Metro to ^0.76.9, CLI to ^11.4.0 2024-02-08 16:56:04 +00:00
Blake Friedman 08fd9170fc Avoid using Cocoapods 1.15 until it fixes an issue affection RN. (#42702)
Summary:
Cocoapods 1.15 (https://github.com/facebook/react-native/issues/42698) current breaks the build, limit to version >= 1.13 & < 1.15

This is currently broken and affecting users, we'll remove this limit once Cocopods fixes the regression.  It's currently blocking 0.73.3.

## Changelog:
[iOS][Fixed] don't allow cocoapods 1.15.
2024-01-29 14:06:16 +00:00
Distiller 19f3ddd5c1 [0.72.10] Bump version numbers 2024-01-18 15:48:24 +00:00
Alex Hunt 1f70f58aa4 [LOCAL] Fix min ios version regression and update podfile.lock
Manually applied version of https://github.com/facebook/react-native/pull/42232
2024-01-15 15:46:01 +00:00
Oscar Franco 91872826f3 Unhandled promise rejection - attach non-standard Error object stack info if possible (#42079)
Summary:
This is a continuation of my [last PR](https://github.com/facebook/react-native/pull/40914) which improved the symbolication of unhandled promise rejections.

While I was developing another library I noticed I still got an error stack of the log adding and not of the error itself. The library I'm trying to debug does not throw a standard error object but rather a custom one, but it still contains the stack field. By passing this stack field to the logbox call I was able to get a better symbolicated stack trace. The exact line of the failure is not displayed but at least the correct file is.

## Changelog:

<!-- Help reviewers and the release process by writing your own changelog entry.

Pick one each for the category and type tags:

[GENERAL] [ADDED] - Unhandled promise rejection - attach non-standard Error object stack info if possible

For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests

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

Test Plan:
Test any unhandled promise rejection with a non-standard error (line 23, toString must not return `[object Error]`) and see if the correct (or at least a better) stack trace is shown.

Here is the one I got before and after this change:

<img src="https://github.com/facebook/react-native/assets/1634213/3d07faad-9535-42c9-8032-b4d8fe407e88" width="200" />

<img src="https://github.com/facebook/react-native/assets/1634213/2c39bd82-c7a1-4f58-8ac4-5c479bb96b6e" width="200" />

Reviewed By: huntie

Differential Revision: D52431711

Pulled By: cipolleschi

fbshipit-source-id: be2172d3b1e2fc3f72812faac372c83bc6dface2
2024-01-15 15:46:01 +00:00
Riccardo Cipolleschi 89ef9cb81d Disable Hermes Bitcode from 0.72 2024-01-15 15:45:41 +00:00
Alex Hunt cb25ab9fa7 Update Podfile.lock 2024-01-15 13:03:39 +00:00
Riccardo Cipolleschi 565281105e [RN][iOS] Fix flags 2024-01-15 12:57:58 +00:00
Distiller 7b20c5b5e5 [0.72.9] Bump version numbers 2024-01-08 13:28:02 +00:00
Riccardo Cipolleschi d62d714ada [RN][General] Fix boost link (#42175) 2024-01-08 12:08:23 +01:00
Tommy Nguyen b7c1a40db4 Fix New Arch build failing with -std=c++20 (#42138) 2024-01-05 17:47:13 -08:00
Riccardo Cipolleschi 7c7baad7bd [LOCAL] Fix ruby tests 2024-01-05 14:13:03 +01:00
Riccardo Cipolleschi 34da08755d [LOCAL] Bump Podfile.lock and try to fix Hermes update 2024-01-04 15:23:14 +01:00
Distiller f63a721e89 [0.72.8] Bump version numbers 2023-12-20 08:24:00 +00:00
Luna Wei e5e15a8115 [LOCAL] Add missing sed import to test script 2023-12-19 10:46:54 -08:00
fortmarek 0db45a5590 bumped packages versions
#publish-packages-to-npm
2023-12-19 14:58:38 +01:00
Marek FořtandMoti Zilberman c3c6cf4646 Prevent LogBox from crashing on long messages (#38005) (#41989)
* Prevent LogBox from crashing on long messages (#38005)

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

Fixes https://github.com/facebook/react-native/issues/32093 by guarding the expensive `BABEL_CODE_FRAME_ERROR_FORMAT` regex with a cheaper initial scan. (Longer term, we should reduce our reliance on string parsing and propagate more structured errors.)

Changelog: [General][Fixed] Prevent LogBox from crashing on very long messages

Reviewed By: GijsWeterings

Differential Revision: D46892454

fbshipit-source-id: 3afadcdd75969c2589bbb06f47d1c4c1c2690abd

* Update RNTester Podfile.lock

* Check for major ruby version

---------

Co-authored-by: Moti Zilberman <moti@meta.com>
2023-12-19 14:55:11 +01:00
Riccardo Cipolleschi ed5a798932 Install bundler versions depending on Ruby version (#41962)
Summary:
Since yesterday evening (why it is always friday evening???) CircleCI or Gem decided to update the default bundler version that is installed with `gem bundle install`.
Therefore, CI for iOS stopped working.

This change installs bundler's versions so that they are compatible with the Ruby version.

[Internal] - Fix CI for iOS installing versions of bundler that are compatible with Ruby

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

Test Plan: CircleCI is green

Reviewed By: GijsWeterings

Differential Revision: D52230544

Pulled By: cipolleschi

fbshipit-source-id: 2f96e16ecb94159953056e8de757ea4d249f80f0
2023-12-19 10:25:47 +01:00
Pieter De Baets 99cdaaacce Call invalidate on ViewManager on context destroy (#37481)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/37481

ViewManagers inherit from BaseJavaModule so we should honour the same lifecycle  for them as we do for native modules, which is to call `invalidate` / `onCatalystInstanceDestroy` when the ReactContext is destroyed. This allows the ViewManager to do any cleanup which cannot happen at the View level.

Changelog: [Android][Fixed] ViewManagers now receive an invalidate callback

Reviewed By: cortinico

Differential Revision: D45945678

fbshipit-source-id: 27c26d951b50a734c42eb033a46e599ef939e29f
2023-12-19 10:17:43 +01:00
Tommy Nguyen e70166a3a8 Fix build_codegen! not finding @react-native/codegen in pnpm setups (#41456)
`build_codegen!` currently assumes that `@react-native/codegen` gets
installed next to `react-native`. In a pnpm setup, it's found under
`/~/react-native/node_modules/@react-native/codegen` instead.

However, as @dmytrorykun pointed out, we don't actually need to build
it outside of this repository.
2023-12-07 15:56:24 +01:00
Tommy Nguyen df2bbba50b Correctly declare runtime dependencies (#41445)
In pnpm setups, codegen will fail during build because it cannot find
its dependencies. Some of the dependencies it relies on at runtime are
currently declared under `devDependencies`. This change moves them to
`dependencies`.
2023-12-07 15:55:38 +01:00
Distiller 52904ffc42 [0.72.7] Bump version numbers 2023-11-14 10:56:06 +00:00
Marek FořtandOscar Franco 55c2c33b46 Symbolicate unhandled promise rejections (#40914) (#41377)
Summary:
For a very long time when a promise rejects without an attached catch we get this warning screen without a correct stack trace, only some internal calls to the RN internals.

<img src="https://github.com/facebook/react-native/assets/1634213/75aa7615-ee3e-4229-80d6-1744130de6e5" width="200" />

I created [an issue for discussion](https://github.com/react-native-community/discussions-and-proposals/discussions/718) in the react-native-community repo and we figured out it was only a matter of symbolication. While it cannot be done on release without external packages and source maps, at least while developing we can provide a symbolicated stack-trace so developers can better debug the source of rejected promise.

I got the stack trace symbolicated and the correct code frame. I'm missing some help trying to display it in the warning view but at the very least I can now correctly show the line of the error and log the codeframe to the console.

<!-- Help reviewers and the release process by writing your own changelog entry.

Pick one each for the category and type tags:

[GENERAL] [FIXED] - Show correct stack frame on unhandled promise rejections on development mode.

For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests

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

Test Plan:
I simply created a throwing function on a dummy app, and checked the output of the console and the warning view:

```ts
import React from 'react';
import {SafeAreaView, Text} from 'react-native';

async function throwme() {
  throw new Error('UNHANDLED');
}

function App(): JSX.Element {
  throwme();

  return (
    <SafeAreaView>
      <Text>Throw test</Text>
    </SafeAreaView>
  );
}

export default App;
```

Here is the output

<img src="https://github.com/facebook/react-native/assets/1634213/2c100e4d-618e-4143-8d64-4095e8370f4f" width="200" />

Edit: I got the warning window working properly:

<img src="https://github.com/facebook/react-native/assets/1634213/f02a2568-da3e-4daa-8132-e05cbe591737" width="200" />

Reviewed By: yungsters

Differential Revision: D50324344

Pulled By: javache

fbshipit-source-id: 66850312d444cf1ae5333b493222ae0868d47056

Co-authored-by: Oscar Franco <ospfranco@gmail.com>
2023-11-10 14:48:39 +01:00
f399afc395 Fix RNTestProject testing on Android (#41378)
* Fix RNTestProject testing on Android (#41172)

Summary:
While releasing RN 0.73.0-RC3, we relaized that the e2e test script was bugged for Android when used to test RNTestProject with the `-c` option.

There  were 2 problems:
- The downloaded maven-local was not actually used because it doesn't work with a zip. (We were always downloading a version from Maven)
- The versions of React Native between maven-local and the locally packaged React Native were different.

This change fixes the script by:
- Downloading maven-local
- Unzipping maven-local and passing the new folder to the Android app
- Downloading the React Native version that has been packaged in CI

By unzipping maven-local and using the unzipped folder, we make sure that Android is actually using the local repository.
By downloading both the packaged react native and the maven-local from the same CI workflow, we ensure that the versions are aligned.

This also speeds-up further the Android testing.

While running this change, we also moved the `pod install` step inside the `if (iOS)` branch, so we do not install Cocoapods if we need to test
Android.

[Internal] - Fix Android E2E test script when downloading artefacts from CI

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

Test Plan: Tested locally on both main and 0.73-stable, on both Android and iOS

Reviewed By: cortinico

Differential Revision: D50651448

Pulled By: cipolleschi

fbshipit-source-id: 70a9ed19072119d19c5388e8a4309d7333a08e13

* Backport e2e script changes to main (#41332)

Summary:
Last week, I modified the e2e script to make sure it was working properly with 0.73.
This change backport those changes in main

## Changelog:
[Internal] - Backport e2e script changes

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

Test Plan: Tested locally

Reviewed By: dmytrorykun

Differential Revision: D51025796

Pulled By: cipolleschi

fbshipit-source-id: 89ecd3701eaac4ba4bdde2c640df45a158329158

* Use old REACT_NATIVE_MAVEN_LOCAL_REPO env var

* prettier

---------

Co-authored-by: Riccardo Cipolleschi <riccardo.cipolleschi@gmail.com>
Co-authored-by: Riccardo Cipolleschi <cipolleschi@meta.com>
2023-11-10 14:44:14 +01:00
a304cb43c6 Make the interop-layer work with components with custom name (#41376)
* Make the interop-layer work with components with custom name (#41207)

Summary:
This should fix
https://github.com/facebook/react-native/issues/37905#issuecomment-1774851214

When working on react-native-fast-image, we realized that the interop layer does not work for components where the exported name is different from the iOS class.

To fix this, we can use the Bridge to retrieve the actual view manager, given the component name.

This solution should be much more robust than making assumptions on the ViewManager name, given the ComponentName.

On top of that, we realized tha the interop layer was not calling `didSetProps` after setting the props, so we are invoking that.

bypass-github-export-checks

[iOS][Fixed] - Add support for Components with custom names in the interop layer.

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

Test Plan: Tested locally on an app created in 0.72 and 0.73 in Bridge and Bridgeless mode.

Reviewed By: cortinico

Differential Revision: D50698172

Pulled By: cipolleschi

fbshipit-source-id: 49aee905418515b0204febbbe6a67c0114f37029

* Remove references to RCTBridgeProxy

---------

Co-authored-by: Riccardo Cipolleschi <riccardo.cipolleschi@gmail.com>
Co-authored-by: Riccardo Cipolleschi <cipolleschi@meta.com>
2023-11-10 14:43:11 +01:00
Riccardo Cipolleschi 5858fd768e Fix unstable RCTAppDelegate podspec (#41009)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/41009

This change should fix [#39971](https://github.com/facebook/react-native/issues/39971), computing the relative path from the App path to the pod installation root and using that instead of the absolute path to the `react-native.config.js` file

## Changelog
[Internal] - Stabilize RCTAppDelegate podspec

Reviewed By: cortinico

Differential Revision: D50323710

fbshipit-source-id: e29e62228d08c752e822d7a9ab5b1a2b5dcd6eb4
2023-11-08 10:35:08 +01:00
Ivan Alexandrov 2f08813bc7 Fix android platform border color (#39893)
Summary:
If you try to apply PlatformColor to borders on Android app will crash with the next error:

"Error while updating property 'borderColor' of a view managed by: RCTView"

## Changelog:

[ANDROID] [FIXED] - Fix android crash when apply PlatformColor to borders

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

Test Plan:
In RNTester example, go to APIs -> PlatformColor
|    Before  | After |
| ----------- | ----------- |
|  <img src="https://github.com/facebook/react-native/assets/70860930/66ac2880-53da-4438-bd9a-332f8ea40645" alt="drawing" width="200"/>    | <img src="https://github.com/facebook/react-native/assets/70860930/151f58a1-d857-4b3d-9ec6-de74eb065127" alt="drawing" width="200"/>      |

Reviewed By: NickGerleman

Differential Revision: D50011758

Pulled By: javache

fbshipit-source-id: ea06c18c6aef4b6731e9b9b87422a1e0d13de208
2023-11-08 10:33:11 +01:00
Pieter De Baets 981a0a08de Fix normalization of degrees in AnimatedInterpolation (#36645)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/36645

This broke while changing the AnimatedInterpolation back in D40571873 and D40632443, as I assumed the native side would be able to correctly handle values such as '1rad'. However these were being sent over as strings, and were thus using the string interpolation path, which does not work here.

Instead, handle both `deg` and `rad` explicitly when generating the config in JS.

Resolves issue https://github.com/facebook/react-native/issues/36608

Changelog: [General][Fixed] Resolves Animated.Value.interpolate results in NaN when output is in radians

Reviewed By: yungsters

Differential Revision: D44406034

fbshipit-source-id: fe0f3df16f2b8ec6c31f9359e4706cacc72b9951
2023-11-08 10:32:53 +01:00
Szymon Rybczak e844a62ce9 Bump CLI to v11.3.10 (#41316) 2023-11-06 16:42:05 +01:00
Riccardo Cipolleschiandfortmarek 3e23e14763 Update node installation on debian (#41276)
Co-authored-by: fortmarek <marekfort@me.com>
2023-11-03 16:23:45 +01:00
Marek Fořt 945c429b6a Bump Podfile.lock for 0.72 (#41303)
* Update Podfile.lock after the latest release

* Change nodejs version for test_windows
2023-11-03 13:55:30 +01:00
Nicola Corti 3a4d79e775 Fix broken Loading/Refreshing indicator on Android
Summary:
The Loading.../Refreshing... indicator is currently broken on Android.
The reason is related to D42599220
We used to have a Toast shown to users on Android as a fallback, but as the
DevLoadingView is not always loaded as a module in the core package, this ends up in the banner never beign shown to the user (on RN Tester or template apps).

Changelog:
[Android] [Fixed] - Fix broken Loading/Refreshing indicator on Android

Reviewed By: cipolleschi

Differential Revision: D49876757

fbshipit-source-id: 400e002327ebca908e3e7a7f81c5066888ac4e9b
2023-10-13 15:56:10 +01:00
Alex Hunt e031c05cdc Bump deprecated-react-native-prop-types to ^4.2.3
This version correctly sets a dependency on `"@react-native/normalize-colors": "<0.73.0"` (from `"*"`), preventing future unwanted breakages.
2023-10-12 16:45:38 +01:00
Distiller 4fd3da2a87 [0.72.6] Bump version numbers 2023-10-12 15:02:49 +00:00
Riccardo Cipolleschi 6e3a130860 [Local] Fix CI for 0.72, with Acitve Support and Xcode15 (#40855) 2023-10-12 13:49:58 +01:00
Tim Yung 9b3bd63723 RN: Switch EventEmitter to Array.from(...) (#39525)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/39525

Switches `EventEmitter#emit` to use `Array.from` instead of the spread operator.

This should be functionally identical (with marginally less overhead of the runtime having to determine the type of `registrations`), but there seems to be [some unexpected Babel configurations in the community](https://github.com/facebook/react-native/issues/35577#issuecomment-1723218934) that causes this line of code to do the wrong things.

Although we should independently root cause the Babel plugin configuration problems, this change might provide immediate relief and is also not any worse (e.g. in terms of code readability). This also adds a descriptive comment explaining the intention of the call to `Array.from`.

Changelog:
[Fixed][General] - Fix a potential bug in `EventEmitter` when used with certain Babel configurations that incorrectly polyfill the spread operator for iterables.

Reviewed By: javache

Differential Revision: D49389813

fbshipit-source-id: 7caf63734fc047496afe2f1ed6d918c22747258a
2023-10-11 11:56:19 +01:00
Riccardo Cipolleschi 785f91b67a Fix Gemfile, setting Active support to < 7.1.0 (#39828)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/39828

Active Suppert released a new Gem which is incompatible with Cocoapods 1.13.0, the latest release, as they removed a method used by cocoapods.

This fix ensures that we install compatible versions of the Gem.

## Changelog:
[iOS][Fixed] - Set the max version of Active support to 7.0.8

Reviewed By: hoxyq

Differential Revision: D49949782

fbshipit-source-id: 278097502d3a416567cc8c0b90090fee4fb21503

# Conflicts:
#	Gemfile
2023-10-11 11:56:19 +01:00
Riccardo Cipolleschi 355025dae4 Update Xcode 15 patches to be more robust (#39710)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/39710

Last week Apple released Xcode 15, which required us to ship a workaround for the new linker.
Unfortunately, the previous fix was not good enough and there were some edge cases that were not covered.
For example, in some occasions the flags are read as an array and the `-Wl` and the `-ld_classic` flags were separated and not properly removed when moving from Xcode 15 to Xcpde 14.3.1.

This change fixes those edge cases, with a more robust solution where:
- We convert the flags to a string.
- We trim the string and the values properly.
- We add the flags when running `pod install` with Xcode 15 as the default iOS toolchain.
- We remove the flags when running `pod install` with Xcode <15 as the default iOS toolchain.

## Changelog:
[Internal] - Make the Xcode 15 workaround more robust.

Reviewed By: dmytrorykun

Differential Revision: D49748844

fbshipit-source-id: 34976d148f123c5aacba6487a500874bb938fe99

# Conflicts:
#	packages/react-native/scripts/cocoapods/__tests__/utils-test.rb
#	packages/react-native/scripts/cocoapods/utils.rb
2023-10-11 11:56:19 +01:00
Riccardo Cipolleschi 3c4cc59542 Move hermes-engine.podspec and hermes-utils.rb from hermes-engine to hermes folders when building (#39575) 2023-10-02 10:09:10 +02:00
Distiller 1e38d4d4b1 [0.72.5] Bump version numbers 2023-09-25 04:32:45 +00:00
Riccardo Cipolleschi 2a041cb967 Add ld_classic flag to Hermes when building for Xcode 15 (#39516)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/39516

With Xcode15, Apple rewrote the C++ linker.
This is a breaking change that does not work with weak symbols.
As a workaround, apple is suggesting to add `-ld_classic` to the linker in order to readd support for weak symbols. The flag does not exists for Xcode 14.3 or lower, so we need to add it conditionally.

With this change, we introduce a couple of checks in the Hermes build logic:
1. Detect the version of Xcode that is used
2. Add the new flag to `HERMES_EXTRA_LINKER_FLAGS` if Xcode version is 15.

[Internal] - Make hermes build properly with Xcode 15

Reviewed By: cortinico, dmytrorykun

Differential Revision: D49368675

fbshipit-source-id: 62d8ed81855c426f56ed94b6a2d6da2eb882b355
2023-09-19 13:20:07 +02:00
Riccardo Cipolleschi 8ccdb2cbe6 Fix Xcode 15 RC issues (#39474)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/39474

When it comes to Xcode 15 RC, we are aware of two issues:
1. `unary_function` and `binary_function` not available in Cxx17
2. [Weak linking](https://developer.apple.com/documentation/xcode-release-notes/xcode-15-release-notes#Linking) is not supported anymore.

This change should fix both of the issues, adding the flags to allow for `unary_function`and `binary_function` to be called and adding the `-Wl -ld_classic` flag to `OTHER_LDFLAGS` in case Xcode 15 is detected.

[Internal] - add the `_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION` and the `-Wl -ld_classic` flags to projects when needed

Reviewed By: dmytrorykun

Differential Revision: D49319256

fbshipit-source-id: bb895f1e60db915db79684f71fa436ce80b42111
2023-09-19 13:19:23 +02:00
Riccardo Cipolleschi a5e110adcf Bump IPHONEOS_DEPLOYMENT_TARGET to 13.4 for 3rd party pods (#39478)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/39478

When testing Xcode 15, we realized that a few pods we do not control directly have the IPHONEOS_DEPLOYMENT_TARGET set to old versions of iOS.
We can update that setting to silence the warning with Cocoapods and this is what this script does.

Notice that bumping that setting generated other warning as some APIs have been deprecated.

[Internal] - Bump min IPHONEOS_DEPLOYMENT_TARGET for 3rd party pods

Reviewed By: dmytrorykun

Differential Revision: D49274837

fbshipit-source-id: 584d105c76d654daa2ecf5eb2f1b9381e70f567a
2023-09-19 13:16:38 +02:00
zhongwuzw f6fd6b8db0 【iOS】Fix timer background state when App is launched from background (#39347)
Summary:
Fixes https://github.com/facebook/react-native/issues/38711

## Changelog:

[IOS] [FIXED] - Fix timer background state when App is launched from background

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

Test Plan: Please see https://github.com/facebook/react-native/issues/38711

Reviewed By: cipolleschi

Differential Revision: D49101979

Pulled By: dmytrorykun

fbshipit-source-id: e25b182539f39e4465fa40e51288d88c68967b31
2023-09-11 15:42:49 +02:00
Thibault Malbranche 4da991407d bumped packages versions
#publish-packages-to-npm
2023-09-11 15:29:31 +02:00
Alex Hunt 6f02d55deb Bump CLI to 11.3.7 (#39280) 2023-09-06 08:24:31 +01:00
Saad Najmi a8ec20db21 Allow RCTBundleURLProvider to request an inline source map (#37878) (#39033)
Summary:
See: http://blog.nparashuram.com/2019/10/debugging-react-native-ios-apps-with.html
When using direct debugging with JavaScriptCore, Safari Web Inspector doesn't pick up the source map over the network. Instead, as far as I can tell, it expects you to pass the source URL at the time you load your bundle:  https://developer.apple.com/documentation/javascriptcore/jscontext/1451384-evaluatescript?language=objc . This leads to a very sub-par developer experience debugging the JSbundle directly. It will however, pick up an inline source map. Therefore, let's add a way to have React Native tell metro to request an inline source map.

I did this by modifying `RCTBundleURLProvider` to have a new query parameter for `inlineSourceMap`, and set to true by default for JSC.

[IOS] [ADDED] - Added support to inline the source map via RCTBundleURLProvider

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

Test Plan:
I can put a breakpoint in RNTester, via Safari Web Inspector, in human readable code :D

<img width="1728" alt="Screenshot 2023-06-14 at 4 09 03 AM" src="https://github.com/facebook/react-native/assets/6722175/055277fa-d887-4566-9dc6-3ea07a1a60b0">

Reviewed By: motiz88

Differential Revision: D46855418

Pulled By: huntie

fbshipit-source-id: 2134cdbcd0a3e81052d26ed75f83601ae4ddecfe
2023-09-04 18:23:02 +02:00
Ales Pergl f77e9af761 Fix building Android on Windows (#39190)
Summary:
Currently Android fails to build on Windows, because CMake cannot work with
native Windows paths that are passed to it as build arguments. This change
converts the input paths to the CMake format.

## Changelog:

[Android] [Fixed] - Fix building Android on Windows.

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

Test Plan: Build the React Native Android project on Windows. It should complete successfully.

Reviewed By: NickGerleman

Differential Revision: D48948140

Pulled By: cortinico

fbshipit-source-id: 6d584c2a10e683cdb6df0dd6dcd5875da7e06e2b
2023-09-04 18:20:35 +02:00
Koen Punt e9eca07f52 Revert "Fix build failure on iOS with pnpm and use_frameworks! (#38158)" (#39177)
Summary:
This partially reverts commit 58adc5e4b9.

Using an absolute path in a podspec is wrong, and causes checksum issues when installs are ran on different systems.

Example:

`pod install --deployment --clean-install` breaks on non-matching checksums on CI because the absolute path is not the same in that environment.

```
Adding spec repo `trunk` with CDN `https://cdn.cocoapods.org/`
Verifying no changes
[!] There were changes to the lockfile in deployment mode:
SPEC CHECKSUMS:
  React-debug:
    New Lockfile: 419922cde6c58cd5b9d43e4a09805146a7dd13a8
    Old Lockfile: 1ce329843d8f9a9cbe0cdd9de264b20e89586734
  React-NativeModulesApple:
    New Lockfile: a683b0c999e76b7d15ad9d5eaf8b6308e710a93e
    Old Lockfile: f82356d67a137295d098a98a03be5ee35871b5a5
  React-runtimescheduler:
    New Lockfile: 79f8dff11acbe36aaeece63553680d7a8272af96
    Old Lockfile: 16c5282d43a0df50d7c68ebf0218aeeb642a7086
  React-utils:
    New Lockfile: 4fabb3cba786651e35bc41e610b0698fa24cecff
    Old Lockfile: e7e9118d0e85b107bb06d1a5f72ec5db6bddb911
  ReactCommon:
    New Lockfile: af30fb021799e18c85a8e30ce799e15607e82212
    Old Lockfile: f04f86f33c22e05dbf875789ea522ee486dace78
```

And even tho the change fixed an issue with pnpm, the issue it introduces with cocoapods I think is a bigger one.

## Changelog:

[INTERNAL] - Revert commit that makes podfile unstable

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

Test Plan: Tested locally that the hashes are stable

Reviewed By: NickGerleman

Differential Revision: D48773887

Pulled By: cipolleschi

fbshipit-source-id: 96bcdbadc17a24fa9a8669f569d004bee6a03521
2023-09-04 18:20:07 +02:00
Dr. Sergey Pogodin 66441e7e5d A fix in Codegen for Windows build host (#36542)
Summary:
Android builds with new arch fail on Windows build host (https://github.com/facebook/react-native/issues/36475). This tiny correction fixes generation of `schema.json` (without it codegen failed to find any files, and generated empty schema). Unfortunately, does not fixes the issue with Windows host entirely, as builds still fail later (on ninja build step).

## Changelog:
[Android] [Fixed] - A bug fix for Android builds with new arch on Windows host.

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

Reviewed By: NickGerleman

Differential Revision: D48563587

Pulled By: cortinico

fbshipit-source-id: acd510308ce9768fb17d3a33c7927de3237748ac
2023-09-04 18:19:56 +02:00
Saad Najmi 05d36d9860 Guard JSGlobalContextSetInspectable behind a compile time check for Xcode 14.3+ (#39037)
Summary:
An earlier [change](https://github.com/facebook/react-native/commit/8b1bf058c4bcbf4e5ca45b0056217266a1ed870c) I made (that huntie resubmitted) only works on Xcode 14.3+ (See more info [here](https://github.com/react-native-community/discussions-and-proposals/discussions/687)). This change adds the appropriate compiler checks so that the change is compatible with Xcode 14.2 and earlier, and therefore cherry-pickable to 0.71 and 0.72.

The check works by checking if iOS 16.4+ is defined, which is the closest proxy I could find for "Is this Xcode 14.3".

## Changelog:

[IOS] [CHANGED] - Guard `JSGlobalContextSetInspectable` behind a compile time check for Xcode 14.3+

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

Test Plan: I can't actually test on Xcode 14.2 (it won't launch on my MacBook 😢), but I made a similar [PR](https://github.com/microsoft/react-native-macos/pull/1848) in React Native macOS, whose CI checks run against Xcode 14.2 and I'm getting passing checks there.

Reviewed By: huntie

Differential Revision: D48414196

Pulled By: NickGerleman

fbshipit-source-id: ba10a6505dd11d982cc56c02bf9f7dcdc104bbec
2023-09-04 18:19:42 +02:00
Vincent Riemer 26b49f9ff9 Adjust RawPropsPropNameLength's type to account for increased number of props (#39008)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/39008

Changelog: [Internal] - Adjust RawPropsPropNameLength's type to account for increased number of props

While investigating why we needed to back out D48288752 I discovered that the root cause was that the `items_` vector in `RawProsKeyMap` was now a size greater than 255 which becomes an issue because `items_`'s indices are statically cast to `RawPropsPropNameLength` (previously alias to `uint8_t`).

This diff updates `RawPropsPropNameLength` to be an alias to `uint16_t` so the current issue is resolved as well as adding an assert to ensure (however unlikely) that this happens again.

Reviewed By: rozele

Differential Revision: D48331909

fbshipit-source-id: f6bc3e4825f2f293d79d8cd90c40ced7cba0e3c5
2023-09-04 18:19:18 +02:00
Janic Duplessis 7aeadbc249 Fix null crash when using maintainVisibleContentPosition on Android (#38891)
Summary:
`mFirstVisibleView` is a weak ref so it can also be null when dereferencing.

This was reported on the original PR here https://github.com/facebook/react-native/pull/35049#discussion_r1288195469

## Changelog:

[ANDROID] [FIXED] - Fix null crash when using maintainVisibleContentPosition on Android

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

Test Plan: Not sure exactly in what cases this can happen, but the fix is trivial and makes sense.

Reviewed By: cortinico

Differential Revision: D48192154

Pulled By: rshest

fbshipit-source-id: 57a38a22a0e216a33603438355bde0013c014fbf
2023-09-04 18:19:04 +02:00
Alex Hunt 1794832a26 Re-enable direct debugging with JSC on iOS 16.4+ (#37914)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/37914

Restores https://github.com/facebook/react-native/pull/37874 (reverted earlier today), with fix for `JSCRuntime.cpp` build on Android.

Changelog: None

Reviewed By: cortinico

Differential Revision: D46762984

fbshipit-source-id: 6d56f81b9d0c928887860993b2b729ed96c0734c
2023-09-04 18:18:35 +02:00
Lorenzo SciandraandWilliam Bell ef8ac7a329 chore(releases): improve bump oss script to allow less human errors (72 edition) (#38888)
Co-authored-by: William Bell <williambell9708@outlook.com>
resolved: https://github.com/facebook/react-native/pull/38247
resolved: https://github.com/facebook/react-native/pull/38666
2023-08-18 12:24:19 +01:00
Riccardo Cipolleschi 33fc55dc6e Add scripts and pipeline to poll for maven (#38980) 2023-08-16 13:26:38 +02:00
Distiller ff27568f62 [0.72.4] Bump version numbers 2023-08-14 07:56:35 +00:00
fortmarek fe804b8597 bumped packages versions
#publish-packages-to-npm
2023-08-11 14:34:24 +02:00
fortmarek c7073fd685 Change comment in @react-native/metro-config to trigger a release bump 2023-08-11 14:33:34 +02:00
fortmarek f3e7572a10 bumped packages versions
#publish-packages-to-npm
2023-08-11 13:17:40 +02:00
fortmarek 9f792180b5 Reorder test imports in @react-native/virtualized-lists to trigger a release bump 2023-08-11 13:16:52 +02:00
Ellis Tsung 768c9604a2 Pass hitSlop prop into TextInput Pressability config (#38857)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/38857

`hitSlop` must be passed into the `usePressability` hook in order for it to take effect. It's a no-op if no hit slop is present

Changelog:
    [Internal][Fixed] - Propagate hit slop prop to TextInput pressability config

Reviewed By: NickGerleman

Differential Revision: D48124538

fbshipit-source-id: a910fdcec55e67d37c84facca297428556ef777e
2023-08-10 10:18:14 -07:00
Nicola Corti 2f6c200eff [LOCAL] Fix broken Android tests for 0.72 (#38926) 2023-08-10 10:11:37 -07:00
LunaandLuna Wei 40ea8ffcc7 Bump cli and metro (#38898)
Co-authored-by: Luna Wei <luwe@fb.com>
2023-08-10 10:11:37 -07:00
Michał Mąka 5f503b8427 Restore checking shadow tree commit cancellation after commit hook execution (#38715)
Summary:
Hello! This PR is a fix for one merged some time ago (https://github.com/facebook/react-native/pull/36216). In the PR check for `nullptr` value of `newRootShadowNode` just after performing commit hooks was overlooked. This PR restores previous behaviour of conditional commit cancellation after commit hook execution.

## Changelog:

[INTERNAL] [FIXED] - Restore checking shadow tree commit cancellation after commit hook execution

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

Test Plan: Just register a commit hook that return `nullptr`. In that case current code crashes due to `nullptr` dereference.

Reviewed By: sammy-SC

Differential Revision: D47972245

Pulled By: ryancat

fbshipit-source-id: 7599ad11ed4b2dcaf25e53f676ec4530e37410d5
2023-08-10 10:11:37 -07:00
Nicola Corti 4f8c87ce0d [LOCAL] Fabric Interop - Properly dispatch integer commands (#38527) (#38835)
resolved: https://github.com/facebook/react-native/pull/38527
2023-08-10 10:11:37 -07:00
Luna Wei 7aa8cd55be Fix missing Platform in VirtualizedList 2023-08-10 10:11:37 -07:00
Luna Wei e9ea926ba3 Hermes bump for hermes-2023-08-07-RNv0.72.4-813b2def12bc9df026
54b3e3653ae4a68d0572e0
2023-08-07 11:54:56 -07:00
Fabrizio Bertoglio 5b45e973f4 Remove option to paste rich text from Android EditText context menu (#38189)
Summary:
Text is copy pasted as rich text on Android TextInput instead of Plain Text.

### What is the root cause of that problem?

Android EditText and iOS UITextField/UITextView have different copy/paste behavior.
- Android TextInput copies/pastes rich text
- iOS UITextField copies/pastes plain text.

| iOS (react-native)   | Android (react-native) |
| ----------- | ----------- |
| <video src="https://user-images.githubusercontent.com/24992535/249170968-8fde35f0-a53c-4c5c-bd89-ee822c08eadf.mp4" width="350" />      | <video src="https://user-images.githubusercontent.com/24992535/249171968-bf0915a0-4060-4586-b267-7c2b463d76f6.mov" width="350" />       |

### What changes do you think we should make in order to solve the problem?

The issue is a bug in react-native https://github.com/facebook/react-native/issues/31442:

1) The JavaScript TextInput and ReactEditText Android state are not in sync
2) The TextInput Android Native state over-rides the JavaScript state.
3) onChangeText passes a plain text string to JavaScript, not rich text (text with spans and styles).

More info at https://github.com/Expensify/App/issues/21411#issuecomment-1611591137

The solution consists of:

1) **Over-riding onTextContextMenuItem in ReactEditText to copy/paste plain text instead of rich-text** (https://stackoverflow.com/a/45319485/7295772).
2) **Removing the `Paste as plaintext` option from the insert and selection context menu**

fixes https://github.com/facebook/react-native/issues/31442

## Changelog:

[ANDROID] [FIXED] - Remove option to paste rich text from Android EditText context menu

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

Test Plan:
#### Reproducing the issue on Android

https://user-images.githubusercontent.com/24992535/249185416-76f8a687-1aca-4dc9-9abe-3d73d6e2893c.mp4

#### Fixing the issue on Android
Sourcecode https://github.com/fabriziobertoglio1987/text-input-cursor-flickering-android/blob/fix-copy-paste/app/src/main/java/com/example/myapplication/CustomEditText.java

https://user-images.githubusercontent.com/24992535/249486339-95449bb9-71b6-430c-8207-f5672f034fa9.mp4

#### Testing the solution on React Native

https://github.com/Expensify/App/assets/24992535/b302237b-99e5-44a2-996d-8bc50bbbc95c

Reviewed By: mdvacca

Differential Revision: D47824730

Pulled By: NickGerleman

fbshipit-source-id: 35525e7d52e664b0f78649d23941262ee45a00cd
2023-08-07 10:44:15 -07:00
Guil Varandas a601b22d14 fix: Correctly assign the hermes-engine pod tag when installing pods from a different folder (#38754)
Summary:
This PR aims to fix an issue where installing iOS pods from a different directory causes the `hermes-engine` `:tag:` not to be properly resolved.

Ever since https://github.com/facebook/react-native/issues/37148 was merged, the `setup_hermes` script tries to resolve the `node_modules/react-native/sdks/.hermesversion` file and use its content to generate the pod tag, in order to verify when it changes over time.
This works perfectly when installing pods within the `ios` folder, as the `react_native_path` should point to the correct relative folder (`../node_modules/react-native` by default).

However, when installing pods from a different directory (the project root, for example) and leveraging the `--project-directory` flag, the file fails to resolve, as the current working directory is considered when resolving the `.hermesversion` file.

### Quick Example:

- `react_native_path`: `../node_modules/react-native` (the default config)

**Installing pods from the `ios` folder:**
- `cd ios`
- `bundle exec pod install`
- `hermestag_file` resolved path: `$project_root/node_modules/react-native` 
- `hermes-engine` `:tag:`: `hermes-2023-03-20-RNv0.72.0-49794cfc7c81fb8f69fd60c3bbf85a7480cc5a77` 

**Installing pods from the `$project_root` folder**
- `bundle exec pod install --project-directory=ios`
- `hermestag_file` resolved path: `$parent_folder/$project_root/node_modules/react-native` 
- `hermes-engine` `:tag:`: `''` 

### The fix

Turns out that the same file had a resolved reference to the `react-native` folder, assigned to the `react_native_dir` variable:
```ruby
react_native_dir = Pod::Config.instance.installation_root.join(react_native_path)
```

By resolving the `.hermesversion` using that folder, we guarantee that the relative path will always reference the directory where the `Podfile` is defined, which is the expected behaviour.

## Changelog:

[Internal] - Fix an issue where installing pods from a different directory would fail to resolve `hermes-engine` tags correctly.

For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests

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

Test Plan:
- Init a new `react-native` repo
- Remove the generated `Podfile.lock` file
- Navigate to the project root folder
- `bundle exec pod install -project-directory=ios`
- Check that the `hermes-engine` entry has a properly populated `:tag:` attribute:

**Before:**
```
hermes-engine:
    :podspec: "../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec"
    :tag: ''
```

**After:**
```
hermes-engine:
    :podspec: "../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec"
    :tag: hermes-2023-03-20-RNv0.72.0-49794cfc7c81fb8f69fd60c3bbf85a7480cc5a77
```

Reviewed By: cortinico

Differential Revision: D48029413

Pulled By: cipolleschi

fbshipit-source-id: 82d465abd5c888eeb9eacd32858fa4ecf4f8c217
2023-08-07 10:44:05 -07:00
Andrea Cassani 3350dd8652 Fix Android ScrollView not responding to Keyboard events when nested inside a KeyboardAvoidingView (#38728)
Summary:
Starting from RN 0.72.0, when we nest a ScrollView inside a KeyboardAvoidingView, the ScrollView doesn't respond properly to the Keyboard on Android.

https://github.com/facebook/react-native/assets/32062066/a62b5a42-6817-4093-91a2-7cc9e4a315bb

This issue is due to a change made in https://github.com/facebook/react-native/issues/36104, which was added to fix https://github.com/facebook/react-native/issues/32235.

That commit changed this line of code to abort the Scroller animation if a new call to the `scrollTo` method was made:

https://github.com/facebook/react-native/blob/aab52859a447a8257b106fe307008af218322e3d/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java#L1073

Apparently, this is the same method that scrolls the ScrollView in response to the Keyboard opening on Android.

So, here comes my proposal for a fix that doesn't break https://github.com/facebook/react-native/issues/36104 and fixes https://github.com/facebook/react-native/issues/38152.

When we open the Keyboard, the call stack is as follows:
- InputMethodManager
- AndroidIME
- InsetsController
- `ReactScrollView.scrollTo` gets called

When we use the ScrollView method `scrollTo` directly from the UI, the call stack is different as it goes through:
- ReactScrollViewCommandHelper
- ReactScrollViewManager
- `ReactScrollView.scrollTo` gets called

We can move `mScroller.abortAnimation();` from `ReactScrollView.scrollTo` to the `ReactScrollViewManager.scrollTo` method so that it gets called only when we call `scrollTo` from the UI and not when the `scrollTo` method is called by other sources.

https://github.com/facebook/react-native/assets/32062066/9c10ded3-08e5-48e0-9a85-0987d62de011

## Changelog:

[ANDROID] [FIXED] - Fixed ScrollView not responding to Keyboard events when nested inside a KeyboardAvoidingView

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

Test Plan: You can see the issue and the proposed fixes in this repo: [kav-test-android](https://github.com/andreacassani/kav-test-android). Please refer to the `kav_test_fix` folder and to the [readme](https://github.com/andreacassani/kav-test-android/blob/main/README.md).

Reviewed By: NickGerleman

Differential Revision: D47972445

Pulled By: ryancat

fbshipit-source-id: e58758d4b3d5318b947b42a88a56ad6ae69a539c
2023-08-07 10:43:51 -07:00
Nicola Corti 7aed30a037 Fabric Interop - Also normalize direct events (#38352)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/38352

This change is making sure we normalize both bubbling and direct events for the sake of Fabric Interop.
This is currently required as some libraries have reported incompatiblities with Fabric Interop
(see https://github.com/react-native-maps/react-native-maps/issues/4383)

Also this is has been reported by the WG here:
https://github.com/reactwg/react-native-new-architecture/discussions/135#discussioncomment-6443294

Changelog:
[Android] [Fixed] - Fabric Interop - Fix support for direct events on Paper components

Reviewed By: rshest

Differential Revision: D47472050

fbshipit-source-id: f0ae95cb782e340281928819a702273fb14e9b16
2023-08-07 10:43:36 -07:00
Hanno J. Gödecke e4429fa1c8 Add workaround fix for #35350 (#38073)
Summary:
This PR is a result of this PR, which got merged but then reverted:

- https://github.com/facebook/react-native/pull/37913

We are trying to implement a workaround for https://github.com/facebook/react-native/issues/35350, so react-native users on android API 33+ can use `<FlatList inverted={true} />` without running into ANRs.

As explained in the issue, starting from android API 33 there are severe performance issues when using scaleY: -1 on a view, and its child view, which is what we are doing when inverting the ScrollView component (e.g. in FlatList).

This PR adds a workaround. The workaround is to also scale on the X-Axis which causes a different transform matrix to be created, that doesn't cause the ANR (see the issue for details).
However, when doing that the vertical scroll bar will be on the wrong side, thus we switch the position in the native code once we detect that the list is inverted, using the newly added `isInvertedVirtualizedList` prop.

This is a follow up PR to:

- https://github.com/facebook/react-native/pull/38071

⚠️ **Note:** [38071](https://github.com/facebook/react-native/pull/38071) needs to be merged and shipped first! Only then we can merge this PR.

## 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
-->

[ANDROID] [FIXED] - ANR when having an inverted FlatList on android API 33+

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

Test Plan:
- Check the RN tester app and see that scrollview is still working as expected
- Add the `internalAndroidApplyInvertedFix` prop as test to a scrollview and see how the scrollbar will change position.

Reviewed By: cortinico

Differential Revision: D47848063

Pulled By: NickGerleman

fbshipit-source-id: 4a6948a8b89f0b39f01b7a2d44dba740c53fabb3
2023-08-07 10:43:26 -07:00
Hanno J. Gödecke 22c9739042 Add workaround for android API 33 ANR when inverting ScrollView (#38071)
Summary:
This PR is a result of this PR, which got merged but then reverted:

- https://github.com/facebook/react-native/pull/37913

We are trying to implement a workaround for https://github.com/facebook/react-native/issues/35350, so react-native users on android API 33+ can use `<FlatList inverted={true} />` without running into ANRs.

This is the native part, where we add a new internal prop named `isInvertedVirtualizedList`, which can in a follow up change be used to achieve the final fix as proposed in https://github.com/facebook/react-native/pull/37913

However as NickGerleman pointed out, its important that we first ship the native change.

## 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
-->

[ANDROID] [ADDED] - Native part of fixing ANR when having an inverted FlatList on android API 33+

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

Test Plan:
- Check the RN tester app and see that scrollview is still working as expected
- Add the `isInvertedVirtualizedList` prop as test to a scrollview and see how the scrollbar will change position.

Reviewed By: rozele

Differential Revision: D47062200

Pulled By: NickGerleman

fbshipit-source-id: d20eebeec757d9aaeced8561f53556bbb4a492e4
2023-08-07 10:43:18 -07:00
Kun Wang 3cf94df45f For targeting SDK 34 - Added RECEIVER_EXPORTED/RECEIVER_NOT_EXPORTED flag support in DevSupportManagerBase (#38256)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/38256

Add RECEIVER_EXPORTED/RECEIVER_NOT_EXPORTED flag support to DevSupportManagerBase for Android 14 change. See
https://developer.android.com/about/versions/14/behavior-changes-14#runtime-receivers-exported for details.

Without this fix, app crashes during launch because of :
```SecurityException: {package name here}: One of RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED should be specified when a receiver isn't being registered exclusively for system broadcasts```

Changelog:
[Targeting SDK 34] Added RECEIVER_EXPORTED/RECEIVER_NOT_EXPORTED flag support in DevSupportManagerBase

Reviewed By: javache

Differential Revision: D47313501

fbshipit-source-id: 12e8299559d08b4ff87b4bdabb0a29d27763c698
2023-08-07 10:43:03 -07:00
Nick Gerleman 938bd78fbb Allow string transform style in TypeScript (#37569)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/37569

Fixes https://github.com/facebook/react-native/issues/37543

Missed as part of D39423409 (or maybe we didn't have TS types inline yet?)

Changelog:
[General][Fixed] - Allow string `transform` style in TypeScript

Reviewed By: cortinico

Differential Revision: D46161450

fbshipit-source-id: 24ee9e19365b7209ec0a2c8fb5a5d7ac78203f4d
2023-08-07 10:42:53 -07:00
tarunrajput e90733776e Add enterKeyHint in TextInput type declaration (#37624)
Summary:
Resolves: https://github.com/facebook/react-native/issues/37622

Related:
https://github.com/facebook/react-native/pull/34482
https://reactnative.dev/docs/textinput#enterkeyhint

## 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
-->
[Internal][Added]: Add enterKeyHint in TextInput type declaration

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

Reviewed By: cortinico, NickGerleman

Differential Revision: D46292040

Pulled By: lunaleaps

fbshipit-source-id: a037b7f8dd0d60880dcf1aec64749546fa54a95d
2023-08-07 10:42:46 -07:00
Szymon Rybczak a3cfdf0a08 Bump CLI to 11.3.6 (#38778) 2023-08-07 10:00:56 -07:00
Ruslan Lesiutin 03187b68e5 fix[AppContainer]: mount react devtools overlay only when devtools are attached (#38785)
resolved: https://github.com/facebook/react-native/pull/38727
Fixes https://github.com/facebook/react-native/issues/38024.
2023-08-07 09:27:40 -07:00
Riccardo CipolleschiandRiccardo Cipolleschi 79c4ec1a9a [LOCAL] Port CircleCI Artifact downloads to speed up release testing to 0.72 (#38553)
Co-authored-by: Riccardo Cipolleschi <cipolleschi@fb.com>
resolved: https://github.com/facebook/react-native/pull/37971
2023-07-24 16:12:15 +01:00
Lorenzo Sciandra ff37ddb2e2 [LOCAL] update podlock for CI 2023-07-12 13:31:01 +01:00
Distiller 24b682081b [0.72.3] Bump version numbers 2023-07-12 10:38:28 +00:00
Lorenzo Sciandra 8f41f25c21 Revert "Fix pod install for swift libs using new arch (#38121)"
This reverts commit 7a4ae799b8.
2023-07-12 11:13:30 +01:00
123 changed files with 3294 additions and 1434 deletions
+57 -140
View File
@@ -57,20 +57,19 @@ references:
cache_keys:
checkout_cache_key: &checkout_cache_key v1-checkout
gems_cache_key: &gems_cache_key v1-gems-{{ checksum "Gemfile.lock" }}
gems_cache_key: &gems_cache_key v1-gems-{{ arch }}-{{ checksum "Gemfile.lock" }}
gradle_cache_key: &gradle_cache_key v1-gradle-{{ checksum "gradle/wrapper/gradle-wrapper.properties" }}-{{ checksum "packages/react-native/ReactAndroid/gradle.properties" }}
hermes_workspace_cache_key: &hermes_workspace_cache_key v4-hermes-{{ .Environment.CIRCLE_JOB }}-{{ checksum "/tmp/hermes/hermesversion" }}
hermes_workspace_debug_cache_key: &hermes_workspace_debug_cache_key v2-hermes-{{ .Environment.CIRCLE_JOB }}-debug-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
hermes_workspace_release_cache_key: &hermes_workspace_release_cache_key v2-hermes-{{ .Environment.CIRCLE_JOB }}-release-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
hermes_workspace_debug_cache_key: &hermes_workspace_debug_cache_key v2-hermes-{{ arch }}-{{ .Environment.CIRCLE_JOB }}-debug-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}-{{ checksum "packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh" }}
hermes_workspace_release_cache_key: &hermes_workspace_release_cache_key v2-hermes-{{ arch }}-{{ .Environment.CIRCLE_JOB }}-release-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}-{{ checksum "packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh" }}
hermes_linux_cache_key: &hermes_linux_cache_key v1-hermes-{{ .Environment.CIRCLE_JOB }}-linux-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
hermes_windows_cache_key: &hermes_windows_cache_key v2-hermes-{{ .Environment.CIRCLE_JOB }}-windows-{{ checksum "/Users/circleci/project/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
hermes_tarball_debug_cache_key: &hermes_tarball_debug_cache_key v4-hermes-tarball-debug-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
hermes_tarball_release_cache_key: &hermes_tarball_release_cache_key v3-hermes-tarball-release-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
pods_cache_key: &pods_cache_key v8-pods-{{ .Environment.CIRCLE_JOB }}-{{ checksum "packages/rn-tester/Podfile.lock.bak" }}-{{ checksum "packages/rn-tester/Podfile" }}
hermes_tarball_debug_cache_key: &hermes_tarball_debug_cache_key v4-hermes-tarball-debug-{{ arch }}-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
hermes_tarball_release_cache_key: &hermes_tarball_release_cache_key v3-hermes-tarball-release-{{ arch }}-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
pods_cache_key: &pods_cache_key v8-pods-{{ arch }}-{{ .Environment.CIRCLE_JOB }}-{{ checksum "packages/rn-tester/Podfile.lock.bak" }}-{{ checksum "packages/rn-tester/Podfile" }}
windows_yarn_cache_key: &windows_yarn_cache_key v1-win-yarn-cache-{{ arch }}-{{ checksum "yarn.lock" }}
windows_choco_cache_key: &windows_choco_cache_key v1-win-choco-cache-{{ .Environment.CIRCLE_JOB }}
yarn_cache_key: &yarn_cache_key v5-yarn-cache-{{ .Environment.CIRCLE_JOB }}
rbenv_cache_key: &rbenv_cache_key v1-rbenv-{{ checksum "/tmp/required_ruby" }}
rbenv_cache_key: &rbenv_cache_key v1-rbenv-{{ arch }}-{{ checksum "/tmp/required_ruby" }}
cache_paths:
hermes_workspace_macos_cache_paths: &hermes_workspace_macos_cache_paths
@@ -129,9 +128,9 @@ executors:
<<: *defaults
macos:
xcode: *xcode_version
resource_class: macos.x86.medium.gen2
resource_class: macos.m1.medium.gen1
environment:
- BUILD_FROM_SOURCE: true
- RCT_BUILD_HERMES_FROM_SOURCE: true
# -------------------------
# COMMANDS
@@ -172,7 +171,7 @@ commands:
- restore_cache:
key: *rbenv_cache_key
- run:
name: Bundle Install
name: Install the proper Ruby and run Bundle install
command: |
# Check if rbenv is installed. CircleCI is migrating to rbenv so we may not need to always install it.
@@ -202,7 +201,13 @@ commands:
# Set ruby dependencies
rbenv global << parameters.ruby_version >>
gem install bundler
if [[ $(echo << parameters.ruby_version >> | awk -F'.' '{print $1}') == "2" ]]; then
rbenv rehash
gem install bundler -v 2.4.22
else
rbenv rehash
gem install bundler
fi
bundle check || bundle install --path vendor/bundle --clean
- save_cache:
key: *rbenv_cache_key
@@ -998,116 +1003,6 @@ jobs:
-scheme RNTester \
-sdk iphonesimulator
# -------------------------
# JOBS: Windows
# -------------------------
test_windows:
executor:
name: win/default
parameters:
run_disabled_tests:
type: boolean
default: false
environment:
- ANDROID_HOME: "C:\\Android\\android-sdk"
- ANDROID_NDK: "C:\\Android\\android-sdk\\ndk\\20.1.5948944"
- ANDROID_BUILD_VERSION: 33
- ANDROID_TOOLS_VERSION: 33.0.0
- GRADLE_OPTS: -Dorg.gradle.daemon=false
- CHOCO_CACHE_DIR: "C:\\ChocoCache"
steps:
- checkout_code_with_cache
- restore_cache:
keys:
- *windows_choco_cache_key
- run:
name: Choco cache
# Cache our dependencies which can be flakey to download
command: |
if (!Test-Path $env:CHOCO_CACHE_DIR) {
mkdir $env:CHOCO_CACHE_DIR
}
choco config set --name cacheLocation --value $env:CHOCO_CACHE_DIR
- run:
name: Disable NVM
# Use choco to manage node versions due to https://github.com/npm/cli/issues/4234
command: nvm off
- run:
name: Install Node JS
# Note: Version set separately for non-Windows builds, see above.
command: choco install nodejs-lts
# Setup Dependencies
- run:
name: Enable Yarn with corepack
command: corepack enable
# it looks like that, last week, envinfo released version 7.9.0 which does not works
# with Windows. I have opened an issue here: https://github.com/tabrindle/envinfo/issues/238
# TODO: T156811874 - Revert this to npx envinfo@latest when the issue is addressed
- run:
name: Display Environment info
command: |
npm install -g envinfo
envinfo -v
envinfo
- restore_cache:
keys:
- *windows_yarn_cache_key
- run:
name: "Yarn: Install Dependencies"
command: yarn install --frozen-lockfile --non-interactive
- save_cache:
key: *windows_yarn_cache_key
paths:
- C:\Users\circleci\AppData\Local\Yarn
- run:
name: Install Android SDK Tools
command: choco install android-sdk;
- save_cache:
key: *windows_choco_cache_key
paths:
- $env:CHOCO_CACHE_DIR
- run:
name: Setup Android SDKs
command: |
sdkmanager --licenses
sdkmanager "system-images;android-21;google_apis;armeabi-v7a"
sdkmanager "platforms;android-%ANDROID_BUILD_VERSION%"
sdkmanager "build-tools;%ANDROID_TOOLS_VERSION%"
sdkmanager "add-ons;addon-google_apis-google-23"
sdkmanager "extras;android;m2repository"
# -------------------------
# Run Tests
- run:
name: "Flow: Check Android"
command: yarn flow-check-android
- run:
name: "Flow: Check iOS"
command: yarn flow-check-ios
- run:
name: "Run Tests: JavaScript Tests"
command: yarn test
# Optionally, run disabled tests
- when:
condition: << parameters.run_disabled_tests >>
steps:
- run: echo "Failing tests may be moved here temporarily."
- run:
name: Android Build
command: ./gradlew.bat packages:rn-tester:android:app:assembleRelease
# -------------------------
# JOBS: Coverage
# -------------------------
@@ -1142,14 +1037,22 @@ jobs:
environment:
- HERMES_WS_DIR: *hermes_workspace_root
- HERMES_VERSION_FILE: "packages/react-native/sdks/.hermesversion"
- BUILD_FROM_SOURCE: true
- RCT_BUILD_HERMES_FROM_SOURCE: true
steps:
- run:
name: Install dependencies
command: |
apt update
apt install -y wget git curl
curl -sL https://deb.nodesource.com/setup_16.x | bash -
apt-get update
apt-get install -y ca-certificates curl gnupg
mkdir -p /etc/apt/keyrings
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
NODE_MAJOR=16
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list
apt-get update
apt install -y nodejs
npm install --global yarn
- checkout
@@ -1362,9 +1265,9 @@ jobs:
name: Build HermesC for Windows
command: |
if (-not(Test-Path -Path $Env:HERMES_WS_DIR\win64-bin\hermesc.exe)) {
choco install --no-progress cmake --version 3.14.7
choco install -y --no-progress cmake --version 3.14.7
if (-not $?) { throw "Failed to install CMake" }
choco install --no-progress python3
choco install -y --no-progress python3
if (-not $?) { throw "Failed to install Python" }
cd $Env:HERMES_WS_DIR\icu
@@ -1564,6 +1467,19 @@ jobs:
-d "{\"event_type\": \"publish\", \"client_payload\": { \"version\": \"${CIRCLE_TAG:1}\" }}"
# END: Stable releases
poll_maven:
docker:
- image: cimg/node:current
resource_class: small
steps:
- checkout_code_with_cache
- run_yarn
- run:
name: Poll Maven for Artifacts
command: |
node scripts/circleci/poll-maven.js
# -------------------------
# JOBS: Nightly
# -------------------------
@@ -1668,15 +1584,15 @@ workflows:
- test_ios_template:
requires:
- build_npm_package
name: "Test Template with Ruby 2.7.7"
ruby_version: "2.7.7"
name: "Test Template with Ruby 2.7.8"
ruby_version: "2.7.8"
architecture: "NewArch"
flavor: "Debug"
- test_ios_template:
requires:
- build_npm_package
name: "Test Template with Ruby 3.2.0"
ruby_version: "3.2.0"
name: "Test Template with Ruby 3.2.2"
ruby_version: "3.2.2"
architecture: "NewArch"
flavor: "Debug"
- test_ios_template:
@@ -1813,14 +1729,14 @@ workflows:
- test_ios_rntester:
requires:
- build_hermes_macos
name: "Test RNTester with Ruby 2.7.7"
ruby_version: "2.7.7"
name: "Test RNTester with Ruby 2.7.8"
ruby_version: "2.7.8"
architecture: "NewArch"
- test_ios_rntester:
requires:
- build_hermes_macos
name: "Test RNTester with Ruby 3.2.0"
ruby_version: "3.2.0"
name: "Test RNTester with Ruby 3.2.2"
ruby_version: "3.2.2"
architecture: "NewArch"
- test_ios_rntester:
requires:
@@ -1830,17 +1746,17 @@ workflows:
architecture: ["NewArch", "OldArch"]
jsengine: ["Hermes", "JSC"]
- test_ios:
name: "Test iOS with Ruby 2.7.7"
name: "Test iOS with Ruby 2.7.8"
run_unit_tests: true
requires:
- build_hermes_macos
ruby_version: "2.7.7"
ruby_version: "2.7.8"
- test_ios:
name: "Test iOS with Ruby 3.2.0"
name: "Test iOS with Ruby 3.2.2"
run_unit_tests: true
requires:
- build_hermes_macos
ruby_version: "3.2.0"
ruby_version: "3.2.2"
- test_ios:
run_unit_tests: true
requires:
@@ -1858,8 +1774,6 @@ workflows:
- test_js:
name: test_js_prev_lts
executor: nodeprevlts
- test_windows:
run_disabled_tests: false
# This workflow should only be triggered by release script
package_release:
@@ -1900,6 +1814,9 @@ workflows:
- build_hermesc_linux
- build_hermes_macos
- build_hermesc_windows
- poll_maven:
requires:
- build_and_publish_npm_package
package_and_publish_release_dryrun:
when:
+2
View File
@@ -107,6 +107,8 @@ package-lock.json
/packages/react-native/template/vendor
.ruby-version
/**/.ruby-version
./vendor/
vendor/
# iOS / CocoaPods
/packages/react-native/template/ios/build/
+1 -1
View File
@@ -4,4 +4,4 @@ source 'https://rubygems.org'
ruby ">= 2.6.10"
gem 'cocoapods', '~> 1.12'
gem 'activesupport', '>= 6.1.7.1'
gem 'activesupport', '>= 6.1.7.3', '< 7.1.0'
+26 -20
View File
@@ -1,26 +1,29 @@
GEM
remote: https://rubygems.org/
specs:
CFPropertyList (3.0.6)
CFPropertyList (3.0.7)
base64
nkf
rexml
activesupport (7.0.6)
activesupport (7.0.8.4)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
tzinfo (~> 2.0)
addressable (2.8.4)
public_suffix (>= 2.0.2, < 6.0)
addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0)
algoliasearch (1.27.5)
httpclient (~> 2.8, >= 2.8.3)
json (>= 1.5.1)
atomos (0.1.3)
base64 (0.2.0)
claide (1.1.0)
cocoapods (1.12.1)
cocoapods (1.15.2)
addressable (~> 2.8)
claide (>= 1.0.2, < 2.0)
cocoapods-core (= 1.12.1)
cocoapods-core (= 1.15.2)
cocoapods-deintegrate (>= 1.0.3, < 2.0)
cocoapods-downloader (>= 1.6.0, < 2.0)
cocoapods-downloader (>= 2.1, < 3.0)
cocoapods-plugins (>= 1.0.0, < 2.0)
cocoapods-search (>= 1.0.0, < 2.0)
cocoapods-trunk (>= 1.6.0, < 2.0)
@@ -32,8 +35,8 @@ GEM
molinillo (~> 0.8.0)
nap (~> 1.0)
ruby-macho (>= 2.3.0, < 3.0)
xcodeproj (>= 1.21.0, < 2.0)
cocoapods-core (1.12.1)
xcodeproj (>= 1.23.0, < 2.0)
cocoapods-core (1.15.2)
activesupport (>= 5.0, < 8)
addressable (~> 2.8)
algoliasearch (~> 1.0)
@@ -44,7 +47,7 @@ GEM
public_suffix (~> 4.0)
typhoeus (~> 1.0)
cocoapods-deintegrate (1.0.5)
cocoapods-downloader (1.6.3)
cocoapods-downloader (2.1)
cocoapods-plugins (1.0.0)
nap
cocoapods-search (1.0.1)
@@ -53,43 +56,46 @@ GEM
netrc (~> 0.11)
cocoapods-try (1.2.0)
colored2 (3.1.2)
concurrent-ruby (1.2.2)
concurrent-ruby (1.3.4)
escape (0.0.4)
ethon (0.16.0)
ffi (>= 1.15.0)
ffi (1.15.5)
ffi (1.17.0)
fourflusher (2.3.1)
fuzzy_match (2.0.4)
gh_inspector (1.1.3)
httpclient (2.8.3)
i18n (1.14.1)
i18n (1.14.5)
concurrent-ruby (~> 1.0)
json (2.6.3)
minitest (5.18.1)
json (2.7.2)
minitest (5.25.1)
molinillo (0.8.0)
nanaimo (0.3.0)
nap (1.1.0)
netrc (0.11.0)
nkf (0.2.0)
public_suffix (4.0.7)
rexml (3.2.5)
rexml (3.3.5)
strscan
ruby-macho (2.5.1)
typhoeus (1.4.0)
strscan (3.1.0)
typhoeus (1.4.1)
ethon (>= 0.9.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
xcodeproj (1.22.0)
xcodeproj (1.25.0)
CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3)
claide (>= 1.0.2, < 2.0)
colored2 (~> 3.1)
nanaimo (~> 0.3.0)
rexml (~> 3.2.4)
rexml (>= 3.3.2, < 4.0)
PLATFORMS
ruby
DEPENDENCIES
activesupport (>= 6.1.7.1)
activesupport (>= 6.1.7.3, < 7.1.0)
cocoapods (~> 1.12)
RUBY VERSION
+2
View File
@@ -39,6 +39,8 @@ nexusPublishing {
sonatype {
username.set(sonatypeUsername)
password.set(sonatypePassword)
nexusUrl.set(uri("https://ossrh-staging-api.central.sonatype.com/service/local/"))
snapshotRepositoryUrl.set(uri("https://central.sonatype.com/repository/maven-snapshots/"))
}
}
}
+6 -5
View File
@@ -40,7 +40,8 @@
"test-ios": "./scripts/objc-test.sh test",
"test-typescript": "dtslint packages/react-native/types",
"test-typescript-offline": "dtslint --localTs node_modules/typescript/lib packages/react-native/types",
"bump-all-updated-packages": "node ./scripts/monorepo/bump-all-updated-packages"
"bump-all-updated-packages": "node ./scripts/monorepo/bump-all-updated-packages",
"trigger-react-native-release": "node ./scripts/trigger-react-native-release.js"
},
"workspaces": [
"packages/*"
@@ -56,7 +57,7 @@
"@definitelytyped/dtslint": "^0.0.127",
"@jest/create-cache-key-function": "^29.2.1",
"@reactions/component": "^2.0.2",
"@react-native/metro-config": "^0.72.9",
"@react-native/metro-config": "^0.72.12",
"@types/react": "^18.0.18",
"@typescript-eslint/parser": "^5.30.5",
"async": "^3.2.2",
@@ -84,9 +85,9 @@
"jest": "^29.2.1",
"jest-junit": "^10.0.0",
"jscodeshift": "^0.14.0",
"metro-babel-register": "0.76.7",
"metro-memory-fs": "0.76.7",
"metro-react-native-babel-transformer": "0.76.7",
"metro-babel-register": "^0.76.9",
"metro-memory-fs": "^0.76.9",
"metro-react-native-babel-transformer": "^0.76.9",
"mkdirp": "^0.5.1",
"mock-fs": "^5.1.4",
"prettier": "^2.4.1",
+1 -1
View File
@@ -82,7 +82,7 @@ function getDefaultConfig(
watchFolders: [],
};
// Set global hook so that the CLI can detect when this config has been loaded
// Set global hook, so that the CLI can detect when this config has been loaded
global.__REACT_NATIVE_METRO_CONFIG_LOADED = true;
return mergeConfig(
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/metro-config",
"version": "0.72.9",
"version": "0.72.12",
"description": "Metro configuration for React Native.",
"repository": {
"type": "git",
@@ -11,8 +11,8 @@
"exports": "./index.js",
"dependencies": {
"@react-native/js-polyfills": "^0.72.1",
"metro-config": "0.76.7",
"metro-react-native-babel-transformer": "0.76.7",
"metro-runtime": "0.76.7"
"metro-config": "^0.76.9",
"metro-react-native-babel-transformer": "^0.76.9",
"metro-runtime": "^0.76.9"
}
}
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/codegen",
"version": "0.72.6",
"version": "0.72.8",
"description": "⚛️ Code generation tools for React Native",
"homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/react-native-codegen",
"repository": {
@@ -20,7 +20,10 @@
"dependencies": {
"@babel/parser": "^7.20.0",
"flow-parser": "^0.206.0",
"glob": "^7.1.1",
"invariant": "^2.2.4",
"jscodeshift": "^0.14.0",
"mkdirp": "^0.5.1",
"nullthrows": "^1.1.1"
},
"devDependencies": {
@@ -35,10 +38,7 @@
"@babel/plugin-transform-flow-strip-types": "^7.20.0",
"@babel/preset-env": "^7.20.0",
"chalk": "^4.0.0",
"glob": "^7.1.1",
"invariant": "^2.2.4",
"micromatch": "^4.0.4",
"mkdirp": "^0.5.1",
"prettier": "^2.4.1",
"rimraf": "^3.0.2"
},
@@ -14,6 +14,7 @@
const combine = require('./combine-js-to-schema');
const fs = require('fs');
const glob = require('glob');
const path = require('path');
const {parseArgs, filterJSFile} = require('./combine-utils');
const {platform, outfile, fileList} = parseArgs(process.argv);
@@ -21,9 +22,14 @@ const {platform, outfile, fileList} = parseArgs(process.argv);
const allFiles = [];
fileList.forEach(file => {
if (fs.lstatSync(file).isDirectory()) {
const filePattern = path.sep === '\\' ? file.replace(/\\/g, '/') : file;
const dirFiles = glob
.sync(`${file}/**/*.{js,ts,tsx}`, {
.sync(`${filePattern}/**/*.{js,ts,tsx}`, {
nodir: true,
// TODO: This will remove the need of slash substitution above for Windows,
// but it requires glob@v9+; with the package currenlty relying on
// glob@7.1.1; and flow-typed repo not having definitions for glob@9+.
// windowsPathsNoEscape: true,
})
.filter(element => filterJSFile(element, platform));
allFiles.push(...dirFiles);
@@ -562,10 +562,13 @@ function transformDataType(value: number | string): number | string {
if (typeof value !== 'string') {
return value;
}
if (/deg$/.test(value)) {
// Normalize degrees and radians to a number expressed in radians
if (value.endsWith('deg')) {
const degrees = parseFloat(value) || 0;
const radians = (degrees * Math.PI) / 180.0;
return radians;
return (degrees * Math.PI) / 180.0;
} else if (value.endsWith('rad')) {
return parseFloat(value) || 0;
} else {
return value;
}
@@ -349,4 +349,20 @@ describe('Interpolation', () => {
expect(interpolation(1e-12)).toBe('rgba(0, 0, 0, 0)');
expect(interpolation(2 / 3)).toBe('rgba(0, 0, 0, 0.667)');
});
it.each([
['radians', ['1rad', '2rad'], [1, 2]],
['degrees', ['90deg', '180deg'], [Math.PI / 2, Math.PI]],
['numbers', [1024, Math.PI], [1024, Math.PI]],
['unknown', ['5foo', '10foo'], ['5foo', '10foo']],
])(
'should convert %s to numbers in the native config',
(_, outputRange, expected) => {
const config = new AnimatedInterpolation(
{},
{inputRange: [0, 1], outputRange},
).__getNativeConfig();
expect(config.outputRange).toEqual(expected);
},
);
});
@@ -96,15 +96,19 @@ Pod::Spec.new do |s|
s.dependency "React-utils"
s.dependency "React-debug"
rel_path_from_pods_root_to_app = Pathname.new(ENV['APP_PATH']).relative_path_from(Pod::Config.instance.installation_root)
rel_path_from_pods_to_app = Pathname.new(ENV['APP_PATH']).relative_path_from(File.join(Pod::Config.instance.installation_root, 'Pods'))
s.script_phases = {
:name => "Generate Legacy Components Interop",
:script => "
WITH_ENVIRONMENT=\"$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh\"
source $WITH_ENVIRONMENT
${NODE_BINARY} ${REACT_NATIVE_PATH}/scripts/codegen/generate-legacy-interop-components.js -p #{ENV['APP_PATH']} -o ${REACT_NATIVE_PATH}/Libraries/AppDelegate
${NODE_BINARY} ${REACT_NATIVE_PATH}/scripts/codegen/generate-legacy-interop-components.js -p #{rel_path_from_pods_to_app} -o ${REACT_NATIVE_PATH}/Libraries/AppDelegate
",
:execution_position => :before_compile,
:input_files => ["#{ENV['APP_PATH']}/react-native.config.js"],
:input_files => ["#{rel_path_from_pods_root_to_app}/react-native.config.js"],
:output_files => ["${REACT_NATIVE_PATH}/Libraries/AppDelegate/RCTLegacyInteropComponents.mm"],
}
end
@@ -86,6 +86,7 @@ export const __INTERNAL_VIEW_CONFIG: PartialViewConfig =
process: require('../../StyleSheet/processColor').default,
},
pointerEvents: true,
isInvertedVirtualizedList: true,
},
}
: {
@@ -41,6 +41,7 @@ export type ScrollViewNativeProps = $ReadOnly<{
endFillColor?: ?ColorValue,
fadingEdgeLength?: ?number,
indicatorStyle?: ?('default' | 'black' | 'white'),
isInvertedVirtualizedList?: ?boolean,
keyboardDismissMode?: ?('none' | 'on-drag' | 'interactive'),
maintainVisibleContentPosition?: ?$ReadOnly<{
minIndexForVisible: number,
@@ -46,6 +46,7 @@ const ScrollViewViewConfig = {
fadingEdgeLength: true,
indicatorStyle: true,
inverted: true,
isInvertedVirtualizedList: true,
keyboardDismissMode: true,
maintainVisibleContentPosition: true,
maximumZoomScale: true,
@@ -70,6 +70,15 @@ export type ReturnKeyTypeOptions =
| ReturnKeyTypeAndroid
| ReturnKeyTypeIOS;
export type EnterKeyHintTypeAndroid = 'previous';
export type EnterKeyHintTypeIOS = 'enter';
export type EnterKeyHintType = 'done' | 'go' | 'next' | 'search' | 'send';
export type EnterKeyHintTypeOptions =
| EnterKeyHintType
| EnterKeyHintTypeAndroid
| EnterKeyHintTypeIOS;
type DataDetectorTypes =
| 'phoneNumber'
| 'link'
@@ -779,6 +788,12 @@ export interface TextInputProps
*/
returnKeyType?: ReturnKeyTypeOptions | undefined;
/**
* Determines what text should be shown to the return key on virtual keyboards.
* Has precedence over the returnKeyType prop.
*/
enterKeyHint?: EnterKeyHintTypeOptions | undefined;
/**
* If true, the text input obscures the text entered so that sensitive text like passwords stay secure.
* The default value is false.
@@ -223,13 +223,16 @@ export type TextContentType =
| 'oneTimeCode';
export type enterKeyHintType =
| 'enter'
// Cross Platform
| 'done'
| 'go'
| 'next'
| 'previous'
| 'search'
| 'send';
| 'send'
// Android-only
| 'previous'
// iOS-only
| 'enter';
type PasswordRules = string;
@@ -1344,6 +1347,7 @@ function InternalTextInput(props: Props): React.Node {
const config = React.useMemo(
() => ({
hitSlop: props.hitSlop,
onPress: (event: PressEvent) => {
if (props.editable !== false) {
if (inputRef.current != null) {
@@ -1358,6 +1362,7 @@ function InternalTextInput(props: Props): React.Node {
}),
[
props.editable,
props.hitSlop,
props.onPressIn,
props.onPressOut,
props.rejectResponderTermination,
+1 -1
View File
@@ -12,6 +12,6 @@
exports.version = {
major: 0,
minor: 72,
patch: 2,
patch: 17,
prerelease: null,
};
+2 -1
View File
@@ -30,6 +30,7 @@ export type LogData = $ReadOnly<{|
message: Message,
category: Category,
componentStack: ComponentStack,
stack?: string,
|}>;
export type Observer = (
@@ -198,7 +199,7 @@ export function addLog(log: LogData): void {
// otherwise spammy logs would pause rendering.
setImmediate(() => {
try {
const stack = parseErrorStack(errorForStackTrace?.stack);
const stack = parseErrorStack(log.stack ?? errorForStackTrace?.stack);
appendNewLog(
new LogBoxLog({
@@ -1020,6 +1020,54 @@ Please follow the instructions at: fburl.com/rn-remote-assets`,
});
});
it('detects a component stack for ts, tsx, jsx, and js files', () => {
expect(
parseLogBoxLog([
'Some kind of message\n in MyTSComponent (at MyTSXComponent.ts:1)\n in MyTSXComponent (at MyTSCComponent.tsx:1)\n in MyJSXComponent (at MyJSXComponent.jsx:1)\n in MyJSComponent (at MyJSComponent.js:1)',
]),
).toEqual({
componentStack: [
{
content: 'MyTSComponent',
fileName: 'MyTSXComponent.ts',
location: {
column: -1,
row: 1,
},
},
{
content: 'MyTSXComponent',
fileName: 'MyTSCComponent.tsx',
location: {
column: -1,
row: 1,
},
},
{
content: 'MyJSXComponent',
fileName: 'MyJSXComponent.jsx',
location: {
column: -1,
row: 1,
},
},
{
content: 'MyJSComponent',
fileName: 'MyJSComponent.js',
location: {
column: -1,
row: 1,
},
},
],
category: 'Some kind of message',
message: {
content: 'Some kind of message',
substitutions: [],
},
});
});
it('detects a component stack in the first argument (JSC)', () => {
expect(
parseLogBoxLog([
+51 -21
View File
@@ -14,12 +14,38 @@ import type {LogBoxLogData} from './LogBoxLog';
import parseErrorStack from '../../Core/Devtools/parseErrorStack';
import UTFSequence from '../../UTFSequence';
import stringifySafe from '../../Utilities/stringifySafe';
import ansiRegex from 'ansi-regex';
const ANSI_REGEX = ansiRegex().source;
const BABEL_TRANSFORM_ERROR_FORMAT =
/^(?:TransformError )?(?:SyntaxError: |ReferenceError: )(.*): (.*) \((\d+):(\d+)\)\n\n([\s\S]+)/;
// https://github.com/babel/babel/blob/33dbb85e9e9fe36915273080ecc42aee62ed0ade/packages/babel-code-frame/src/index.ts#L183-L184
const BABEL_CODE_FRAME_MARKER_PATTERN = new RegExp(
[
// Beginning of a line (per 'm' flag)
'^',
// Optional ANSI escapes for colors
`(?:${ANSI_REGEX})*`,
// Marker
'>',
// Optional ANSI escapes for colors
`(?:${ANSI_REGEX})*`,
// Left padding for line number
' +',
// Line number
'[0-9]+',
// Gutter
' \\|',
].join(''),
'm',
);
const BABEL_CODE_FRAME_ERROR_FORMAT =
// eslint-disable-next-line no-control-regex
/^(?:TransformError )?(?:.*):? (?:.*?)(\/.*): ([\s\S]+?)\n([ >]{2}[\d\s]+ \|[\s\S]+|\u{001b}[\s\S]+)/u;
const METRO_ERROR_FORMAT =
/^(?:InternalError Metro has encountered an error:) (.*): (.*) \((\d+):(\d+)\)\n\n([\s\S]+)/u;
@@ -166,7 +192,7 @@ export function parseComponentStack(message: string): ComponentStack {
if (!s) {
return null;
}
const match = s.match(/(.*) \(at (.*\.js):([\d]+)\)/);
const match = s.match(/(.*) \(at (.*\.(?:js|jsx|ts|tsx)):([\d]+)\)/);
if (!match) {
return null;
}
@@ -241,27 +267,31 @@ export function parseLogBoxException(
};
}
const babelCodeFrameError = message.match(BABEL_CODE_FRAME_ERROR_FORMAT);
// Perform a cheap match first before trying to parse the full message, which
// can get expensive for arbitrary input.
if (BABEL_CODE_FRAME_MARKER_PATTERN.test(message)) {
const babelCodeFrameError = message.match(BABEL_CODE_FRAME_ERROR_FORMAT);
if (babelCodeFrameError) {
// Codeframe errors are thrown from any use of buildCodeFrameError.
const [fileName, content, codeFrame] = babelCodeFrameError.slice(1);
return {
level: 'syntax',
stack: [],
isComponentError: false,
componentStack: [],
codeFrame: {
fileName,
location: null, // We are not given the location.
content: codeFrame,
},
message: {
content,
substitutions: [],
},
category: `${fileName}-${1}-${1}`,
};
if (babelCodeFrameError) {
// Codeframe errors are thrown from any use of buildCodeFrameError.
const [fileName, content, codeFrame] = babelCodeFrameError.slice(1);
return {
level: 'syntax',
stack: [],
isComponentError: false,
componentStack: [],
codeFrame: {
fileName,
location: null, // We are not given the location.
content: codeFrame,
},
message: {
content,
substitutions: [],
},
category: `${fileName}-${1}-${1}`,
};
}
}
if (message.match(/^TransformError /)) {
+32 -9
View File
@@ -17,6 +17,8 @@ import {type EventSubscription} from '../vendor/emitter/EventEmitter';
import {RootTagContext, createRootTag} from './RootTag';
import * as React from 'react';
const reactDevToolsHook = window.__REACT_DEVTOOLS_GLOBAL_HOOK__;
type Props = $ReadOnly<{|
children?: React.Node,
fabric?: boolean,
@@ -47,9 +49,21 @@ class AppContainer extends React.Component<Props, State> {
};
_mainRef: ?React.ElementRef<typeof View>;
_subscription: ?EventSubscription = null;
_reactDevToolsAgentListener: ?() => void = null;
static getDerivedStateFromError: any = undefined;
mountReactDevToolsOverlays(): void {
const DevtoolsOverlay = require('../Inspector/DevtoolsOverlay').default;
const devtoolsOverlay = <DevtoolsOverlay inspectedView={this._mainRef} />;
const TraceUpdateOverlay =
require('../Components/TraceUpdateOverlay/TraceUpdateOverlay').default;
const traceUpdateOverlay = <TraceUpdateOverlay />;
this.setState({devtoolsOverlay, traceUpdateOverlay});
}
componentDidMount(): void {
if (__DEV__) {
if (!this.props.internal_excludeInspector) {
@@ -71,16 +85,21 @@ class AppContainer extends React.Component<Props, State> {
this.setState({inspector});
},
);
if (window.__REACT_DEVTOOLS_GLOBAL_HOOK__ != null) {
const DevtoolsOverlay =
require('../Inspector/DevtoolsOverlay').default;
const devtoolsOverlay = (
<DevtoolsOverlay inspectedView={this._mainRef} />
if (reactDevToolsHook != null) {
if (reactDevToolsHook.reactDevtoolsAgent) {
// In case if this is not the first AppContainer rendered and React DevTools are already attached
this.mountReactDevToolsOverlays();
return;
}
this._reactDevToolsAgentListener = () =>
this.mountReactDevToolsOverlays();
reactDevToolsHook.on(
'react-devtools',
this._reactDevToolsAgentListener,
);
const TraceUpdateOverlay =
require('../Components/TraceUpdateOverlay/TraceUpdateOverlay').default;
const traceUpdateOverlay = <TraceUpdateOverlay />;
this.setState({devtoolsOverlay, traceUpdateOverlay});
}
}
}
@@ -90,6 +109,10 @@ class AppContainer extends React.Component<Props, State> {
if (this._subscription != null) {
this._subscription.remove();
}
if (reactDevToolsHook != null && this._reactDevToolsAgentListener != null) {
reactDevToolsHook.off('react-devtools', this._reactDevToolsAgentListener);
}
}
render(): React.Node {
@@ -190,6 +190,7 @@ export interface TransformsStyle {
| SkewYTransform
| MatrixTransform
)[]
| string
| undefined;
/**
* @deprecated Use matrix in transform prop instead.
@@ -10,6 +10,8 @@
import typeof {enable} from 'promise/setimmediate/rejection-tracking';
import LogBox from './LogBox/LogBox';
type ExtractOptionsType = <P>(((options?: ?P) => void)) => P;
let rejectionTrackingOptions: $Call<ExtractOptionsType, enable> = {
@@ -34,19 +36,36 @@ let rejectionTrackingOptions: $Call<ExtractOptionsType, enable> = {
? rejection
: JSON.stringify((rejection: $FlowFixMe));
}
// It could although this object is not a standard error, it still has stack information to unwind
// $FlowFixMe ignore types just check if stack is there
if (rejection.stack && typeof rejection.stack === 'string') {
stack = rejection.stack;
}
}
const warning =
`Possible Unhandled Promise Rejection (id: ${id}):\n` +
`${message ?? ''}\n` +
(stack == null ? '' : stack);
console.warn(warning);
const warning = `Possible unhandled promise rejection (id: ${id}):\n${
message ?? ''
}`;
if (__DEV__) {
LogBox.addLog({
level: 'warn',
message: {
content: warning,
substitutions: [],
},
componentStack: [],
stack,
category: 'possible_unhandled_promise_rejection',
});
} else {
console.warn(warning);
}
},
onHandled: id => {
const warning =
`Promise Rejection Handled (id: ${id})\n` +
`Promise rejection handled (id: ${id})\n` +
'This means you can ignore any previous messages of the form ' +
`"Possible Unhandled Promise Rejection (id: ${id}):"`;
`"Possible unhandled promise rejection (id: ${id}):"`;
console.warn(warning);
},
};
@@ -109,7 +109,9 @@ export default class EventEmitter<TEventToArgsMap: {...}>
Registration<$ElementType<TEventToArgsMap, TEvent>>,
> = this._registry[eventType];
if (registrations != null) {
for (const registration of [...registrations]) {
// Copy `registrations` to take a snapshot when we invoke `emit`, in case
// registrations are added or removed when listeners are invoked.
for (const registration of Array.from(registrations)) {
registration.listener.apply(registration.context, args);
}
}
@@ -101,6 +101,7 @@ RCT_EXTERN void RCTBundleURLProviderAllowPackagerServerAccess(BOOL allowed);
@property (nonatomic, assign) BOOL enableMinification;
@property (nonatomic, assign) BOOL enableDev;
@property (nonatomic, assign) BOOL inlineSourceMap;
/**
* The scheme/protocol used of the packager, the default is the http protocol
@@ -125,13 +126,32 @@ RCT_EXTERN void RCTBundleURLProviderAllowPackagerServerAccess(BOOL allowed);
+ (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot
packagerHost:(NSString *)packagerHost
enableDev:(BOOL)enableDev
enableMinification:(BOOL)enableMinification;
enableMinification:(BOOL)enableMinification
__deprecated_msg(
"Use `jsBundleURLForBundleRoot:packagerHost:enableDev:enableMinification:inlineSourceMap:` instead");
+ (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot
packagerHost:(NSString *)packagerHost
packagerScheme:(NSString *)scheme
enableDev:(BOOL)enableDev
enableMinification:(BOOL)enableMinification
modulesOnly:(BOOL)modulesOnly
runModule:(BOOL)runModule
__deprecated_msg(
"Use jsBundleURLForBundleRoot:packagerHost:enableDev:enableMinification:inlineSourceMap:modulesOnly:runModule:` instead");
+ (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot
packagerHost:(NSString *)packagerHost
enableDev:(BOOL)enableDev
enableMinification:(BOOL)enableMinification
inlineSourceMap:(BOOL)inlineSourceMap;
+ (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot
packagerHost:(NSString *)packagerHost
packagerScheme:(NSString *)scheme
enableDev:(BOOL)enableDev
enableMinification:(BOOL)enableMinification
inlineSourceMap:(BOOL)inlineSourceMap
modulesOnly:(BOOL)modulesOnly
runModule:(BOOL)runModule;
/**
@@ -142,6 +162,17 @@ RCT_EXTERN void RCTBundleURLProviderAllowPackagerServerAccess(BOOL allowed);
+ (NSURL *)resourceURLForResourcePath:(NSString *)path
packagerHost:(NSString *)packagerHost
scheme:(NSString *)scheme
query:(NSString *)query;
query:(NSString *)query
__deprecated_msg("Use version with queryItems parameter instead");
/**
* Given a hostname for the packager and a resource path (including "/"), return the URL to the resource.
* In general, please use the instance method to decide if the packager is running and fallback to the pre-packaged
* resource if it is not: -resourceURLForResourceRoot:resourceName:resourceExtension:offlineBundle:
*/
+ (NSURL *)resourceURLForResourcePath:(NSString *)path
packagerHost:(NSString *)packagerHost
scheme:(NSString *)scheme
queryItems:(NSArray<NSURLQueryItem *> *)queryItems;
@end
@@ -22,10 +22,12 @@ void RCTBundleURLProviderAllowPackagerServerAccess(BOOL allowed)
kRCTAllowPackagerAccess = allowed;
}
#endif
static NSString *const kRCTPlatformName = @"ios";
static NSString *const kRCTPackagerSchemeKey = @"RCT_packager_scheme";
static NSString *const kRCTJsLocationKey = @"RCT_jsLocation";
static NSString *const kRCTEnableDevKey = @"RCT_enableDev";
static NSString *const kRCTEnableMinificationKey = @"RCT_enableMinification";
static NSString *const kRCTInlineSourceMapKey = @"RCT_inlineSourceMap";
@implementation RCTBundleURLProvider
@@ -187,6 +189,7 @@ static NSURL *serverRootWithHostPort(NSString *hostPort, NSString *scheme)
packagerScheme:[self packagerScheme]
enableDev:[self enableDev]
enableMinification:[self enableMinification]
inlineSourceMap:[self inlineSourceMap]
modulesOnly:NO
runModule:YES];
}
@@ -199,6 +202,7 @@ static NSURL *serverRootWithHostPort(NSString *hostPort, NSString *scheme)
packagerScheme:[self packagerScheme]
enableDev:[self enableDev]
enableMinification:[self enableMinification]
inlineSourceMap:[self inlineSourceMap]
modulesOnly:YES
runModule:NO];
}
@@ -238,13 +242,29 @@ static NSURL *serverRootWithHostPort(NSString *hostPort, NSString *scheme)
return [[self class] resourceURLForResourcePath:path
packagerHost:packagerServerHostPort
scheme:packagerServerScheme
query:nil];
queryItems:nil];
}
+ (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot
packagerHost:(NSString *)packagerHost
enableDev:(BOOL)enableDev
enableMinification:(BOOL)enableMinification
{
return [self jsBundleURLForBundleRoot:bundleRoot
packagerHost:packagerHost
packagerScheme:nil
enableDev:enableDev
enableMinification:enableMinification
inlineSourceMap:NO
modulesOnly:NO
runModule:YES];
}
+ (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot
packagerHost:(NSString *)packagerHost
enableDev:(BOOL)enableDev
enableMinification:(BOOL)enableMinification
inlineSourceMap:(BOOL)inlineSourceMap
{
return [self jsBundleURLForBundleRoot:bundleRoot
@@ -252,6 +272,7 @@ static NSURL *serverRootWithHostPort(NSString *hostPort, NSString *scheme)
packagerScheme:nil
enableDev:enableDev
enableMinification:enableMinification
inlineSourceMap:inlineSourceMap
modulesOnly:NO
runModule:YES];
}
@@ -264,26 +285,44 @@ static NSURL *serverRootWithHostPort(NSString *hostPort, NSString *scheme)
modulesOnly:(BOOL)modulesOnly
runModule:(BOOL)runModule
{
NSString *path = [NSString stringWithFormat:@"/%@.bundle", bundleRoot];
#ifdef HERMES_BYTECODE_VERSION
NSString *runtimeBytecodeVersion = [NSString stringWithFormat:@"&runtimeBytecodeVersion=%u", HERMES_BYTECODE_VERSION];
#else
NSString *runtimeBytecodeVersion = @"";
#endif
return [self jsBundleURLForBundleRoot:bundleRoot
packagerHost:packagerHost
packagerScheme:nil
enableDev:enableDev
enableMinification:enableMinification
inlineSourceMap:NO
modulesOnly:modulesOnly
runModule:runModule];
}
// When we support only iOS 8 and above, use queryItems for a better API.
NSString *query = [NSString stringWithFormat:@"platform=ios&dev=%@&minify=%@&modulesOnly=%@&runModule=%@%@",
enableDev ? @"true" : @"false",
enableMinification ? @"true" : @"false",
modulesOnly ? @"true" : @"false",
runModule ? @"true" : @"false",
runtimeBytecodeVersion];
+ (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot
packagerHost:(NSString *)packagerHost
packagerScheme:(NSString *)scheme
enableDev:(BOOL)enableDev
enableMinification:(BOOL)enableMinification
inlineSourceMap:(BOOL)inlineSourceMap
modulesOnly:(BOOL)modulesOnly
runModule:(BOOL)runModule
{
NSString *path = [NSString stringWithFormat:@"/%@.bundle", bundleRoot];
BOOL lazy = enableDev;
NSArray<NSURLQueryItem *> *queryItems = @[
[[NSURLQueryItem alloc] initWithName:@"platform" value:kRCTPlatformName],
[[NSURLQueryItem alloc] initWithName:@"dev" value:enableDev ? @"true" : @"false"],
[[NSURLQueryItem alloc] initWithName:@"minify" value:enableMinification ? @"true" : @"false"],
[[NSURLQueryItem alloc] initWithName:@"inlineSourceMap" value:inlineSourceMap ? @"true" : @"false"],
[[NSURLQueryItem alloc] initWithName:@"modulesOnly" value:modulesOnly ? @"true" : @"false"],
[[NSURLQueryItem alloc] initWithName:@"runModule" value:runModule ? @"true" : @"false"],
#ifdef HERMES_BYTECODE_VERSION
[[NSURLQueryItem alloc] initWithName:@"runtimeBytecodeVersion" value:HERMES_BYTECODE_VERSION],
#endif
];
NSString *bundleID = [[NSBundle mainBundle] objectForInfoDictionaryKey:(NSString *)kCFBundleIdentifierKey];
if (bundleID) {
query = [NSString stringWithFormat:@"%@&app=%@", query, bundleID];
queryItems = [queryItems arrayByAddingObject:[[NSURLQueryItem alloc] initWithName:@"app" value:bundleID]];
}
return [[self class] resourceURLForResourcePath:path packagerHost:packagerHost scheme:scheme query:query];
return [[self class] resourceURLForResourcePath:path packagerHost:packagerHost scheme:scheme queryItems:queryItems];
}
+ (NSURL *)resourceURLForResourcePath:(NSString *)path
@@ -300,6 +339,20 @@ static NSURL *serverRootWithHostPort(NSString *hostPort, NSString *scheme)
return components.URL;
}
+ (NSURL *)resourceURLForResourcePath:(NSString *)path
packagerHost:(NSString *)packagerHost
scheme:(NSString *)scheme
queryItems:(NSArray<NSURLQueryItem *> *)queryItems
{
NSURLComponents *components = [NSURLComponents componentsWithURL:serverRootWithHostPort(packagerHost, scheme)
resolvingAgainstBaseURL:NO];
components.path = path;
if (queryItems != nil) {
components.queryItems = queryItems;
}
return components.URL;
}
- (void)updateValue:(id)object forKey:(NSString *)key
{
[[NSUserDefaults standardUserDefaults] setObject:object forKey:key];
@@ -317,6 +370,11 @@ static NSURL *serverRootWithHostPort(NSString *hostPort, NSString *scheme)
return [[NSUserDefaults standardUserDefaults] boolForKey:kRCTEnableMinificationKey];
}
- (BOOL)inlineSourceMap
{
return [[NSUserDefaults standardUserDefaults] boolForKey:kRCTInlineSourceMapKey];
}
- (NSString *)jsLocation
{
return [[NSUserDefaults standardUserDefaults] stringForKey:kRCTJsLocationKey];
@@ -346,6 +404,11 @@ static NSURL *serverRootWithHostPort(NSString *hostPort, NSString *scheme)
[self updateValue:@(enableMinification) forKey:kRCTEnableMinificationKey];
}
- (void)setInlineSourceMap:(BOOL)inlineSourceMap
{
[self updateValue:@(inlineSourceMap) forKey:kRCTInlineSourceMapKey];
}
- (void)setPackagerScheme:(NSString *)packagerScheme
{
[self updateValue:packagerScheme forKey:kRCTPackagerSchemeKey];
@@ -23,7 +23,7 @@ NSDictionary* RCTGetReactNativeVersion(void)
__rnVersion = @{
RCTVersionMajor: @(0),
RCTVersionMinor: @(72),
RCTVersionPatch: @(2),
RCTVersionPatch: @(17),
RCTVersionPrerelease: [NSNull null],
};
});
@@ -128,6 +128,11 @@ RCT_EXPORT_MODULE()
_paused = YES;
_timers = [NSMutableDictionary new];
_inBackground = NO;
RCTExecuteOnMainQueue(^{
if (!self->_inBackground && [RCTSharedApplication() applicationState] == UIApplicationStateBackground) {
[self appDidMoveToBackground];
}
});
for (NSString *name in @[
UIApplicationWillResignActiveNotification,
@@ -243,7 +243,7 @@ task createNativeDepsDirectories {
}
task downloadBoost(dependsOn: createNativeDepsDirectories, type: Download) {
src("https://boostorg.jfrog.io/artifactory/main/release/${BOOST_VERSION.replace("_", ".")}/source/boost_${BOOST_VERSION}.tar.gz")
src("https://archives.boost.io/release/${BOOST_VERSION.replace("_", ".")}/source/boost_${BOOST_VERSION}.tar.gz")
onlyIfModified(true)
overwrite(false)
retries(5)
@@ -1,4 +1,4 @@
VERSION_NAME=0.72.2
VERSION_NAME=0.72.17
GROUP=com.facebook.react
# JVM Versions
@@ -113,6 +113,7 @@ public abstract class ReactActivity extends AppCompatActivity
@Override
public void onRequestPermissionsResult(
int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
mDelegate.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
@@ -20,6 +20,7 @@ import android.content.pm.PackageManager;
import android.graphics.Color;
import android.graphics.Typeface;
import android.hardware.SensorManager;
import android.os.Build;
import android.util.Pair;
import android.view.Gravity;
import android.view.View;
@@ -1142,7 +1143,7 @@ public abstract class DevSupportManagerBase implements DevSupportManager {
if (!mIsReceiverRegistered) {
IntentFilter filter = new IntentFilter();
filter.addAction(getReloadAppAction(mApplicationContext));
mApplicationContext.registerReceiver(mReloadAppBroadcastReceiver, filter);
compatRegisterReceiver(mApplicationContext, mReloadAppBroadcastReceiver, filter, true);
mIsReceiverRegistered = true;
}
@@ -1258,4 +1259,21 @@ public abstract class DevSupportManagerBase implements DevSupportManager {
return mSurfaceDelegateFactory.createSurfaceDelegate(moduleName);
}
/**
* Starting with Android 14, apps and services that target Android 14 and use context-registered
* receivers are required to specify a flag to indicate whether or not the receiver should be
* exported to all other apps on the device: either RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED
*
* <p>https://developer.android.com/about/versions/14/behavior-changes-14#runtime-receivers-exported
*/
private void compatRegisterReceiver(
Context context, BroadcastReceiver receiver, IntentFilter filter, boolean exported) {
if (Build.VERSION.SDK_INT >= 34 && context.getApplicationInfo().targetSdkVersion >= 34) {
context.registerReceiver(
receiver, filter, exported ? Context.RECEIVER_EXPORTED : Context.RECEIVER_NOT_EXPORTED);
} else {
context.registerReceiver(receiver, filter);
}
}
}
@@ -53,7 +53,6 @@ import com.facebook.react.bridge.WritableMap;
import com.facebook.react.common.build.ReactBuildConfig;
import com.facebook.react.common.mapbuffer.ReadableMapBuffer;
import com.facebook.react.config.ReactFeatureFlags;
import com.facebook.react.fabric.events.EventBeatManager;
import com.facebook.react.fabric.events.EventEmitterWrapper;
import com.facebook.react.fabric.events.FabricEventEmitter;
import com.facebook.react.fabric.interop.InteropEventEmitter;
@@ -61,6 +60,7 @@ import com.facebook.react.fabric.mounting.MountItemDispatcher;
import com.facebook.react.fabric.mounting.MountingManager;
import com.facebook.react.fabric.mounting.SurfaceMountingManager;
import com.facebook.react.fabric.mounting.SurfaceMountingManager.ViewEvent;
import com.facebook.react.fabric.mounting.mountitems.DispatchCommandMountItem;
import com.facebook.react.fabric.mounting.mountitems.DispatchIntCommandMountItem;
import com.facebook.react.fabric.mounting.mountitems.DispatchStringCommandMountItem;
import com.facebook.react.fabric.mounting.mountitems.IntBufferBatchMountItem;
@@ -79,6 +79,7 @@ import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.UIManagerHelper;
import com.facebook.react.uimanager.ViewManagerPropertyUpdater;
import com.facebook.react.uimanager.ViewManagerRegistry;
import com.facebook.react.uimanager.events.BatchEventDispatchedListener;
import com.facebook.react.uimanager.events.EventCategoryDef;
import com.facebook.react.uimanager.events.EventDispatcher;
import com.facebook.react.uimanager.events.EventDispatcherImpl;
@@ -168,7 +169,7 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
@NonNull private final MountItemDispatcher mMountItemDispatcher;
@NonNull private final ViewManagerRegistry mViewManagerRegistry;
@NonNull private final EventBeatManager mEventBeatManager;
@NonNull private final BatchEventDispatchedListener mBatchEventDispatchedListener;
@NonNull
private final CopyOnWriteArrayList<UIManagerListener> mListeners = new CopyOnWriteArrayList<>();
@@ -208,16 +209,16 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
};
public FabricUIManager(
ReactApplicationContext reactContext,
ViewManagerRegistry viewManagerRegistry,
EventBeatManager eventBeatManager) {
@NonNull ReactApplicationContext reactContext,
@NonNull ViewManagerRegistry viewManagerRegistry,
@NonNull BatchEventDispatchedListener batchEventDispatchedListener) {
mDispatchUIFrameCallback = new DispatchUIFrameCallback(reactContext);
mReactApplicationContext = reactContext;
mMountingManager = new MountingManager(viewManagerRegistry, mMountItemExecutor);
mMountItemDispatcher =
new MountItemDispatcher(mMountingManager, new MountItemDispatchListener());
mEventDispatcher = new EventDispatcherImpl(reactContext);
mEventBeatManager = eventBeatManager;
mBatchEventDispatchedListener = batchEventDispatchedListener;
mReactApplicationContext.addLifecycleEventListener(this);
mViewManagerRegistry = viewManagerRegistry;
@@ -385,7 +386,7 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
@Override
public void initialize() {
mEventDispatcher.registerEventEmitter(FABRIC, new FabricEventEmitter(this));
mEventDispatcher.addBatchEventDispatchedListener(mEventBeatManager);
mEventDispatcher.addBatchEventDispatchedListener(mBatchEventDispatchedListener);
if (ENABLE_FABRIC_PERF_LOGS) {
mDevToolsReactPerfLogger = new DevToolsReactPerfLogger();
mDevToolsReactPerfLogger.addDevToolsReactPerfLoggerListener(FABRIC_PERF_LOGGER);
@@ -424,10 +425,11 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
// memory immediately.
mDispatchUIFrameCallback.stop();
mEventDispatcher.removeBatchEventDispatchedListener(mEventBeatManager);
mEventDispatcher.removeBatchEventDispatchedListener(mBatchEventDispatchedListener);
mEventDispatcher.unregisterEventEmitter(FABRIC);
mReactApplicationContext.unregisterComponentCallbacks(mViewManagerRegistry);
mViewManagerRegistry.invalidate();
// Remove lifecycle listeners (onHostResume, onHostPause) since the FabricUIManager is going
// away. Then stop the mDispatchUIFrameCallback false will cause the choreographer
@@ -1039,8 +1041,16 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
final int reactTag,
final String commandId,
@Nullable final ReadableArray commandArgs) {
mMountItemDispatcher.dispatchCommandMountItem(
new DispatchStringCommandMountItem(surfaceId, reactTag, commandId, commandArgs));
if (ReactFeatureFlags.unstable_useFabricInterop) {
// For Fabric Interop, we check if the commandId is an integer. If it is, we use the integer
// overload of dispatchCommand. Otherwise, we use the string overload.
// and the events won't be correctly dispatched.
mMountItemDispatcher.dispatchCommandMountItem(
createDispatchCommandMountItemForInterop(surfaceId, reactTag, commandId, commandArgs));
} else {
mMountItemDispatcher.dispatchCommandMountItem(
new DispatchStringCommandMountItem(surfaceId, reactTag, commandId, commandArgs));
}
}
@Override
@@ -1200,6 +1210,24 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
}
}
/**
* Util function that takes care of handling commands for Fabric Interop. If the command is a
* string that represents a number (say "42"), it will be parsed as an integer and the
* corresponding dispatch command mount item will be created.
*/
/* package */ DispatchCommandMountItem createDispatchCommandMountItemForInterop(
final int surfaceId,
final int reactTag,
final String commandId,
@Nullable final ReadableArray commandArgs) {
try {
int commandIdInteger = Integer.parseInt(commandId);
return new DispatchIntCommandMountItem(surfaceId, reactTag, commandIdInteger, commandArgs);
} catch (NumberFormatException e) {
return new DispatchStringCommandMountItem(surfaceId, reactTag, commandId, commandArgs);
}
}
private class DispatchUIFrameCallback extends GuardedFrameCallback {
private volatile boolean mIsMountingEnabled = true;
@@ -17,6 +17,6 @@ public class ReactNativeVersion {
public static final Map<String, Object> VERSION = MapBuilder.<String, Object>of(
"major", 0,
"minor", 72,
"patch", 2,
"patch", 17,
"prerelease", null);
}
@@ -25,6 +25,7 @@ import com.facebook.react.modules.blob.BlobModule;
import com.facebook.react.modules.blob.FileReaderModule;
import com.facebook.react.modules.camera.ImageStoreManager;
import com.facebook.react.modules.clipboard.ClipboardModule;
import com.facebook.react.modules.devloading.DevLoadingModule;
import com.facebook.react.modules.devtoolssettings.DevToolsSettingsManagerModule;
import com.facebook.react.modules.dialog.DialogModule;
import com.facebook.react.modules.fresco.FrescoModule;
@@ -72,6 +73,7 @@ import javax.inject.Provider;
AppearanceModule.class,
AppStateModule.class,
BlobModule.class,
DevLoadingModule.class,
FileReaderModule.class,
ClipboardModule.class,
DialogModule.class,
@@ -113,6 +115,8 @@ public class MainReactPackage extends TurboReactPackage implements ViewManagerOn
return new AppStateModule(context);
case BlobModule.NAME:
return new BlobModule(context);
case DevLoadingModule.NAME:
return new DevLoadingModule(context);
case FileReaderModule.NAME:
return new FileReaderModule(context);
case ClipboardModule.NAME:
@@ -371,6 +375,7 @@ public class MainReactPackage extends TurboReactPackage implements ViewManagerOn
AppearanceModule.class,
AppStateModule.class,
BlobModule.class,
DevLoadingModule.class,
FileReaderModule.class,
ClipboardModule.class,
DialogModule.class,
@@ -175,7 +175,7 @@ public class UIImplementation {
*
* @return The num of root view
*/
private int getRootViewNum() {
public int getRootViewNum() {
return mOperationsQueue.getNativeViewHierarchyManager().getRootViewNum();
}
@@ -608,12 +608,6 @@ public class UIImplementation {
/** Invoked at the end of the transaction to commit any updates to the node hierarchy. */
public void dispatchViewUpdates(int batchId) {
if (getRootViewNum() <= 0) {
// If there are no RootViews registered, there will be no View updates to dispatch.
// This is a hack to prevent this from being called when Fabric is used everywhere.
// This should no longer be necessary in Bridgeless Mode.
return;
}
SystraceMessage.beginSection(
Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "UIImplementation.dispatchViewUpdates")
.arg("batchId", batchId)
@@ -792,6 +786,7 @@ public class UIImplementation {
public void onCatalystInstanceDestroyed() {
mViewOperationsEnabled = false;
mViewManagers.invalidate();
}
public void setViewHierarchyUpdateDebugListener(
@@ -719,7 +719,12 @@ public class UIManagerModule extends ReactContextBaseJavaModule
listener.willDispatchViewUpdates(this);
}
try {
mUIImplementation.dispatchViewUpdates(batchId);
// If there are no RootViews registered, there will be no View updates to dispatch.
// This is a hack to prevent this from being called when Fabric is used everywhere.
// This should no longer be necessary in Bridgeless Mode.
if (mUIImplementation.getRootViewNum() > 0) {
mUIImplementation.dispatchViewUpdates(batchId);
}
} finally {
Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
}
@@ -117,7 +117,6 @@ import java.util.Set;
Map viewManagerBubblingEvents = viewManager.getExportedCustomBubblingEventTypeConstants();
if (viewManagerBubblingEvents != null) {
if (ReactFeatureFlags.enableFabricRenderer && ReactFeatureFlags.unstable_useFabricInterop) {
// For Fabric, events needs to be fired with a "top" prefix.
// For the sake of Fabric Interop, here we normalize events adding "top" in their
@@ -133,6 +132,12 @@ import java.util.Set;
Map viewManagerDirectEvents = viewManager.getExportedCustomDirectEventTypeConstants();
if (viewManagerDirectEvents != null) {
if (ReactFeatureFlags.enableFabricRenderer && ReactFeatureFlags.unstable_useFabricInterop) {
// For Fabric, events needs to be fired with a "top" prefix.
// For the sake of Fabric Interop, here we normalize events adding "top" in their
// name if the user hasn't provided it.
normalizeEventTypes(viewManagerDirectEvents);
}
recursiveMerge(cumulativeDirectEventTypes, viewManagerDirectEvents);
recursiveMerge(viewManagerDirectEvents, defaultDirectEvents);
viewManagerConstants.put(DIRECT_EVENTS_KEY, viewManagerDirectEvents);
@@ -10,6 +10,8 @@ package com.facebook.react.uimanager;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.Nullable;
import com.facebook.common.logging.FLog;
import com.facebook.react.common.ReactConstants;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -65,6 +67,17 @@ public class ViewGroupDrawingOrderHelper {
* ViewGroup#getChildDrawingOrder}.
*/
public int getChildDrawingOrder(int childCount, int index) {
if (mDrawingOrderIndices != null
&& (index >= mDrawingOrderIndices.length || mDrawingOrderIndices[index] >= childCount)) {
FLog.w(
ReactConstants.TAG,
"getChildDrawingOrder index out of bounds! Please check any custom view manipulations you"
+ " may have done. childCount = %d, index = %d",
childCount,
index);
update();
}
if (mDrawingOrderIndices == null) {
ArrayList<View> viewsToSort = new ArrayList<>();
for (int i = 0; i < childCount; i++) {
@@ -103,12 +103,28 @@ public final class ViewManagerRegistry implements ComponentCallbacks2 {
viewManagers = new ArrayList<>(mViewManagers.values());
}
Runnable runnable =
new Runnable() {
@Override
public void run() {
for (ViewManager viewManager : viewManagers) {
viewManager.onSurfaceStopped(surfaceId);
}
() -> {
for (ViewManager viewManager : viewManagers) {
viewManager.onSurfaceStopped(surfaceId);
}
};
if (UiThreadUtil.isOnUiThread()) {
runnable.run();
} else {
UiThreadUtil.runOnUiThread(runnable);
}
}
/** Called on instance destroy */
public void invalidate() {
final List<ViewManager> viewManagers;
synchronized (this) {
viewManagers = new ArrayList<>(mViewManagers.values());
}
Runnable runnable =
() -> {
for (ViewManager viewManager : viewManagers) {
viewManager.invalidate();
}
};
if (UiThreadUtil.isOnUiThread()) {
@@ -204,6 +204,11 @@ import java.util.Map;
mDefaultValue = defaultValue;
}
public ColorPropSetter(ReactPropGroup prop, Method setter, int index, int defaultValue) {
super(prop, "mixed", setter, index);
mDefaultValue = defaultValue;
}
@Override
protected Object getValueOrDefault(Object value, Context context) {
if (value == null) {
@@ -331,6 +336,10 @@ import java.util.Map;
super(prop, "mixed", setter);
}
public BoxedColorPropSetter(ReactPropGroup prop, Method setter, int index) {
super(prop, "mixed", setter, index);
}
@Override
protected @Nullable Object getValueOrDefault(Object value, Context context) {
if (value != null) {
@@ -463,7 +472,11 @@ import java.util.Map;
}
} else if (propTypeClass == int.class) {
for (int i = 0; i < names.length; i++) {
props.put(names[i], new IntPropSetter(annotation, method, i, annotation.defaultInt()));
if ("Color".equals(annotation.customType())) {
props.put(names[i], new ColorPropSetter(annotation, method, i, annotation.defaultInt()));
} else {
props.put(names[i], new IntPropSetter(annotation, method, i, annotation.defaultInt()));
}
}
} else if (propTypeClass == float.class) {
for (int i = 0; i < names.length; i++) {
@@ -476,7 +489,11 @@ import java.util.Map;
}
} else if (propTypeClass == Integer.class) {
for (int i = 0; i < names.length; i++) {
props.put(names[i], new BoxedIntPropSetter(annotation, method, i));
if ("Color".equals(annotation.customType())) {
props.put(names[i], new BoxedColorPropSetter(annotation, method, i));
} else {
props.put(names[i], new BoxedIntPropSetter(annotation, method, i));
}
}
} else {
throw new RuntimeException(
@@ -103,6 +103,10 @@ public class MaintainVisibleScrollPositionHelper<ScrollViewT extends ViewGroup &
}
View firstVisibleView = mFirstVisibleView.get();
if (firstVisibleView == null) {
return;
}
Rect newFrame = new Rect();
firstVisibleView.getHitRect(newFrame);
@@ -218,6 +218,12 @@ public class ReactScrollView extends ScrollView
}
}
public void abortAnimation() {
if (mScroller != null && !mScroller.isFinished()) {
mScroller.abortAnimation();
}
}
public void setSnapInterval(int snapInterval) {
mSnapInterval = snapInterval;
}
@@ -1076,7 +1082,6 @@ public class ReactScrollView extends ScrollView
*/
@Override
public void scrollTo(int x, int y) {
mScroller.abortAnimation();
super.scrollTo(x, y);
ReactScrollViewHelper.updateFabricScrollState(this);
setPendingContentOffsets(x, y);
@@ -213,6 +213,7 @@ public class ReactScrollViewManager extends ViewGroupManager<ReactScrollView>
@Override
public void scrollTo(
ReactScrollView scrollView, ReactScrollViewCommandHelper.ScrollToCommandData data) {
scrollView.abortAnimation();
if (data.mAnimated) {
scrollView.reactSmoothScrollTo(data.mDestX, data.mDestY);
} else {
@@ -379,4 +380,22 @@ public class ReactScrollViewManager extends ViewGroupManager<ReactScrollView>
public void setScrollEventThrottle(ReactScrollView view, int scrollEventThrottle) {
view.setScrollEventThrottle(scrollEventThrottle);
}
@ReactProp(name = "isInvertedVirtualizedList")
public void setIsInvertedVirtualizedList(ReactScrollView view, boolean applyFix) {
// Usually when inverting the scroll view we are using scaleY: -1 on the list
// and on the parent container. HOWEVER, starting from android API 33 there is
// a bug that can cause an ANR due to that. Thus we are using different transform
// commands to circumvent the ANR. This however causes the vertical scrollbar to
// be on the wrong side. Thus we are moving it to the other side, when the list
// is inverted.
// See also:
// - https://github.com/facebook/react-native/issues/35350
// - https://issuetracker.google.com/issues/287304310
if (applyFix) {
view.setVerticalScrollbarPosition(View.SCROLLBAR_POSITION_LEFT);
} else {
view.setVerticalScrollbarPosition(View.SCROLLBAR_POSITION_DEFAULT);
}
}
}
@@ -10,6 +10,8 @@ package com.facebook.react.views.textinput;
import static com.facebook.react.uimanager.UIManagerHelper.getReactContext;
import static com.facebook.react.views.text.TextAttributeProps.UNSET;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Paint;
@@ -28,8 +30,11 @@ import android.text.TextWatcher;
import android.text.method.KeyListener;
import android.text.method.QwertyKeyListener;
import android.util.TypedValue;
import android.view.ActionMode;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.accessibility.AccessibilityNodeInfo;
@@ -180,6 +185,35 @@ public class ReactEditText extends AppCompatEditText
}
};
ViewCompat.setAccessibilityDelegate(this, editTextAccessibilityDelegate);
ActionMode.Callback customActionModeCallback =
new ActionMode.Callback() {
/*
* Editor onCreateActionMode adds the cut, copy, paste, share, autofill,
* and paste as plain text items to the context menu.
*/
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
menu.removeItem(android.R.id.pasteAsPlainText);
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return true;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
return false;
}
@Override
public void onDestroyActionMode(ActionMode mode) {}
};
setCustomSelectionActionModeCallback(customActionModeCallback);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
setCustomInsertionActionModeCallback(customActionModeCallback);
}
}
@Override
@@ -268,6 +302,37 @@ public class ReactEditText extends AppCompatEditText
return inputConnection;
}
/*
* Called when a context menu option for the text view is selected.
* React Native replaces copy (as rich text) with copy as plain text.
*/
@Override
public boolean onTextContextMenuItem(int id) {
if (id == android.R.id.paste) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
id = android.R.id.pasteAsPlainText;
} else {
ClipboardManager clipboard =
(ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE);
ClipData previousClipData = clipboard.getPrimaryClip();
if (previousClipData != null) {
for (int i = 0; i < previousClipData.getItemCount(); i++) {
final CharSequence text = previousClipData.getItemAt(i).coerceToText(getContext());
final CharSequence paste = (text instanceof Spanned) ? text.toString() : text;
if (paste != null) {
ClipData clipData = ClipData.newPlainText(null, text);
clipboard.setPrimaryClip(clipData);
}
}
boolean actionPerformed = super.onTextContextMenuItem(id);
clipboard.setPrimaryClip(previousClipData);
return actionPerformed;
}
}
}
return super.onTextContextMenuItem(id);
}
@Override
public void clearFocus() {
setFocusableInTouchMode(false);
@@ -420,10 +420,10 @@ public class ReactViewGroup extends ViewGroup
if (!intersects && child.getParent() != null && !isAnimating) {
// We can try saving on invalidate call here as the view that we remove is out of visible area
// therefore invalidation is not necessary.
super.removeViewsInLayout(idx - clippedSoFar, 1);
removeViewsInLayout(idx - clippedSoFar, 1);
needUpdateClippingRecursive = true;
} else if (intersects && child.getParent() == null) {
super.addViewInLayout(child, idx - clippedSoFar, sDefaultLayoutParam, true);
addViewInLayout(child, idx - clippedSoFar, sDefaultLayoutParam, true);
invalidate();
needUpdateClippingRecursive = true;
} else if (intersects) {
@@ -501,23 +501,18 @@ public class ReactViewGroup extends ViewGroup
return ViewUtil.getUIManagerType(getId()) == UIManagerType.FABRIC;
}
@Override
public void addView(View child, int index, ViewGroup.LayoutParams params) {
// This will get called for every overload of addView so there is not need to override every
// method.
private void handleAddView(View view) {
UiThreadUtil.assertOnUiThread();
if (!customDrawOrderDisabled()) {
getDrawingOrderHelper().handleAddView(child);
getDrawingOrderHelper().handleAddView(view);
setChildrenDrawingOrderEnabled(getDrawingOrderHelper().shouldEnableCustomDrawingOrder());
} else {
setChildrenDrawingOrderEnabled(false);
}
super.addView(child, index, params);
}
@Override
public void removeView(View view) {
private void handleRemoveView(View view) {
UiThreadUtil.assertOnUiThread();
if (!customDrawOrderDisabled()) {
@@ -526,24 +521,62 @@ public class ReactViewGroup extends ViewGroup
} else {
setChildrenDrawingOrderEnabled(false);
}
}
private void handleRemoveViews(int start, int count) {
int endIndex = start + count;
for (int index = start; index < endIndex; index++) {
if (index < getChildCount()) {
handleRemoveView(getChildAt(index));
}
}
}
@Override
public void addView(View child, int index, ViewGroup.LayoutParams params) {
// This will get called for every overload of addView so there is not need to override every
// method.
handleAddView(child);
super.addView(child, index, params);
}
@Override
protected boolean addViewInLayout(
View child, int index, LayoutParams params, boolean preventRequestLayout) {
handleAddView(child);
return super.addViewInLayout(child, index, params, preventRequestLayout);
}
@Override
public void removeView(View view) {
handleRemoveView(view);
super.removeView(view);
}
@Override
public void removeViewAt(int index) {
UiThreadUtil.assertOnUiThread();
if (!customDrawOrderDisabled()) {
getDrawingOrderHelper().handleRemoveView(getChildAt(index));
setChildrenDrawingOrderEnabled(getDrawingOrderHelper().shouldEnableCustomDrawingOrder());
} else {
setChildrenDrawingOrderEnabled(false);
}
handleRemoveView(getChildAt(index));
super.removeViewAt(index);
}
@Override
public void removeViewInLayout(View view) {
handleRemoveView(view);
super.removeViewInLayout(view);
}
@Override
public void removeViewsInLayout(int start, int count) {
handleRemoveViews(start, count);
super.removeViewsInLayout(start, count);
}
@Override
public void removeViews(int start, int count) {
handleRemoveViews(start, count);
super.removeViews(start, count);
}
@Override
protected int getChildDrawingOrder(int childCount, int index) {
UiThreadUtil.assertOnUiThread();
@@ -665,7 +698,7 @@ public class ReactViewGroup extends ViewGroup
clippedSoFar++;
}
}
super.removeViewsInLayout(index - clippedSoFar, 1);
removeViewsInLayout(index - clippedSoFar, 1);
}
removeFromArray(index);
}
@@ -8,6 +8,11 @@ set(CMAKE_VERBOSE_MAKEFILE on)
project(ReactAndroid)
# Convert input paths to CMake format (with forward slashes)
file(TO_CMAKE_PATH "${REACT_ANDROID_DIR}" REACT_ANDROID_DIR)
file(TO_CMAKE_PATH "${REACT_BUILD_DIR}" REACT_BUILD_DIR)
file(TO_CMAKE_PATH "${REACT_COMMON_DIR}" REACT_COMMON_DIR)
# If you have ccache installed, we're going to honor it.
find_program(CCACHE_FOUND ccache)
if(CCACHE_FOUND)
@@ -0,0 +1,57 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.react.fabric
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.uimanager.ViewManagerRegistry
import com.facebook.react.uimanager.events.BatchEventDispatchedListener
import com.facebook.testutils.fakes.FakeBatchEventDispatchedListener
import com.facebook.testutils.shadows.ShadowSoLoader
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.RuntimeEnvironment
import org.robolectric.annotation.Config
@RunWith(RobolectricTestRunner::class)
@Config(shadows = [ShadowSoLoader::class])
class FabricUIManagerTest {
private lateinit var reactContext: ReactApplicationContext
private lateinit var viewManagerRegistry: ViewManagerRegistry
private lateinit var batchEventDispatchedListener: BatchEventDispatchedListener
private lateinit var underTest: FabricUIManager
@Before
fun setup() {
reactContext = ReactApplicationContext(RuntimeEnvironment.getApplication())
viewManagerRegistry = ViewManagerRegistry(emptyList())
batchEventDispatchedListener = FakeBatchEventDispatchedListener()
underTest = FabricUIManager(reactContext, viewManagerRegistry, batchEventDispatchedListener)
}
@Test
fun createDispatchCommandMountItemForInterop_withValidString_returnsStringEvent() {
val command = underTest.createDispatchCommandMountItemForInterop(11, 1, "anEvent", null)
// DispatchStringCommandMountItem is package private so we can `as` check it.
val className = command::class.java.name.substringAfterLast(".")
assertEquals("DispatchStringCommandMountItem", className)
}
@Test
fun createDispatchCommandMountItemForInterop_withValidInt_returnsIntEvent() {
val command = underTest.createDispatchCommandMountItemForInterop(11, 1, "42", null)
// DispatchIntCommandMountItem is package private so we can `as` check it.
val className = command::class.java.name.substringAfterLast(".")
assertEquals("DispatchIntCommandMountItem", className)
}
}
@@ -0,0 +1,17 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.testutils.fakes
import com.facebook.react.uimanager.events.BatchEventDispatchedListener
/** A fake [BatchEventDispatchedListener] for testing that does nothing. */
class FakeBatchEventDispatchedListener : BatchEventDispatchedListener {
override fun onBatchEventDispatched() {
// do nothing
}
}
@@ -0,0 +1,24 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.testutils.shadows
import android.content.Context
import com.facebook.soloader.SoLoader
import kotlin.jvm.JvmStatic
import org.robolectric.annotation.Implementation
import org.robolectric.annotation.Implements
@Suppress("UNUSED_PARAMETER")
@Implements(SoLoader::class)
class ShadowSoLoader {
companion object {
@JvmStatic @Implementation fun init(context: Context?, flags: Int) {}
@JvmStatic @Implementation fun loadLibrary(shortName: String?): Boolean = true
}
}
@@ -37,7 +37,7 @@ Pod::Spec.new do |s|
"DEFINES_MODULE" => "YES" }
if ENV['USE_FRAMEWORKS']
s.header_mappings_dir = File.absolute_path('./')
s.header_mappings_dir = './'
s.module_name = 'React_Fabric'
end
@@ -37,7 +37,7 @@ Pod::Spec.new do |s|
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17",
"GCC_WARN_PEDANTIC" => "YES" }
if ENV['USE_FRAMEWORKS']
s.header_mappings_dir = File.absolute_path("./")
s.header_mappings_dir = './'
end
# TODO (T48588859): Restructure this target to align with dir structure: "react/nativemodule/..."
@@ -17,7 +17,7 @@ namespace facebook::react {
constexpr struct {
int32_t Major = 0;
int32_t Minor = 72;
int32_t Patch = 2;
int32_t Patch = 17;
std::string_view Prerelease = "";
} ReactNativeVersion;
@@ -302,6 +302,9 @@ class JSCRuntime : public jsi::Runtime {
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_10_0
#define _JSC_NO_ARRAY_BUFFERS
#endif
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 160400
#define _JSC_HAS_INSPECTABLE
#endif
#endif
#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
#if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_11
@@ -398,6 +401,15 @@ JSCRuntime::JSCRuntime(JSGlobalContextRef ctx)
stringCounter_(0)
#endif
{
#ifndef NDEBUG
#ifdef _JSC_HAS_INSPECTABLE
#if (__OSX_AVAILABLE_STARTING(MAC_NA, IPHONE_16_4))
if (__builtin_available(macOS 13.3, iOS 16.4, tvOS 16.4, *)) {
JSGlobalContextSetInspectable(ctx_, true);
}
#endif
#endif
#endif
}
JSCRuntime::~JSCRuntime() {
@@ -36,8 +36,7 @@ Pod::Spec.new do |s|
s.header_dir = "jsi"
s.compiler_flags = folly_compiler_flags + ' ' + boost_compiler_flags
s.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/RCT-Folly\" \"$(PODS_ROOT)/DoubleConversion\"",
"DEFINES_MODULE" => "YES" }
s.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/RCT-Folly\" \"$(PODS_ROOT)/DoubleConversion\"" }
s.dependency "boost", "1.76.0"
s.dependency "DoubleConversion"
@@ -27,11 +27,13 @@ Pod::Spec.new do |s|
s.source = source
s.source_files = "**/*.{cpp,h}"
s.header_dir = "react/debug"
s.pod_target_xcconfig = { "CLANG_CXX_LANGUAGE_STANDARD" => "c++17",
"DEFINES_MODULE" => "YES" }
s.pod_target_xcconfig = {
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17",
"DEFINES_MODULE" => "YES"
}
if ENV['USE_FRAMEWORKS']
s.module_name = "React_debug"
s.header_mappings_dir = File.absolute_path("../..")
s.header_mappings_dir = "../.."
end
end
@@ -17,5 +17,7 @@
// control and use as a more reliable xplat flag. For any build that doesn't
// have NDEBUG defined, we enable REACT_NATIVE_DEBUG for convenience.
#ifndef NDEBUG
#ifndef COCOAPODS
#define REACT_NATIVE_DEBUG 1
#endif
#endif
@@ -37,7 +37,7 @@ Pod::Spec.new do |s|
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17",
"GCC_WARN_PEDANTIC" => "YES" }
if ENV['USE_FRAMEWORKS']
s.header_mappings_dir = File.absolute_path('./')
s.header_mappings_dir = './'
end
s.source_files = "ReactCommon/**/*.{mm,cpp,h}"
@@ -37,7 +37,7 @@ Pod::Spec.new do |s|
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17",
"GCC_WARN_PEDANTIC" => "YES" }
if ENV['USE_FRAMEWORKS']
s.header_mappings_dir = File.absolute_path('./')
s.header_mappings_dir = './'
end
@@ -74,19 +74,35 @@ static Class getViewManagerFromComponentName(const std::string &componentName)
return nil;
}
static std::shared_ptr<void> const constructCoordinator(
ContextContainer::Shared const &contextContainer,
ComponentDescriptor::Flavor const &flavor)
static Class getViewManagerClass(const std::string &componentName, RCTBridge *bridge)
{
Class viewManager = getViewManagerFromComponentName(componentName);
if (viewManager != nil) {
return viewManager;
}
// If all the heuristics fail, let's try to retrieve the view manager from the bridge/bridgeProxy
if (bridge != nil) {
return [[bridge moduleForName:RCTNSStringFromString(componentName)] class];
}
return nil;
}
static const std::shared_ptr<void> constructCoordinator(
const ContextContainer::Shared &contextContainer,
const ComponentDescriptor::Flavor &flavor)
{
auto componentName = *std::static_pointer_cast<std::string const>(flavor);
Class viewManagerClass = getViewManagerFromComponentName(componentName);
assert(viewManagerClass);
auto optionalBridge = contextContainer->find<std::shared_ptr<void>>("Bridge");
RCTBridge *bridge;
if (optionalBridge) {
bridge = unwrapManagedObjectWeakly(optionalBridge.value());
}
auto componentName = *std::static_pointer_cast<std::string const>(flavor);
Class viewManagerClass = getViewManagerClass(componentName, bridge);
assert(viewManagerClass);
auto optionalEventDispatcher = contextContainer->find<std::shared_ptr<void>>("RCTEventDispatcher");
RCTEventDispatcher *eventDispatcher;
if (optionalEventDispatcher) {
@@ -92,6 +92,10 @@ using namespace facebook::react;
if (props.isObject()) {
NSDictionary<NSString *, id> *convertedProps = convertFollyDynamicToId(props);
[_componentData setProps:convertedProps forView:view];
if ([view respondsToSelector:@selector(didSetProps:)]) {
[view performSelector:@selector(didSetProps:) withObject:[convertedProps allKeys]];
}
}
}
@@ -319,6 +319,15 @@ ScrollViewProps::ScrollViewProps(
rawProps,
"scrollToOverflowEnabled",
sourceProps.scrollToOverflowEnabled,
{})),
isInvertedVirtualizedList(
CoreFeatures::enablePropIteratorSetter
? sourceProps.isInvertedVirtualizedList
: convertRawProp(
context,
rawProps,
"isInvertedVirtualizedList",
sourceProps.isInvertedVirtualizedList,
{})) {}
void ScrollViewProps::setProp(
@@ -368,6 +377,7 @@ void ScrollViewProps::setProp(
RAW_SET_PROP_SWITCH_CASE_BASIC(snapToEnd);
RAW_SET_PROP_SWITCH_CASE_BASIC(contentInsetAdjustmentBehavior);
RAW_SET_PROP_SWITCH_CASE_BASIC(scrollToOverflowEnabled);
RAW_SET_PROP_SWITCH_CASE_BASIC(isInvertedVirtualizedList);
}
}
@@ -492,7 +502,11 @@ SharedDebugStringConvertibleList ScrollViewProps::getDebugProps() const {
debugStringConvertibleItem(
"snapToStart", snapToStart, defaultScrollViewProps.snapToStart),
debugStringConvertibleItem(
"snapToEnd", snapToEnd, defaultScrollViewProps.snapToEnd)};
"snapToEnd", snapToEnd, defaultScrollViewProps.snapToEnd),
debugStringConvertibleItem(
"isInvertedVirtualizedList",
snapToEnd,
defaultScrollViewProps.isInvertedVirtualizedList)};
}
#endif
@@ -69,6 +69,7 @@ class ScrollViewProps final : public ViewProps {
ContentInsetAdjustmentBehavior contentInsetAdjustmentBehavior{
ContentInsetAdjustmentBehavior::Never};
bool scrollToOverflowEnabled{false};
bool isInvertedVirtualizedList{false};
#pragma mark - DebugStringConvertible
@@ -17,6 +17,11 @@ namespace react {
// It should be used as infrequently as possible - most props can and should
// be parsed without any context.
struct PropsParserContext {
PropsParserContext(
SurfaceId const surfaceId,
ContextContainer const &contextContainer)
: surfaceId(surfaceId), contextContainer(contextContainer) {}
// Non-copyable
PropsParserContext(const PropsParserContext &) = delete;
PropsParserContext &operator=(const PropsParserContext &) = delete;
@@ -38,6 +38,8 @@ void RawPropsKeyMap::insert(
item.value = value;
key.render(item.name, &item.length);
items_.push_back(item);
react_native_assert(
items_.size() < std::numeric_limits<RawPropsPropNameLength>::max());
}
void RawPropsKeyMap::reindex() noexcept {
@@ -42,6 +42,7 @@ RawValue const *RawPropsParser::at(
// This is not thread-safe part; this happens only during initialization of
// a `ComponentDescriptor` where it is actually safe.
keys_.push_back(key);
react_native_assert(size < std::numeric_limits<RawPropsValueIndex>::max());
nameToIndex_.insert(key, static_cast<RawPropsValueIndex>(size));
return nullptr;
}
@@ -16,11 +16,11 @@ namespace react {
/*
* Type used to represent an index of some stored values in small arrays.
*/
using RawPropsValueIndex = uint8_t;
using RawPropsValueIndex = uint16_t;
static_assert(
sizeof(RawPropsValueIndex) == 1,
"RawPropsValueIndex must be one byte size.");
using RawPropsPropNameLength = uint8_t;
sizeof(RawPropsValueIndex) == 2,
"RawPropsValueIndex must be two byte size.");
using RawPropsPropNameLength = uint16_t;
using RawPropsPropNameHash = uint32_t;
/*
@@ -45,13 +45,15 @@ Pod::Spec.new do |s|
if ENV['USE_FRAMEWORKS']
s.module_name = "React_graphics"
s.header_mappings_dir = File.absolute_path("../../..")
s.header_mappings_dir = "../../.."
header_search_paths = header_search_paths + ["\"$(PODS_TARGET_SRCROOT)/platform/ios\""]
end
s.pod_target_xcconfig = { "USE_HEADERMAP" => "NO",
"HEADER_SEARCH_PATHS" => header_search_paths.join(" "),
"DEFINES_MODULE" => "YES" }
s.pod_target_xcconfig = {
"USE_HEADERMAP" => "NO",
"HEADER_SEARCH_PATHS" => header_search_paths.join(" "),
"DEFINES_MODULE" => "YES"
}
s.dependency "glog"
s.dependency "RCT-Folly/Fabric", folly_version
@@ -42,7 +42,7 @@ Pod::Spec.new do |s|
if ENV['USE_FRAMEWORKS']
s.module_name = "React_ImageManager"
s.header_mappings_dir = File.absolute_path("./")
s.header_mappings_dir = "./"
header_search_paths = header_search_paths + [
"\"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers\"",
"\"$(PODS_ROOT)/DoubleConversion\"",
@@ -355,6 +355,11 @@ CommitStatus ShadowTree::tryCommit(
newRootShadowNode = delegate_.shadowTreeWillCommit(
*this, oldRootShadowNode, newRootShadowNode);
if (!newRootShadowNode ||
(commitOptions.shouldYield && commitOptions.shouldYield())) {
return CommitStatus::Cancelled;
}
// Layout nodes.
std::vector<LayoutableShadowNode const *> affectedLayoutableNodes{};
affectedLayoutableNodes.reserve(1024);
@@ -372,17 +377,16 @@ CommitStatus ShadowTree::tryCommit(
// Updating `currentRevision_` in unique manner if it hasn't changed.
std::unique_lock lock(commitMutex_);
if (commitOptions.shouldYield && commitOptions.shouldYield()) {
return CommitStatus::Cancelled;
}
if (currentRevision_.number != oldRevision.number) {
return CommitStatus::Failed;
}
auto newRevisionNumber = oldRevision.number + 1;
if (!newRootShadowNode ||
(commitOptions.shouldYield && commitOptions.shouldYield())) {
return CommitStatus::Cancelled;
}
{
std::lock_guard<std::mutex> dispatchLock(EventEmitter::DispatchMutex());
@@ -47,7 +47,7 @@ Pod::Spec.new do |s|
if ENV['USE_FRAMEWORKS']
s.module_name = "React_runtimescheduler"
s.header_mappings_dir = File.absolute_path("../../..")
s.header_mappings_dir = "../../.."
end
s.dependency "React-jsi"
@@ -42,13 +42,15 @@ Pod::Spec.new do |s|
s.compiler_flags = folly_compiler_flags
s.header_dir = "react/utils"
s.exclude_files = "tests"
s.pod_target_xcconfig = { "CLANG_CXX_LANGUAGE_STANDARD" => "c++17",
"HEADER_SEARCH_PATHS" => header_search_paths.join(' '),
"DEFINES_MODULE" => "YES" }
s.pod_target_xcconfig = {
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17",
"HEADER_SEARCH_PATHS" => header_search_paths.join(' '),
"DEFINES_MODULE" => "YES"
}
if ENV['USE_FRAMEWORKS']
s.module_name = "React_utils"
s.header_mappings_dir = File.absolute_path("../..")
s.header_mappings_dir = "../.."
end
s.dependency "RCT-Folly", folly_version
@@ -0,0 +1,14 @@
/**
* @flow strict
* @format
*/
declare module 'ansi-regex' {
declare export type Options = {
/**
* Match only the first ANSI escape.
*/
+onlyFirst?: boolean,
};
declare export default function ansiRegex(options?: Options): RegExp;
}
+10 -9
View File
@@ -1,6 +1,6 @@
{
"name": "react-native",
"version": "0.72.2",
"version": "0.72.17",
"bin": "./cli.js",
"description": "A framework for building native apps using React",
"license": "MIT",
@@ -79,27 +79,28 @@
},
"dependencies": {
"@jest/create-cache-key-function": "^29.2.1",
"@react-native-community/cli": "11.3.5",
"@react-native-community/cli-platform-android": "11.3.5",
"@react-native-community/cli-platform-ios": "11.3.5",
"@react-native-community/cli": "^11.4.1",
"@react-native-community/cli-platform-android": "^11.4.1",
"@react-native-community/cli-platform-ios": "^11.4.1",
"@react-native/assets-registry": "^0.72.0",
"@react-native/codegen": "^0.72.6",
"@react-native/codegen": "^0.72.8",
"@react-native/gradle-plugin": "^0.72.11",
"@react-native/js-polyfills": "^0.72.1",
"@react-native/normalize-colors": "^0.72.0",
"@react-native/virtualized-lists": "^0.72.6",
"@react-native/virtualized-lists": "^0.72.8",
"abort-controller": "^3.0.0",
"anser": "^1.4.9",
"base64-js": "^1.1.2",
"deprecated-react-native-prop-types": "4.1.0",
"deprecated-react-native-prop-types": "^4.2.3",
"ansi-regex": "^5.0.0",
"event-target-shim": "^5.0.1",
"flow-enums-runtime": "^0.0.5",
"invariant": "^2.2.4",
"jest-environment-node": "^29.2.1",
"jsc-android": "^250231.0.0",
"memoize-one": "^5.0.0",
"metro-runtime": "0.76.7",
"metro-source-map": "0.76.7",
"metro-runtime": "^0.76.9",
"metro-source-map": "^0.76.9",
"mkdirp": "^0.5.1",
"nullthrows": "^1.1.1",
"pretty-format": "^26.5.2",
@@ -68,7 +68,7 @@ class CodegenTests < Test::Unit::TestCase
assert_equal(Pod::Executable.executed_commands.length, 0)
end
def testCheckAndGenerateEmptyThirdPartyProvider_whenHeaderMissingAndCodegenMissing_raiseError()
def testCheckAndGenerateEmptyThirdPartyProvider_whenHeaderMissingAndCodegenMissing_dontBuildCodegen()
# Arrange
FileMock.mocked_existing_files([
@@ -76,7 +76,7 @@ class CodegenTests < Test::Unit::TestCase
])
# Act
assert_raise {
assert_nothing_raised {
checkAndGenerateEmptyThirdPartyProvider!(@prefix, false, dir_manager: DirMock, file_manager: FileMock)
}
@@ -84,16 +84,16 @@ class CodegenTests < Test::Unit::TestCase
assert_equal(Pathname.pwd_invocation_count, 1)
assert_equal(Pod::Config.instance.installation_root.relative_path_from_invocation_count, 1)
assert_equal(FileMock.exist_invocation_params, [
@prefix + "/React/Fabric/" + @third_party_provider_header
@prefix + "/React/Fabric/" + @third_party_provider_header,
@prefix + "/React/Fabric/tmpSchemaList.txt",
])
assert_equal(DirMock.exist_invocation_params, [
@base_path + "/"+ @prefix + "/../react-native-codegen",
@base_path + "/"+ @prefix + "/../@react-native/codegen",
])
assert_equal(Pod::UI.collected_messages, [])
assert_equal(Pod::UI.collected_messages, ["[Codegen] generating an empty RCTThirdPartyFabricComponentsProvider"])
assert_equal($collected_commands, [])
assert_equal(FileMock.open_files.length, 0)
assert_equal(Pod::Executable.executed_commands.length, 0)
assert_equal(FileMock.open_files.length, 1)
assert_equal(Pod::Executable.executed_commands.length, 1)
end
def testCheckAndGenerateEmptyThirdPartyProvider_whenImplementationMissingAndCodegenrepoExists_dontBuildCodegen()
@@ -145,7 +145,7 @@ class CodegenTests < Test::Unit::TestCase
def testCheckAndGenerateEmptyThirdPartyProvider_whenBothMissing_buildCodegen()
# Arrange
codegen_cli_path = @base_path + "/" + @prefix + "/../@react-native/codegen"
codegen_cli_path = @base_path + "/" + @prefix + "/../react-native-codegen"
DirMock.mocked_existing_dirs([
codegen_cli_path,
])
@@ -160,15 +160,14 @@ class CodegenTests < Test::Unit::TestCase
@prefix + "/React/Fabric/" + @tmp_schema_list_file
])
assert_equal(DirMock.exist_invocation_params, [
@base_path + "/" + @prefix + "/../react-native-codegen",
codegen_cli_path,
codegen_cli_path + "/lib",
])
assert_equal(Pod::UI.collected_messages, [
"[Codegen] building #{codegen_cli_path}.",
"[Codegen] building #{codegen_cli_path}",
"[Codegen] generating an empty RCTThirdPartyFabricComponentsProvider"
])
assert_equal($collected_commands, ["~/app/ios/../../../@react-native/codegen/scripts/oss/build.sh"])
assert_equal($collected_commands, ["~/app/ios/../../../react-native-codegen/scripts/oss/build.sh"])
assert_equal(FileMock.open_files[0].collected_write, ["[]"])
assert_equal(FileMock.open_files[0].fsync_invocation_count, 1)
assert_equal(Pod::Executable.executed_commands[0], {
@@ -107,7 +107,6 @@ class JSEngineTests < Test::Unit::TestCase
assert_equal($podInvocation["libevent"][:version], "~> 2.1.12")
hermes_engine_pod_invocation = $podInvocation["hermes-engine"]
assert_equal(hermes_engine_pod_invocation[:podspec], "../../sdks/hermes-engine/hermes-engine.podspec")
assert_equal(hermes_engine_pod_invocation[:tag], "")
end
def test_setupHermes_installsPods_installsFabricSubspecWhenFabricEnabled
@@ -122,7 +121,6 @@ class JSEngineTests < Test::Unit::TestCase
assert_equal($podInvocation["React-jsi"][:path], "../../ReactCommon/jsi")
hermes_engine_pod_invocation = $podInvocation["hermes-engine"]
assert_equal(hermes_engine_pod_invocation[:podspec], "../../sdks/hermes-engine/hermes-engine.podspec")
assert_equal(hermes_engine_pod_invocation[:tag], "")
assert_equal($podInvocation["React-hermes"][:path], "../../ReactCommon/hermes")
assert_equal($podInvocation["libevent"][:version], "~> 2.1.12")
end
@@ -128,7 +128,7 @@ class NewArchitectureTests < Test::Unit::TestCase
NewArchitectureHelper.install_modules_dependencies(spec, true, '2021.07.22.00')
# Assert
assert_equal(spec.compiler_flags, NewArchitectureHelper.folly_compiler_flags)
assert_equal(spec.compiler_flags, "$(inherited) #{NewArchitectureHelper.folly_compiler_flags} -DRCT_NEW_ARCH_ENABLED=1")
assert_equal(spec.pod_target_xcconfig["HEADER_SEARCH_PATHS"], "\"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/DoubleConversion\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTFabric/RCTFabric.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-utils/React_utils.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-debug/React_debug.framework/Headers\"")
assert_equal(spec.pod_target_xcconfig["CLANG_CXX_LANGUAGE_STANDARD"], "c++17")
assert_equal(spec.pod_target_xcconfig["OTHER_CPLUSPLUSFLAGS"], "$(inherited) -DRCT_NEW_ARCH_ENABLED=1 -DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1")
@@ -166,7 +166,7 @@ class NewArchitectureTests < Test::Unit::TestCase
NewArchitectureHelper.install_modules_dependencies(spec, false, '2021.07.22.00')
# Assert
assert_equal(spec.compiler_flags, "-Wno-nullability-completeness #{NewArchitectureHelper.folly_compiler_flags}")
assert_equal(spec.compiler_flags, "$(inherited) -Wno-nullability-completeness #{NewArchitectureHelper.folly_compiler_flags}")
assert_equal(spec.pod_target_xcconfig["HEADER_SEARCH_PATHS"], "#{other_flags} \"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/DoubleConversion\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTFabric/RCTFabric.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-utils/React_utils.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-debug/React_debug.framework/Headers\"")
assert_equal(spec.pod_target_xcconfig["CLANG_CXX_LANGUAGE_STANDARD"], "c++17")
assert_equal(
@@ -0,0 +1,26 @@
# 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.
class XcodebuildMock < Xcodebuild
@@version = ""
@@version_invocation_count = 0
def self.set_version=(v)
@@version = v
end
def self.version
@@version_invocation_count += 1
@@version
end
def self.version_invocation_count
@@version_invocation_count
end
def self.reset()
@@version_invocation_count = 0
end
end
@@ -14,6 +14,7 @@ require_relative "./test_utils/FileMock.rb"
require_relative "./test_utils/systemUtils.rb"
require_relative "./test_utils/PathnameMock.rb"
require_relative "./test_utils/TargetDefinitionMock.rb"
require_relative "./test_utils/XcodebuildMock.rb"
class UtilsTests < Test::Unit::TestCase
def setup
@@ -28,6 +29,7 @@ class UtilsTests < Test::Unit::TestCase
Pod::Config.reset()
SysctlChecker.reset()
Environment.reset()
XcodebuildMock.reset()
ENV['RCT_NEW_ARCH_ENABLED'] = '0'
ENV['USE_HERMES'] = '1'
ENV['USE_FRAMEWORKS'] = nil
@@ -177,11 +179,33 @@ class UtilsTests < Test::Unit::TestCase
# ============================ #
# Test - Exclude Architectures #
# ============================ #
def test_excludeArchitectures_whenHermesEngineIsNotIncluded_excludeNothing
def test_excludeArchitectures_whenHermesEngineIsNotIncluded_withNoValue_leaveUnset
# Arrange
user_project_mock = prepare_empty_user_project_mock()
pods_projects_mock = PodsProjectMock.new()
installer = InstallerMock.new(PodsProjectMock.new(), [
AggregatedProjectMock.new(user_project_mock)
])
# Act
ReactNativePodsUtils.exclude_i386_architecture_while_using_hermes(installer)
# Assert
user_project_mock.build_configurations.each do |config|
assert_equal(config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"], nil)
end
assert_equal(user_project_mock.save_invocation_count, 0)
assert_equal(pods_projects_mock.save_invocation_count, 0)
end
def test_excludeArchitectures_whenHermesEngineIsNotIncluded_withExistingValue_preserveExistingValue
# Arrange
user_project_mock = prepare_empty_user_project_mock()
user_project_mock.build_configurations.each do |config|
config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = "arm64"
end
pods_projects_mock = PodsProjectMock.new()
installer = InstallerMock.new(PodsProjectMock.new(), [
installer = InstallerMock.new(pods_projects_mock, [
AggregatedProjectMock.new(user_project_mock)
])
@@ -190,13 +214,14 @@ class UtilsTests < Test::Unit::TestCase
# Assert
user_project_mock.build_configurations.each do |config|
assert_equal(config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"], "")
assert_equal(config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"], "arm64")
end
assert_equal(user_project_mock.save_invocation_count, 1)
assert_equal(user_project_mock.save_invocation_count, 0)
assert_equal(pods_projects_mock.save_invocation_count, 0)
end
def test_excludeArchitectures_whenHermesEngineIsIncluded_excludeI386
def test_excludeArchitectures_whenHermesEngineIsIncluded_withNoValue_onlyExcludeI386
# Arrange
user_project_mock = prepare_empty_user_project_mock()
pods_projects_mock = PodsProjectMock.new([], {"hermes-engine" => {}})
@@ -216,6 +241,29 @@ class UtilsTests < Test::Unit::TestCase
assert_equal(pods_projects_mock.save_invocation_count, 1)
end
def test_excludeArchitectures_whenHermesEngineIsIncluded_withExistingValue_appendI386
# Arrange
user_project_mock = prepare_empty_user_project_mock()
user_project_mock.build_configurations.each do |config|
config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = "arm64"
end
pods_projects_mock = PodsProjectMock.new([], {"hermes-engine" => {}})
installer = InstallerMock.new(pods_projects_mock, [
AggregatedProjectMock.new(user_project_mock)
])
# Act
ReactNativePodsUtils.exclude_i386_architecture_while_using_hermes(installer)
# Assert
user_project_mock.build_configurations.each do |config|
assert_equal(config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"], "arm64 i386")
end
assert_equal(user_project_mock.save_invocation_count, 1)
assert_equal(pods_projects_mock.save_invocation_count, 1)
end
# ================= #
# Test - Fix Config #
# ================= #
@@ -437,9 +485,9 @@ class UtilsTests < Test::Unit::TestCase
# ================================= #
# Test - Apply Xcode 15 Patch #
# ================================= #
def test_applyXcode15Patch_correctlyAppliesNecessaryPatch
def test_applyXcode15Patch_whenXcodebuild14_correctlyAppliesNecessaryPatch
# Arrange
XcodebuildMock.set_version = "Xcode 14.3"
first_target = prepare_target("FirstTarget")
second_target = prepare_target("SecondTarget")
third_target = TargetMock.new("ThirdTarget", [
@@ -468,24 +516,117 @@ class UtilsTests < Test::Unit::TestCase
])
# Act
ReactNativePodsUtils.apply_xcode_15_patch(installer)
user_project_mock.build_configurations.each do |config|
assert_nil(config.build_settings["OTHER_LDFLAGS"])
end
ReactNativePodsUtils.apply_xcode_15_patch(installer, :xcodebuild_manager => XcodebuildMock)
# Assert
first_target.build_configurations.each do |config|
assert_equal(config.build_settings["GCC_PREPROCESSOR_DEFINITIONS"].strip,
'$(inherited) "_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION"'
)
user_project_mock.build_configurations.each do |config|
assert_equal("$(inherited) _LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION", config.build_settings["GCC_PREPROCESSOR_DEFINITIONS"])
assert_equal("$(inherited) ", config.build_settings["OTHER_LDFLAGS"])
end
second_target.build_configurations.each do |config|
assert_equal(config.build_settings["GCC_PREPROCESSOR_DEFINITIONS"].strip,
'$(inherited) "_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION"'
)
# User project and Pods project
assert_equal(2, XcodebuildMock.version_invocation_count)
end
def test_applyXcode15Patch_whenXcodebuild15_correctlyAppliesNecessaryPatch
# Arrange
XcodebuildMock.set_version = "Xcode 15.0"
first_target = prepare_target("FirstTarget")
second_target = prepare_target("SecondTarget")
third_target = TargetMock.new("ThirdTarget", [
BuildConfigurationMock.new("Debug", {
"GCC_PREPROCESSOR_DEFINITIONS" => '$(inherited) "SomeFlag=1" '
}),
BuildConfigurationMock.new("Release", {
"GCC_PREPROCESSOR_DEFINITIONS" => '$(inherited) "SomeFlag=1" '
}),
], nil)
user_project_mock = UserProjectMock.new("/a/path", [
prepare_config("Debug"),
prepare_config("Release"),
],
:native_targets => [
first_target,
second_target
]
)
pods_projects_mock = PodsProjectMock.new([], {"hermes-engine" => {}}, :native_targets => [
third_target
])
installer = InstallerMock.new(pods_projects_mock, [
AggregatedProjectMock.new(user_project_mock)
])
# Act
user_project_mock.build_configurations.each do |config|
assert_nil(config.build_settings["OTHER_LDFLAGS"])
end
third_target.build_configurations.each do |config|
assert_equal(config.build_settings["GCC_PREPROCESSOR_DEFINITIONS"].strip,
'$(inherited) "SomeFlag=1" "_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION"'
)
ReactNativePodsUtils.apply_xcode_15_patch(installer, :xcodebuild_manager => XcodebuildMock)
# Assert
user_project_mock.build_configurations.each do |config|
assert_equal("$(inherited) _LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION", config.build_settings["GCC_PREPROCESSOR_DEFINITIONS"])
assert_equal("$(inherited) -Wl -ld_classic", config.build_settings["OTHER_LDFLAGS"])
end
# User project and Pods project
assert_equal(2, XcodebuildMock.version_invocation_count)
end
def test_applyXcode15Patch_whenXcodebuild14ButProjectHasSettings_correctlyRemovesNecessaryPatch
# Arrange
XcodebuildMock.set_version = "Xcode 14.3"
first_target = prepare_target("FirstTarget")
second_target = prepare_target("SecondTarget")
third_target = TargetMock.new("ThirdTarget", [
BuildConfigurationMock.new("Debug", {
"GCC_PREPROCESSOR_DEFINITIONS" => '$(inherited) "SomeFlag=1" '
}),
BuildConfigurationMock.new("Release", {
"GCC_PREPROCESSOR_DEFINITIONS" => '$(inherited) "SomeFlag=1" '
}),
], nil)
debug_config = prepare_config("Debug", {"OTHER_LDFLAGS" => "$(inherited) -Wl -ld_classic "})
release_config = prepare_config("Release", {"OTHER_LDFLAGS" => "$(inherited) -Wl -ld_classic "})
user_project_mock = UserProjectMock.new("/a/path", [
debug_config,
release_config,
],
:native_targets => [
first_target,
second_target
]
)
pods_projects_mock = PodsProjectMock.new([debug_config.clone, release_config.clone], {"hermes-engine" => {}}, :native_targets => [
third_target
])
installer = InstallerMock.new(pods_projects_mock, [
AggregatedProjectMock.new(user_project_mock)
])
# Act
user_project_mock.build_configurations.each do |config|
assert_equal("$(inherited) -Wl -ld_classic ", config.build_settings["OTHER_LDFLAGS"])
end
ReactNativePodsUtils.apply_xcode_15_patch(installer, :xcodebuild_manager => XcodebuildMock)
# Assert
user_project_mock.build_configurations.each do |config|
assert_equal("$(inherited) _LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION", config.build_settings["GCC_PREPROCESSOR_DEFINITIONS"])
assert_equal("$(inherited)", config.build_settings["OTHER_LDFLAGS"])
end
# User project and Pods project
assert_equal(2, XcodebuildMock.version_invocation_count)
end
# ==================================== #
@@ -744,12 +885,14 @@ def prepare_empty_user_project_mock
])
end
def prepare_config(config_name)
return BuildConfigurationMock.new(config_name, {"LIBRARY_SEARCH_PATHS" => [
def prepare_config(config_name, extra_config = {})
config = {"LIBRARY_SEARCH_PATHS" => [
"$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)",
"\"$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)\"",
"another/path",
]})
]}.merge(extra_config)
return BuildConfigurationMock.new(config_name, config)
end
def prepare_target(name, product_type = nil, dependencies = [])
@@ -11,23 +11,12 @@
# - dir_manager: a class that implements the `Dir` interface. Defaults to `Dir`, the Dependency can be injected for testing purposes.
# @throws an error if it could not find the codegen folder.
def build_codegen!(react_native_path, relative_installation_root, dir_manager: Dir)
codegen_repo_path = "#{relative_installation_root}/#{react_native_path}/../react-native-codegen";
codegen_npm_path = "#{relative_installation_root}/#{react_native_path}/../@react-native/codegen";
codegen_cli_path = ""
codegen_repo_path = "#{relative_installation_root}/#{react_native_path}/../react-native-codegen";
return unless dir_manager.exist?(codegen_repo_path) && !dir_manager.exist?("#{codegen_repo_path}/lib")
if dir_manager.exist?(codegen_repo_path)
codegen_cli_path = codegen_repo_path
elsif dir_manager.exist?(codegen_npm_path)
codegen_cli_path = codegen_npm_path
else
raise "[codegen] Could not find react-native-codegen."
end
if !dir_manager.exist?("#{codegen_cli_path}/lib")
Pod::UI.puts "[Codegen] building #{codegen_cli_path}."
system("#{codegen_cli_path}/scripts/oss/build.sh")
end
end
Pod::UI.puts "[Codegen] building #{codegen_repo_path}"
system("#{codegen_repo_path}/scripts/oss/build.sh")
end
# It generates an empty `ThirdPartyProvider`, required by Fabric to load the components
#
@@ -11,6 +11,14 @@ class SysctlChecker
end
end
# Helper class that is used to easily send commands to Xcodebuild
# And that can be subclassed for testing purposes.
class Xcodebuild
def self.version
`xcodebuild -version`
end
end
# Helper object to wrap system properties like RUBY_PLATFORM
# This makes it easier to mock the behaviour in tests
class Environment
@@ -26,3 +34,11 @@ class Finder
return `find #{path} -type f \\( #{js_files} -or #{ts_files} \\)`.split("\n").sort()
end
end
module Helpers
class Constants
def self.min_ios_version_supported
return '12.4'
end
end
end
@@ -30,12 +30,8 @@ def setup_hermes!(react_native_path: "../node_modules/react-native", fabric_enab
abort unless prep_status == 0
pod 'React-jsi', :path => "#{react_native_path}/ReactCommon/jsi"
# This `:tag => hermestag` below is only to tell CocoaPods to update hermes-engine when React Native version changes.
# We have custom logic to compute the source for hermes-engine. See sdks/hermes-engine/*
hermestag_file = File.join(react_native_path, "sdks", ".hermesversion")
hermestag = File.exist?(hermestag_file) ? File.read(hermestag_file).strip : ''
pod 'hermes-engine', :podspec => "#{react_native_path}/sdks/hermes-engine/hermes-engine.podspec", :tag => hermestag
pod 'hermes-engine', :podspec => "#{react_native_path}/sdks/hermes-engine/hermes-engine.podspec"
pod 'React-hermes', :path => "#{react_native_path}/ReactCommon/hermes"
pod 'libevent', '~> 2.1.12'
end
@@ -87,6 +87,10 @@ class NewArchitectureHelper
current_config = hash["pod_target_xcconfig"] != nil ? hash["pod_target_xcconfig"] : {}
current_headers = current_config["HEADER_SEARCH_PATHS"] != nil ? current_config["HEADER_SEARCH_PATHS"] : ""
flags_to_add = new_arch_enabled ?
"#{@@folly_compiler_flags} -DRCT_NEW_ARCH_ENABLED=1" :
"#{@@folly_compiler_flags}"
header_search_paths = ["\"$(PODS_ROOT)/boost\""]
if ENV['USE_FRAMEWORKS']
header_search_paths << "\"$(PODS_ROOT)/DoubleConversion\""
@@ -100,7 +104,7 @@ class NewArchitectureHelper
header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-debug/React_debug.framework/Headers\""
end
header_search_paths_string = header_search_paths.join(" ")
spec.compiler_flags = compiler_flags.empty? ? @@folly_compiler_flags : "#{compiler_flags} #{@@folly_compiler_flags}"
spec.compiler_flags = compiler_flags.empty? ? "$(inherited) #{flags_to_add}" : "$(inherited) #{compiler_flags} #{flags_to_add}"
current_config["HEADER_SEARCH_PATHS"] = current_headers.empty? ?
header_search_paths_string :
"#{current_headers} #{header_search_paths_string}"
@@ -0,0 +1,170 @@
# 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.
module PrivacyManifestUtils
def self.add_aggregated_privacy_manifest(installer)
user_project = get_user_project_from(installer)
targets = get_application_targets(user_project)
file_path = get_privacyinfo_file_path(user_project, targets)
privacy_info = read_privacyinfo_file(file_path) || {
"NSPrivacyCollectedDataTypes" => [],
"NSPrivacyTracking" => false
}
# Get all required reason APIs defined in current pods
required_reason_apis = get_used_required_reason_apis(installer)
# Add the Required Reason APIs from React Native core
get_core_accessed_apis.each do |accessed_api|
api_type = accessed_api["NSPrivacyAccessedAPIType"]
reasons = accessed_api["NSPrivacyAccessedAPITypeReasons"]
required_reason_apis[api_type] ||= []
required_reason_apis[api_type] += reasons
end
# Merge the Required Reason APIs from pods with the ones from the existing PrivacyInfo file
(privacy_info["NSPrivacyAccessedAPITypes"] || []).each do |accessed_api|
api_type = accessed_api["NSPrivacyAccessedAPIType"]
reasons = accessed_api["NSPrivacyAccessedAPITypeReasons"]
# Add reasons from existing PrivacyInfo file to the ones from pods
required_reason_apis[api_type] ||= []
required_reason_apis[api_type] += reasons
end
# Update the existing PrivacyInfo file with the new aggregated data
privacy_info["NSPrivacyAccessedAPITypes"] = required_reason_apis.map { |api_type, reasons|
{
"NSPrivacyAccessedAPIType" => api_type,
"NSPrivacyAccessedAPITypeReasons" => reasons.uniq
}
}
Xcodeproj::Plist.write_to_path(privacy_info, file_path)
targets.each do |target|
ensure_reference(file_path, user_project, target)
end
end
def self.get_application_targets(user_project)
return user_project.targets.filter { |t| t.symbol_type == :application }
end
def self.read_privacyinfo_file(file_path)
# Maybe add missing default NSPrivacyTracking, NSPrivacyTrackingDomains, NSPrivacyCollectedDataTypes, but this works without those keys
source_data = nil
# Try to read an existing PrivacyInfo.xcprivacy file
begin
source_data = Xcodeproj::Plist.read_from_path(file_path)
Pod::UI.puts "[Privacy Manifest Aggregation] Appending aggregated reasons to existing PrivacyInfo.xcprivacy file."
rescue => e
Pod::UI.puts "[Privacy Manifest Aggregation] No existing PrivacyInfo.xcprivacy file found, creating a new one."
end
return source_data
end
def self.ensure_reference(file_path, user_project, target)
reference_exists = target.resources_build_phase.files_references.any? { |file_ref| file_ref.path&.end_with? "PrivacyInfo.xcprivacy" }
unless reference_exists
# We try to find the main group, but if it doesn't exist, we default to adding the file to the project root both work
file_root = user_project.root_object.main_group.children.first { |group| group.name == target.name } || user_project
file_ref = file_root.new_file(file_path)
build_file = target.resources_build_phase.add_file_reference(file_ref, true)
end
end
def self.get_privacyinfo_file_path(user_project, targets)
file_refs = targets.flat_map { |target| target.resources_build_phase.files_references }
existing_file = file_refs.find { |file_ref| file_ref.path&.end_with? "PrivacyInfo.xcprivacy" }
if existing_file
return existing_file.real_path
end
# We try to find a file we know exists in the project to get the path to the main group directory
info_plist_path = user_project.files.find { |file_ref| file_ref.name == "Info.plist" }
if info_plist_path.nil?
# return path that is sibling to .xcodeproj
path = user_project.path
return File.join(File.dirname(path), "PrivacyInfo.xcprivacy")
end
return File.join(File.dirname(info_plist_path.real_path),"PrivacyInfo.xcprivacy")
end
def self.get_used_required_reason_apis(installer)
# A dictionary with keys of type string (NSPrivacyAccessedAPIType) and values of type string[] (NSPrivacyAccessedAPITypeReasons[])
used_apis = {}
Pod::UI.puts "[Privacy Manifest Aggregation] Reading .xcprivacy files to aggregate all used Required Reason APIs."
installer.pod_targets.each do |pod_target|
# puts pod_target
pod_target.file_accessors.each do |file_accessor|
file_accessor.resource_bundles.each do |bundle_name, bundle_files|
bundle_files.each do |file_path|
# This needs to be named like that due to apple requirements
if File.basename(file_path) == 'PrivacyInfo.xcprivacy'
content = Xcodeproj::Plist.read_from_path(file_path)
accessed_api_types = content["NSPrivacyAccessedAPITypes"]
accessed_api_types&.each do |accessed_api|
api_type = accessed_api["NSPrivacyAccessedAPIType"]
reasons = accessed_api["NSPrivacyAccessedAPITypeReasons"]
next unless api_type
used_apis[api_type] ||= []
used_apis[api_type] += reasons
end
end
end
end
end
end
return used_apis
end
def self.get_privacy_manifest_paths_from(user_project)
privacy_manifests = user_project
.files
.select { |p|
p.path&.end_with?('PrivacyInfo.xcprivacy')
}
return privacy_manifests
end
def self.get_core_accessed_apis()
file_timestamp_accessed_api = {
"NSPrivacyAccessedAPIType" => "NSPrivacyAccessedAPICategoryFileTimestamp",
"NSPrivacyAccessedAPITypeReasons" => ["C617.1"],
}
user_defaults_accessed_api = {
"NSPrivacyAccessedAPIType" => "NSPrivacyAccessedAPICategoryUserDefaults",
"NSPrivacyAccessedAPITypeReasons" => ["CA92.1"],
}
boot_time_accessed_api = {
"NSPrivacyAccessedAPIType" => "NSPrivacyAccessedAPICategorySystemBootTime",
"NSPrivacyAccessedAPITypeReasons" => ["35F9.1"],
}
return [file_timestamp_accessed_api, user_defaults_accessed_api, boot_time_accessed_api]
end
def self.get_user_project_from(installer)
user_project = installer.aggregate_targets
.map{ |t| t.user_project }
.first
return user_project
end
def self.add_privacy_manifest_if_needed(installer)
user_project = get_user_project_from(installer)
privacy_manifest = self.get_privacy_manifest_paths_from(user_project).first
if privacy_manifest.nil?
privacy_manifest = {
"NSPrivacyCollectedDataTypes" => [],
"NSPrivacyTracking" => false,
"NSPrivacyAccessedAPITypes" => get_core_accessed_apis
}
path = File.join(user_project.path.parent, "PrivacyInfo.xcprivacy")
Xcodeproj::Plist.write_to_path(privacy_manifest, path)
Pod::UI.puts "Your app does not have a privacy manifest! A template has been generated containing Required Reasons API usage in the core React Native library. Please add the PrivacyInfo.xcprivacy file to your project and complete data use, tracking and any additional required reasons your app is using according to Apple's guidance: https://developer.apple.com/documentation/bundleresources/privacy_manifest_files. Then, you will need to manually add this file to your project in Xcode.".red
end
end
end
+144 -16
View File
@@ -54,17 +54,49 @@ class ReactNativePodsUtils
end
def self.exclude_i386_architecture_while_using_hermes(installer)
projects = self.extract_projects(installer)
is_using_hermes = self.has_pod(installer, 'hermes-engine')
# Hermes does not support `i386` architecture
excluded_archs_default = self.has_pod(installer, 'hermes-engine') ? "i386" : ""
if is_using_hermes
key = "EXCLUDED_ARCHS[sdk=iphonesimulator*]"
projects.each do |project|
project.build_configurations.each do |config|
config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = excluded_archs_default
projects = self.extract_projects(installer)
projects.each do |project|
project.build_configurations.each do |config|
current_setting = config.build_settings[key] || ""
excluded_archs_includes_I386 = current_setting.include?("i386")
if !excluded_archs_includes_I386
# Hermes does not support `i386` architecture
config.build_settings[key] = "#{current_setting} i386".strip
end
end
project.save()
end
end
end
def self.fix_flipper_for_xcode_15_3(installer)
installer.pods_project.targets.each do |target|
if target.name == 'Flipper'
file_path = 'Pods/Flipper/xplat/Flipper/FlipperTransportTypes.h'
if !File.exist?(file_path)
return
end
contents = File.read(file_path)
if contents.include?('#include <functional>')
return
end
mod_content = contents.gsub("#pragma once", "#pragma once\n#include <functional>")
File.chmod(0755, file_path)
File.open(file_path, 'w') do |file|
file.puts(mod_content)
end
end
project.save()
end
end
@@ -121,16 +153,31 @@ class ReactNativePodsUtils
end
end
def self.apply_xcode_15_patch(installer)
installer.target_installation_results.pod_target_installation_results
.each do |pod_name, target_installation_result|
target_installation_result.native_target.build_configurations.each do |config|
# unary_function and binary_function are no longer provided in C++17 and newer standard modes as part of Xcode 15. They can be re-enabled with setting _LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION
# Ref: https://developer.apple.com/documentation/xcode-release-notes/xcode-15-release-notes#Deprecations
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= '$(inherited) '
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << '"_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION" '
def self.apply_xcode_15_patch(installer, xcodebuild_manager: Xcodebuild)
projects = self.extract_projects(installer)
gcc_preprocessor_definition_key = 'GCC_PREPROCESSOR_DEFINITIONS'
other_ld_flags_key = 'OTHER_LDFLAGS'
libcpp_cxx17_fix = '_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION'
xcode15_compatibility_flags = '-Wl -ld_classic '
projects.each do |project|
project.build_configurations.each do |config|
# fix for unary_function and binary_function
self.safe_init(config, gcc_preprocessor_definition_key)
self.add_value_to_setting_if_missing(config, gcc_preprocessor_definition_key, libcpp_cxx17_fix)
# fix for weak linking
self.safe_init(config, other_ld_flags_key)
if self.is_using_xcode15_0(:xcodebuild_manager => xcodebuild_manager)
self.add_value_to_setting_if_missing(config, other_ld_flags_key, xcode15_compatibility_flags)
else
self.remove_value_from_setting_if_present(config, other_ld_flags_key, xcode15_compatibility_flags)
end
end
project.save()
end
end
def self.apply_flags_for_fabric(installer, fabric_enabled: false)
@@ -232,6 +279,37 @@ class ReactNativePodsUtils
end
end
def self.updateIphoneOSDeploymentTarget(installer)
pod_to_update = Set.new([
"boost",
"CocoaAsyncSocket",
"Flipper",
"Flipper-DoubleConversion",
"Flipper-Fmt",
"Flipper-Boost-iOSX",
"Flipper-Folly",
"Flipper-Glog",
"Flipper-PeerTalk",
"FlipperKit",
"fmt",
"libevent",
"OpenSSL-Universal",
"RCT-Folly",
"SocketRocket",
"YogaKit"
])
installer.target_installation_results.pod_target_installation_results
.each do |pod_name, target_installation_result|
unless pod_to_update.include?(pod_name)
next
end
target_installation_result.native_target.build_configurations.each do |config|
config.build_settings["IPHONEOS_DEPLOYMENT_TARGET"] = Helpers::Constants.min_ios_version_supported
end
end
end
# ========= #
# Utilities #
# ========= #
@@ -243,6 +321,56 @@ class ReactNativePodsUtils
.push(installer.pods_project)
end
def self.safe_init(config, setting_name)
old_config = config.build_settings[setting_name]
if old_config == nil
config.build_settings[setting_name] ||= '$(inherited) '
end
end
def self.add_value_to_setting_if_missing(config, setting_name, value)
old_config = config.build_settings[setting_name]
if old_config.is_a?(Array)
old_config = old_config.join(" ")
end
trimmed_value = value.strip()
if !old_config.include?(trimmed_value)
config.build_settings[setting_name] = "#{old_config.strip()} #{trimmed_value}".strip()
end
end
def self.remove_value_from_setting_if_present(config, setting_name, value)
old_config = config.build_settings[setting_name]
if old_config.is_a?(Array)
old_config = old_config.join(" ")
end
trimmed_value = value.strip()
if old_config.include?(trimmed_value)
new_config = old_config.gsub(trimmed_value, "")
config.build_settings[setting_name] = new_config.strip()
end
end
def self.is_using_xcode15_0(xcodebuild_manager: Xcodebuild)
xcodebuild_version = xcodebuild_manager.version
# The output of xcodebuild -version is something like
# Xcode 15.0
# or
# Xcode 14.3.1
# We want to capture the version digits
regex = /(\d+)\.(\d+)(?:\.(\d+))?/
if match_data = xcodebuild_version.match(regex)
major = match_data[1].to_i
minor = match_data[2].to_i
return major == 15 && minor == 0
end
return false
end
def self.add_compiler_flag_to_project(installer, flag, configuration: nil)
projects = self.extract_projects(installer)
@@ -11,6 +11,7 @@
const yargs = require('yargs');
const fs = require('fs');
const p = require('path');
const CONFIG_FILE_NAME = 'react-native.config.js';
const PROJECT_FIELD = 'project';
@@ -93,7 +94,11 @@ function extractComponentsNames(reactNativeConfig) {
}
function generateRCTLegacyInteropComponents() {
const configFilePath = `${appRoot}/${CONFIG_FILE_NAME}`;
const cwd = process.cwd();
const configFilePath = p.join(cwd, appRoot, CONFIG_FILE_NAME);
console.log(
`Looking for a react-native.config.js file at ${configFilePath}...`,
);
let reactNativeConfig = null;
try {
reactNativeConfig = require(configFilePath);
@@ -107,7 +112,7 @@ function generateRCTLegacyInteropComponents() {
console.log('Skip LegacyInterop generation');
return;
}
console.log(`Components found: ${componentNames}`);
let componentsArray = componentNames.map(name => `\t\t\t@"${name}",`);
// Remove the last comma
if (componentsArray.length > 0) {
@@ -118,6 +123,7 @@ function generateRCTLegacyInteropComponents() {
const filePath = `${outputPath}/${OUTPUT_FILE_NAME}`;
fs.writeFileSync(filePath, fileBody(componentsArray.join('\n')));
console.log(`${filePath} updated!`);
}
generateRCTLegacyInteropComponents();
@@ -15,6 +15,8 @@ require_relative './cocoapods/codegen_utils.rb'
require_relative './cocoapods/utils.rb'
require_relative './cocoapods/new_architecture.rb'
require_relative './cocoapods/local_podspec_patch.rb'
require_relative './cocoapods/helpers.rb'
require_relative './cocoapods/privacy_manifest_utils.rb'
$CODEGEN_OUTPUT_DIR = 'build/generated/ios'
$CODEGEN_COMPONENT_DIR = 'react/renderer/components'
@@ -34,11 +36,12 @@ require Pod::Executable.execute_command('node', ['-p',
{paths: [process.argv[1]]},
)', __dir__]).strip
# This function returns the min iOS version supported by React Native
# This function returns the min supported OS versions supported by React Native
# By using this function, you won't have to manually change your Podfile
# when we change the minimum version supported by the framework.
def min_ios_version_supported
return '12.4'
return Helpers::Constants.min_ios_version_supported
end
# This function prepares the project for React Native, before processing
@@ -72,7 +75,8 @@ def use_react_native! (
flipper_configuration: FlipperConfiguration.disabled,
app_path: '..',
config_file_dir: '',
ios_folder: 'ios'
ios_folder: 'ios',
privacy_file_aggregation_enabled: true
)
# Set the app_path as env variable so the podspecs can access it.
@@ -91,6 +95,7 @@ def use_react_native! (
fabric_enabled = fabric_enabled || new_arch_enabled
ENV['RCT_FABRIC_ENABLED'] = fabric_enabled ? "1" : "0"
ENV['USE_HERMES'] = hermes_enabled ? "1" : "0"
ENV['RCT_AGGREGATE_PRIVACY_FILES'] = privacy_file_aggregation_enabled ? "1" : "0"
prefix = path
@@ -139,7 +144,7 @@ def use_react_native! (
pod 'Yoga', :path => "#{prefix}/ReactCommon/yoga", :modular_headers => true
pod 'DoubleConversion', :podspec => "#{prefix}/third-party-podspecs/DoubleConversion.podspec"
pod 'glog', :podspec => "#{prefix}/third-party-podspecs/glog.podspec", :modular_headers => true
pod 'glog', :podspec => "#{prefix}/third-party-podspecs/glog.podspec"
pod 'boost', :podspec => "#{prefix}/third-party-podspecs/boost.podspec"
pod 'RCT-Folly', :podspec => "#{prefix}/third-party-podspecs/RCT-Folly.podspec", :modular_headers => true
@@ -236,6 +241,8 @@ def react_native_post_install(
if ReactNativePodsUtils.has_pod(installer, 'Flipper')
flipper_post_install(installer)
end
privacy_file_aggregation_enabled = ENV['RCT_AGGREGATE_PRIVACY_FILES'] == '1'
fabric_enabled = ReactNativePodsUtils.has_pod(installer, 'React-Fabric')
@@ -245,11 +252,20 @@ def react_native_post_install(
ReactNativePodsUtils.set_node_modules_user_settings(installer, react_native_path)
ReactNativePodsUtils.apply_flags_for_fabric(installer, fabric_enabled: fabric_enabled)
ReactNativePodsUtils.apply_xcode_15_patch(installer)
ReactNativePodsUtils.updateIphoneOSDeploymentTarget(installer)
ReactNativePodsUtils.fix_flipper_for_xcode_15_3(installer)
if privacy_file_aggregation_enabled
PrivacyManifestUtils.add_aggregated_privacy_manifest(installer)
else
PrivacyManifestUtils.add_privacy_manifest_if_needed(installer)
end
NewArchitectureHelper.set_clang_cxx_language_standard_if_needed(installer)
is_new_arch_enabled = ENV['RCT_NEW_ARCH_ENABLED'] == "1"
NewArchitectureHelper.modify_flags_for_new_architecture(installer, is_new_arch_enabled)
Pod::UI.puts "Pod install took #{Time.now.to_i - $START_TIME} [s] to run".green
end
+1 -1
View File
@@ -1 +1 @@
hermes-2023-03-20-RNv0.72.0-49794cfc7c81fb8f69fd60c3bbf85a7480cc5a77
hermes-2024-04-29-RNv0.72.14-3815fec63d1a6667ca3195160d6e12fee6a0d8d5
@@ -17,7 +17,7 @@ version = package['version']
# sdks/.hermesversion
hermestag_file = File.join(react_native_path, "sdks", ".hermesversion")
build_from_source = ENV['BUILD_FROM_SOURCE'] === 'true'
build_from_source = ENV['RCT_BUILD_HERMES_FROM_SOURCE'] === 'true'
git = "https://github.com/facebook/hermes.git"
@@ -17,7 +17,7 @@ end
# - To use a specific tarball, install the dependencies with:
# `HERMES_ENGINE_TARBALL_PATH=<path_to_tarball> bundle exec pod install`
# - To force a build from source, install the dependencies with:
# `BUILD_FROM_SOURCE=true bundle exec pod install`
# `RCT_BUILD_HERMES_FROM_SOURCE=true bundle exec pod install`
# If none of the two are provided, Cocoapods will check whether there is a tarball for the current version
# (either release or nightly). If not, it will fall back building from source (the latest commit on main).
#
@@ -52,13 +52,9 @@ function build_host_hermesc {
# Utility function to configure an Apple framework
function configure_apple_framework {
local build_cli_tools enable_bitcode enable_debugger cmake_build_type
local build_cli_tools enable_debugger cmake_build_type xcode_15_flags xcode_major_version
if [[ $1 == iphoneos || $1 == catalyst ]]; then
enable_bitcode="true"
else
enable_bitcode="false"
fi
if [[ $1 == macosx ]]; then
build_cli_tools="true"
else
@@ -77,8 +73,15 @@ function configure_apple_framework {
cmake_build_type="MinSizeRel"
fi
xcode_15_flags=""
xcode_major_version=$(xcodebuild -version | grep -oE '[0-9]*' | head -n 1)
if [[ $xcode_major_version -ge 15 ]]; then
xcode_15_flags="LINKER:-ld_classic"
fi
pushd "$HERMES_PATH" > /dev/null || exit 1
cmake -S . -B "build_$1" \
-DHERMES_EXTRA_LINKER_FLAGS="$xcode_15_flags" \
-DHERMES_APPLE_TARGET_PLATFORM:STRING="$1" \
-DCMAKE_OSX_ARCHITECTURES:STRING="$2" \
-DCMAKE_OSX_DEPLOYMENT_TARGET:STRING="$3" \
@@ -87,7 +90,7 @@ function configure_apple_framework {
-DHERMES_ENABLE_LIBFUZZER:BOOLEAN=false \
-DHERMES_ENABLE_FUZZILLI:BOOLEAN=false \
-DHERMES_ENABLE_TEST_SUITE:BOOLEAN=false \
-DHERMES_ENABLE_BITCODE:BOOLEAN="$enable_bitcode" \
-DHERMES_ENABLE_BITCODE:BOOLEAN=false \
-DHERMES_BUILD_APPLE_FRAMEWORK:BOOLEAN=true \
-DHERMES_BUILD_APPLE_DSYM:BOOLEAN=true \
-DHERMES_ENABLE_TOOLS:BOOLEAN="$build_cli_tools" \
@@ -33,6 +33,13 @@ if [ -z "$deployment_target" ]; then
deployment_target=${MACOSX_DEPLOYMENT_TARGET}
fi
xcode_15_flags=""
xcode_major_version=$(xcodebuild -version | grep -oE '[0-9]*' | head -n 1)
if [[ $xcode_major_version -ge 15 ]]; then
echo "########### Using LINKER:-ld_classic ###########"
xcode_15_flags="LINKER:-ld_classic"
fi
architectures=$( echo "$ARCHS" | tr " " ";" )
echo "Configure Apple framework"
@@ -40,6 +47,7 @@ echo "Configure Apple framework"
"$CMAKE_BINARY" \
-S "${PODS_ROOT}/hermes-engine" \
-B "${PODS_ROOT}/hermes-engine/build/${PLATFORM_NAME}" \
-DHERMES_EXTRA_LINKER_FLAGS="$xcode_15_flags" \
-DHERMES_APPLE_TARGET_PLATFORM:STRING="$PLATFORM_NAME" \
-DCMAKE_OSX_ARCHITECTURES:STRING="$architectures" \
-DCMAKE_OSX_DEPLOYMENT_TARGET:STRING="$deployment_target" \
+4 -1
View File
@@ -3,4 +3,7 @@ source 'https://rubygems.org'
# You may use http://rbenv.org/ or https://rvm.io/ to install and use this version
ruby ">= 2.6.10"
gem 'cocoapods', '~> 1.12'
# Cocoapods 1.15 introduced a bug which break the build. We will remove the upper
# bound in the template on Cocoapods with next React Native release.
gem 'cocoapods', '>= 1.13', '< 1.15'
gem 'activesupport', '>= 6.1.7.3', '< 7.1.0'
@@ -12,6 +12,7 @@
13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; };
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
6132EF182BDFF13200BBE14D /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 6132EF172BDFF13200BBE14D /* PrivacyInfo.xcprivacy */; };
7699B88040F8A987B510C191 /* libPods-HelloWorld-HelloWorldTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 19F6CBCC0A4E27FBF8BF4A61 /* libPods-HelloWorld-HelloWorldTests.a */; };
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
/* End PBXBuildFile section */
@@ -41,6 +42,7 @@
5709B34CF0A7D63546082F79 /* Pods-HelloWorld.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HelloWorld.release.xcconfig"; path = "Target Support Files/Pods-HelloWorld/Pods-HelloWorld.release.xcconfig"; sourceTree = "<group>"; };
5B7EB9410499542E8C5724F5 /* Pods-HelloWorld-HelloWorldTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HelloWorld-HelloWorldTests.debug.xcconfig"; path = "Target Support Files/Pods-HelloWorld-HelloWorldTests/Pods-HelloWorld-HelloWorldTests.debug.xcconfig"; sourceTree = "<group>"; };
5DCACB8F33CDC322A6C60F78 /* libPods-HelloWorld.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-HelloWorld.a"; sourceTree = BUILT_PRODUCTS_DIR; };
6132EF172BDFF13200BBE14D /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = PrivacyInfo.xcprivacy; path = HelloWorld/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = HelloWorld/LaunchScreen.storyboard; sourceTree = "<group>"; };
89C6BE57DB24E9ADA2F236DE /* Pods-HelloWorld-HelloWorldTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HelloWorld-HelloWorldTests.release.xcconfig"; path = "Target Support Files/Pods-HelloWorld-HelloWorldTests/Pods-HelloWorld-HelloWorldTests.release.xcconfig"; sourceTree = "<group>"; };
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
@@ -116,6 +118,7 @@
83CBB9F61A601CBA00E9B192 = {
isa = PBXGroup;
children = (
6132EF172BDFF13200BBE14D /* PrivacyInfo.xcprivacy */,
13B07FAE1A68108700A75B9A /* HelloWorld */,
832341AE1AAA6A7D00B99B32 /* Libraries */,
00E356EF1AD99517003FC87E /* HelloWorldTests */,
@@ -242,6 +245,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
6132EF182BDFF13200BBE14D /* PrivacyInfo.xcprivacy in Resources */,
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */,
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
);
@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPrivacyCollectedDataTypes</key>
<array>
</array>
<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>C617.1</string>
</array>
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>CA92.1</string>
</array>
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>35F9.1</string>
</array>
</dict>
</array>
<key>NSPrivacyTracking</key>
<false/>
</dict>
</plist>
+3 -3
View File
@@ -11,21 +11,21 @@
},
"dependencies": {
"react": "18.2.0",
"react-native": "0.72.2"
"react-native": "0.72.17"
},
"devDependencies": {
"@babel/core": "^7.20.0",
"@babel/preset-env": "^7.20.0",
"@babel/runtime": "^7.20.0",
"@react-native/eslint-config": "^0.72.2",
"@react-native/metro-config": "^0.72.9",
"@react-native/metro-config": "^0.72.12",
"@tsconfig/react-native": "^3.0.0",
"@types/react": "^18.0.24",
"@types/react-test-renderer": "^18.0.0",
"babel-jest": "^29.2.1",
"eslint": "^8.19.0",
"jest": "^29.2.1",
"metro-react-native-babel-preset": "0.76.7",
"metro-react-native-babel-preset": "^0.76.9",
"prettier": "^2.4.1",
"react-test-renderer": "18.2.0",
"typescript": "4.8.4"
@@ -10,7 +10,7 @@ Pod::Spec.new do |spec|
spec.homepage = 'http://www.boost.org'
spec.summary = 'Boost provides free peer-reviewed portable C++ source libraries.'
spec.authors = 'Rene Rivera'
spec.source = { :http => 'https://boostorg.jfrog.io/artifactory/main/release/1.76.0/source/boost_1_76_0.tar.bz2',
spec.source = { :http => 'https://archives.boost.io/release/1.76.0/source/boost_1_76_0.tar.bz2',
:sha256 => 'f0397ba6e982c4450f27bf32a2a83292aba035b827a5623a14636ea583318c41' }
# Pinning to the same version as React.podspec.
+4 -1
View File
@@ -1,5 +1,8 @@
# Gemfile
source 'https://rubygems.org'
gem 'cocoapods', '~> 1.12'
# Cocoapods 1.15 introduced a bug which break the build. We will remove the upper
# bound in the template on Cocoapods with next React Native release.
gem 'cocoapods', '>= 1.13', '< 1.15'
gem 'rexml'
gem 'activesupport', '>= 6.1.7.3', '< 7.1.0'

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