Compare commits

...
Author SHA1 Message Date
React Native Bot 06c4c425d7 Release 0.82.0
#publish-packages-to-npm&latest
2025-10-07 22:17:26 +00:00
React Native Bot 8677203b7a [LOCAL] Bump Podfile.lock 2025-09-30 13:20:51 +00:00
React Native Bot 3336199242 Release 0.82.0-rc.5
#publish-packages-to-npm&next
2025-09-30 11:07:35 +00:00
Tim YungandVitali Zaidman fddf263dbc RN: Deprecate InteractionManager (#53832)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53832

Deprecates `InteractionManager` by adding a warning when it is imported.

Changelog:
[General][Changed] - InteractionManager has been deprecated and no longer respects interaction handles. Instead, it is now recommended to avoid executing long-running JavaScript tasks by breaking them up into smaller tasks and scheduling them using `requestIdleCallback()`.

Reviewed By: javache

Differential Revision: D82704809

fbshipit-source-id: 99474cd7949abfe323c366b9ab8d8fc195578395
2025-09-29 14:58:02 +01:00
Tim YungandVitali Zaidman 458cd06bdb RN: Remove References to InteractionManager (#53830)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53830

Now that `InteractionManager` is deprecated (and no-ops), this removes all remaining references to it — in `Animated` and `PanResponder` — from the React Native repository.

Changelog:
[Internal]

Reviewed By: javache

Differential Revision: D82690242

fbshipit-source-id: d101d47d1f8640f70e2d199492d4345b63663251
2025-09-29 14:55:13 +01:00
Riccardo CipolleschiandVitali Zaidman e5fca6c363 Crash the app when Legacy Arch is enabled (#53911)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53911

This change mimics what we implemented on Android to crash the app.

This is in general never going t be triggered. It will be triggered only if users are actually going through the old way to initialize React Native, i.e. by using the RCTRootView class which creates thebridge, or if they are creating the bridge themselves.

## Changelog:
[iOS][Added] - Crash the app if they force the legacy architecture.

Reviewed By: RSNara, cortinico

Differential Revision: D83066377

fbshipit-source-id: 0907effceb9a3655ec8d6bde8e0986f50f1ab663
2025-09-29 14:54:43 +01:00
Kacper KafaraandVitali Zaidman b1994dd547 Add invalidation callback for non-recycled component instances on iOS (#53708)
Summary:
Since the view recycling is optional on iOS [since 0.74](https://github.com/facebook/react-native/commit/613a5a75977d84333df7cbd5701e01a7ab5a3385) when a view (with disabled view recycling) is unmounted / destroyed there is no lifecycle callback for a component view to notify it of such event. Currently we (`react-native-screens`) are forced to scan mutation list of every mounting transaction in every of ours container components. Components with view recycling turned on, get `prepareForRecycle` callback on Fabric & on old architecture, there was `invalidate` message sent (`RCTInvalidating` protocol). It would be nice & useful to have something like this for components with view recycling disabled, or enabled but not recycled due to pool being full.

In particular in `react-native-screens` we need an information that the component is being destroyed to release retained resources (view controllers & others).

I have concern regarding naming of this method, as it could collide / be mistaken with `invalidate` method of `RCTInvalidating` protocol, but naming is hard & I don't see a name that fits better 😄 Open for suggestions!

## Changelog:

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

Pick one each for the category and type tags:

[ANDROID|GENERAL|IOS|INTERNAL] [BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY] - Message

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

[IOS] [ADDED] - Add invalidation callback for non-recycled component instances

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

Test Plan:
Apply this patch to `RNTMyNativeViewComponentView.mm`:

```objective-c

 diff --git a/packages/rn-tester/NativeComponentExample/ios/RNTMyNativeViewComponentView.mm b/packages/rn-tester/NativeComponentExample/ios/RNTMyNativeViewComponentView.mm
index 2eb7bff28e..8464da603b 100644
 --- a/packages/rn-tester/NativeComponentExample/ios/RNTMyNativeViewComponentView.mm
+++ b/packages/rn-tester/NativeComponentExample/ios/RNTMyNativeViewComponentView.mm
@@ -123,6 +123,16 @@ using namespace facebook::react;
   [_view removeOverlays];
 }

+- (void)invalidate
+{
+  NSLog(@"RCTComponentViewProtocol invalidate called");
+}
+
++ (BOOL)shouldBeRecycled
+{
+  return NO;
+}
+
 - (void)fireLagacyStyleEvent
 {
   RNTMyNativeViewEventEmitter::OnLegacyStyleEvent value = {"Legacy Style Event Fired."};

```

& render `MyNativeView` in any of the RNTester screens / examples. Unmount the view & observe the log in XCode.

https://github.com/user-attachments/assets/be3f67bb-73e0-4af2-9ca1-f2eb9f3347bb

(called twice, because there are two components rendered at a time)

Reviewed By: javache

Differential Revision: D83139361

Pulled By: cipolleschi

fbshipit-source-id: 17ef964648ac44b583503b6b00fc5dd457887061
2025-09-29 14:54:21 +01:00
Jakub PiaseckiandGitHub 6efaeaf953 [0.82] Update Hermes V1 version (#53932)
* Update hermes V1 version

* Pin Hermes V1 source version to a specific commit
2025-09-29 14:52:37 +01:00
React Native Bot 0dd3730d23 [LOCAL] Bump Podfile.lock 2025-09-22 17:44:42 +00:00
React Native Bot a70e817da5 Release 0.82.0-rc.4
#publish-packages-to-npm&next
2025-09-22 15:19:10 +00:00
Riccardo CipolleschiandVitali Zaidman 9f43d07679 Fix Switch layout with iOS26 (#53326)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53326

Apple changed the sizes of the UISwitchComponent and now, if you build an iOs app using the <Switch> component, the layout of the app will be broken because of wrong layout measurements.
This has been reported also by [https://github.com/facebook/react-native/issues/52823](https://github.com/facebook/react-native/issues/52823).

The `<Switch>` component was using hardcoded values for its size.
This change fixes the problem by:
- Using codegen for interface only
- Implementing a custom Sadow Node to ask the platform for the Switch measurements
- Updating the JS layout to wrap the size around the native component.

## Changelog:

[iOS][Fixed] - Fix Switch layout to work with iOS26

Reviewed By: sammy-SC

Differential Revision: D80454350

fbshipit-source-id: 1d468910276f7fde4559d2ae87cf60c8494caceb
2025-09-22 14:34:29 +01:00
Jakub PiaseckiandVitali Zaidman 8d775928f5 Update coordinates for remote artifacts of Hermes V1 (#53822)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53822

Changelog: [GENERAL][FIXED] - Fixed coordinates for Hermes V1 artifacts

Reviewed By: cortinico

Differential Revision: D82639319

fbshipit-source-id: becfab3248f2314af97549eb94feb27b19f5d1af
2025-09-22 14:34:01 +01:00
8dddde49b2 [0.82] Ensure legacy architecture can't be initialized (#53843)
* Ensure legacy architecture can't be initialized in Android (#53806)

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

The Legacy architecture of React Native is not supported anymore, let's ensure nobody can initialize it anymore

changelog: [internal] internal

Reviewed By: cortinico

Differential Revision: D82465004

fbshipit-source-id: 099764fb59d906b11cf6ad0cc6208f56df029d19

* Runtime check that NewArchitecture is enabled in DefaultNewArchitectureEntryPoint (#53780)

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

This is a commit we're going to pick in 0.82 as we want to make sure users cannot invoke `load()`
from `DefaultNewArchitectureEntryPoint` with flags that are not true,true,true.

Changelog:
[Android] [Changed] - Runtime check that NewArchitecture is enabled in DefaultNewArchitectureEntryPoint

Reviewed By: mdvacca

Differential Revision: D82456975

fbshipit-source-id: 749996a3491913cfe400173608218077c3ffbc10

* Fix DefaultNewArchitectureEntryPoint config validation (#53807)

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

We need to read the values off feature flags before checking them.

## Changelog
[Internal]

Reviewed By: javache

Differential Revision: D82572898

fbshipit-source-id: 09fbc09570c78b41d9c25fb03c5557e390da7cae

* Fix incorrect validation of feature flags in DefaultNewArchitectureEntryPoint.loadWithFeatureFlags() method (#53863)

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

In this diff I'm fixing an incorrect validation of feature flags in DefaultNewArchitectureEntryPoint.loadWithFeatureFlags() method.

changelog: [internal] internal

Reviewed By: cortinico

Differential Revision: D82841006

fbshipit-source-id: 6f50f2475255d7b841d9224bc8808119dcc68aec

---------

Co-authored-by: David Vacca <dvacca@meta.com>
Co-authored-by: Eric Rozell <ericroz@meta.com>
2025-09-22 14:24:33 +01:00
React Native Bot 3a0a7365ff [LOCAL] Bump Podfile.lock 2025-09-17 09:41:27 +00:00
React Native Bot 45439b0119 Release 0.82.0-rc.3
#publish-packages-to-npm&next
2025-09-17 07:27:43 +00:00
React Native Bot 16bc2e4569 Release 0.82.0-rc.2
#publish-packages-to-npm&next
2025-09-16 13:12:26 +00:00
Vitali Zaidman 47c04b9930 [LOCAL] remove faulty cherry pick networking lines from Android's CMakeList.txt 2025-09-16 11:43:26 +01:00
Rubén NorteandVitali Zaidman 1a0f7b26bc Ship Web Performance APIs in canary (#53712)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53712

Changelog: [internal]

This enables the new Web Performance APIs in the canary channel.

Reviewed By: cortinico

Differential Revision: D82117694

fbshipit-source-id: 370b8397eeec350be8434728ab9d8ce1f5926117
2025-09-16 11:25:30 +01:00
Rubén NorteandVitali Zaidman bf9c6514fc Remove redudant fields from ReactNativeStartupTiming (#53711)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53711

Changelog: [internal]

This removes some fields that contain the same time as `endTime`, which is confusing when documenting them.

Reviewed By: christophpurrer

Differential Revision: D82112473

fbshipit-source-id: 461e2b4b495ae641dcb3233874360a4f7b90dabf
2025-09-16 11:25:14 +01:00
Rubén NorteandVitali Zaidman 5f1a22ac8d Make eventCounts a getter (#53710)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53710

Changelog: [internal]

This should be a getter according to the spec.

Reviewed By: hoxyq

Differential Revision: D82111779

fbshipit-source-id: 614bb4848907bacd80ef228aa747ae685cf2c1f7
2025-09-16 11:25:01 +01:00
Rubén NorteandVitali Zaidman e8129c37d9 Implement performance.timeOrigin (#53660)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53660

Changelog: [internal]

(This is internal because these APIs aren't enabled in OSS yet)

Implements `performance.timeOrigin` to allow converting timestamps from `performance.now()` to be based on the Unix epoch.

This implementation isn't fully spec-compliant to align with the current implementation of `performance.now()`, where the base of the clock is system boot time instead of app startup / navigation time.

Reviewed By: huntie

Differential Revision: D82016724

fbshipit-source-id: e3a066721cecf41e2fd963beb94a0a2f1c5d6493
2025-09-16 11:24:50 +01:00
Rubén NorteandVitali Zaidman e6d1ab8c66 Add feature flag to enable Web Performance APIs by default (#53547)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53547

Changelog: [internal]

This creates a new feature flag to enable the modern Web performance APIs in RN by default. It's disabled by default so it shouldn't have any effect at the moment.

Reviewed By: rshest

Differential Revision: D80811430

fbshipit-source-id: 47d5fd12ac8809aa3c5ad37cdd31c0d9e3ed5912
2025-09-16 11:23:31 +01:00
Nicola CortiandVitali Zaidman e87a8820a5 Unblock run_fantom_tests by pinning react-native-android to v18.0 (#53732)
Summary:
This temporarly unblocks `run_fantom_tests` till we find a solution for the docker image bump. See:
- https://github.com/react-native-community/docker-android/pull/242#issuecomment-3280029122

## Changelog:

[INTERNAL] -

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

Test Plan: CI

Reviewed By: cipolleschi

Differential Revision: D82212022

Pulled By: cortinico

fbshipit-source-id: 652926addf12cc2d88ac2139d3ec58a266ced9ef
2025-09-16 11:04:18 +01:00
Vitali Zaidman 736f608364 re-generated feature flag generated files 2025-09-16 10:30:20 +01:00
Jakub PiaseckiandVitali Zaidman 4c8b6a6915 Add dependency on hermes-compiler (#53773)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53773

Changelog: [GENERAL][ADDED] - Added a dependency on hermes-compiler

Reviewed By: cortinico

Differential Revision: D82437752

fbshipit-source-id: 3b2d92b765f3a5ba949363ce7656e936403a1155
2025-09-15 14:40:21 +01:00
Rubén NorteandVitali Zaidman 06ab1f446c Ship Web Performance APIs in canary (#53712)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53712

Changelog: [internal]

This enables the new Web Performance APIs in the canary channel.

Reviewed By: cortinico

Differential Revision: D82117694

fbshipit-source-id: 370b8397eeec350be8434728ab9d8ce1f5926117
2025-09-15 14:35:12 +01:00
Phil PluckthunandVitali Zaidman 7754c05db4 Remove outdated artifacts codegen early return (#53690)
Summary:
Follow-up to https://github.com/facebook/react-native/issues/53503 for a regression

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

## Changelog:

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

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

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

Reviewed By: javache

Differential Revision: D82103491

Pulled By: cipolleschi

fbshipit-source-id: 3d9619b5a935ca920220824b3963a9a107f926ca
2025-09-15 14:32:49 +01:00
Jakub PiaseckiandGitHub 4c53204422 [0.82] Cherry-pick follow-ups to Hermes V1 opt-in (#53705)
* Check value of the Hermes V1 flag instead of whether it's defined (#53637)

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

Changelog: [ANDROID][FIXED] - Check for the value of the HERMES_V1_ENABLED flag instead of whether it's defined

Reviewed By: cortinico

Differential Revision: D81920483

fbshipit-source-id: 550ae9fd27f666affe102b1c5c3f51bde7b5923e

* Read Hermes V1 opt-in flag from the app's properties (#53665)

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

Changelog: [ANDROID][FIXED] - Read the Hermes V1 opt-in flag from the apps properties when building from source

Reviewed By: cortinico

Differential Revision: D82018545

fbshipit-source-id: f3c6fdbac190f47b6bf6836105d9e0909d8b86ba

* Use artifacts published from Hermes repository when using Hermes V1 (#53725)

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

Changelog: [GENERAL][CHANGED] - Changed the coordinates of hermes artifacts when using Hermes V1

Adds a new `version.properties` file to keep which hermes versions should be consumed from Maven once the versions of Hermes and React Native are decoupled. This diff only implements changes necessary for consuming Hermes V1, as we don't want to migrate everything quite yet (0.82).

Reviewed By: cortinico

Differential Revision: D82204203

fbshipit-source-id: d712257a73f7ba54612a55c1b312416376f28b56
2025-09-15 14:31:05 +01:00
Nicola Corti 71c853ca6d [LOCAL] Use REACT_NATIVE_BOT_GITHUB_TOKEN token for changelog and bump lockfiles 2025-09-09 15:30:28 +01:00
Vitali Zaidman 788e2b9d62 Update Podfile.lock
Changelog: [Internal]
2025-09-09 14:10:55 +01:00
React Native Bot 3c2cc3852d Release 0.82.0-rc.1
#publish-packages-to-npm&next
2025-09-09 10:02:01 +00:00
Nicola Corti f68b918c89 [LOCAL] Remove unnecesary quote in hermesVersionProvider 2025-09-08 15:51:35 +01:00
Nicola Corti ee08261123 [LOCAL] Temporarily disable prebuilds for 0.82 branch 2025-09-08 15:40:05 +01:00
Rubén NorteandVitali Zaidman ac2fe26cf2 Define Flow types for Performance APIs (#53433)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53433

Changelog: [internal]

This adds the definitions for the Web Performance APIs in the global scope.

Reviewed By: zeyap

Differential Revision: D80811659

fbshipit-source-id: a81117a27a480ba03f8feb2e813a3a66a10307f9
2025-09-08 14:56:46 +01:00
Rubén NorteandVitali Zaidman cdfe1ecd52 Set up modern performance APIs if the native module is available (#53431)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53431

Changelog: [internal]

This renames `setUpPerformanceObserver` as `setUpPerformanceModern` and removes the need to call it manually. If the native module is defined, we define the whole new API.

Reviewed By: javache

Differential Revision: D80803626

fbshipit-source-id: ef41cb9aa959ee898d32724c102d7597e6bee84e
2025-09-08 14:44:39 +01:00
Rubén NorteandVitali Zaidman a65325b586 Implement private constructors for Performance APIs (#53430)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53430

Changelog: [internal]

This fixes the spec-compliance of several classes in the Performance API by not allowing userland code to instantiate them directly.

This also exposes some missing interfaces from the Performance API in the global scope.

Reviewed By: rshest

Differential Revision: D80800076

fbshipit-source-id: f6439b9c7914817ef552e78fd61646ccab1e1de2
2025-09-08 14:44:27 +01:00
Rubén NorteandVitali Zaidman ccb34a1063 Refactor PerformanceEntry and subclasses to use interfaces for initialization (#53429)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53429

Changelog: [internal]

This is a refactor of the types in `PerformanceEntry` and subclasses to accept interfaces instead of objects. This allows us to pass down the init object from subclasses to the superclass without having to create intermediate objects.

Additionally, this is also more semantically correct, as existing APIs don't need those options to be own properties of the init object.

Existing benchmark for Performance doesn't show any significant impact.

Reviewed By: rshest

Differential Revision: D80800075

fbshipit-source-id: ab439d70f4db9ce60e3089d89ccb105a91e7ef48
2025-09-08 14:44:14 +01:00
Rubén NorteandVitali Zaidman 68e774bb2c Implement PerformanceObserver.takeRecords() (#53428)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53428

Changelog: [internal]

This is the last method in `PerformanceObserver` to implement. For some reason we never added it, even though it was trivial.

Reviewed By: rshest

Differential Revision: D80717237

fbshipit-source-id: ae3bd243d0f3f0fe4f0705437d78d14c532515f7
2025-09-08 14:43:50 +01:00
Rubén NorteandVitali Zaidman 1cacdf70a1 Remove unnecessary references to internal types in performance tests (#53427)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53427

Changelog: [internal]

Migrate the imported types to the globally defined ones, so we follow the good practice of only accessing the public API in Fantom tests.

Reviewed By: rshest

Differential Revision: D80807160

fbshipit-source-id: 77d792b56b53c8da8409dd9133cd111afb8084f1
2025-09-08 14:41:23 +01:00
Ramanpreet NaraandVitali Zaidman 72d4a1cbd4 Deprecate legacy javascript apis (#53630)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53630

These JavaScript apis were a part of react native's legacy architecture. Let's deprecate them, so that we can eventually remove them in the future.

Changelog: [General][Deprecated] - Deprecate legacy javascript react native apis

Reviewed By: cortinico

Differential Revision: D81795732

fbshipit-source-id: 0a2bd142fa7e08c1f3daaa437ee127a2156e045b
2025-09-08 14:39:28 +01:00
Oskar KwaśniewskiandVitali Zaidman 0cfd7230c6 fix: fallback alert controller to UIScreen size (#53500)
Summary:
This PR falls back to UIScreen when windowScene is not available.

<img width="500" alt="CleanShot 2025-08-28 at 14 30 59@2x" src="https://github.com/user-attachments/assets/9dda3153-dfe7-48a5-9d0e-5416c2e34c64" />

## Changelog:

[IOS] [FIXED] - Simplify RCTAlertController, don't create additional UIWindow

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

Test Plan:
Open the alert multiple times to check if everything works as expected.

Rollback Plan:

Reviewed By: javache

Differential Revision: D81410450

Pulled By: cipolleschi

fbshipit-source-id: c27ea98d9e811c2f259f0ff3c6689482d116c418
2025-09-08 14:39:03 +01:00
Jakub PiaseckiandVitali Zaidman 4fdefa7193 Use hermesc from node_modules when consuming prebuilt hermes (#53581)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53581

Changelog: [General][Changed] - Changed the source of hermesc binary to be an npm package

Reviewed By: cipolleschi, cortinico

Differential Revision: D81224001

fbshipit-source-id: 552d0e66fb891974d7b688bfc0bec95e19345d86
2025-09-08 14:38:24 +01:00
Jakub PiaseckiandVitali Zaidman af734f0ccd Allow to opt-in to use the new Hermes on Android (#53580)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53580

Changelog: [ANDROID][ADDED] Added opt-in to use the new Hermes

Reviewed By: cortinico

Differential Revision: D81035114

fbshipit-source-id: d01e44190941d161cf641ec4e03ed487aff18dd8
2025-09-08 14:38:09 +01:00
Jakub PiaseckiandVitali Zaidman af090eaa69 Allow to opt-in to use the new Hermes on iOS (#53579)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53579

Changelog: [IOS][ADDED] Added opt-in to use the new Hermes

Reviewed By: cipolleschi

Differential Revision: D81035113

fbshipit-source-id: b12ca68824ec4e736edd4393a93c28803312eb32
2025-09-08 14:34:56 +01:00
Jakub PiaseckiandVitali Zaidman dc585b0f05 Gate legacy debugger behind a preprocessor directive (#53578)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53578

Changelog: [Internal]

Adds a new preprocessor directive which should be set when the new Hermes is being used. This directive will disable the legacy debugger which isn't supported by it.

Reviewed By: cipolleschi, cortinico

Differential Revision: D81035112

fbshipit-source-id: b30ae348b3419ec2d064dfe7f91c9d664a66f5cf
2025-09-08 14:34:46 +01:00
Phil PluckthunandVitali Zaidman 26cc647db3 Replace execSync with spawnSync for tarball extraction paths that need to be escaped (#53540)
Summary:
Follow-up to https://github.com/facebook/react-native/issues/53194

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

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

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

## Changelog:

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

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

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

Reviewed By: cipolleschi, cortinico

Differential Revision: D81406841

Pulled By: robhogan

fbshipit-source-id: 08bb06b2cd2b15dc17c2f95fab9024129deca6f3
2025-09-08 14:33:39 +01:00
Riccardo CipolleschiandVitali Zaidman f194ee5626 Fix build with Cocopaods and Dynamic frameworks (#53367)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53367

We are missing a dependency in the React-jsinspector podspec that prevents React Native from building with dynamic frameworks.

## Changelog:
[Internal] -

Reviewed By: cortinico

Differential Revision: D80619664

fbshipit-source-id: 1c87ef4d3614ceea3a23196831479ecae0a5acc8
2025-09-08 14:33:19 +01:00
Phil PluckthunandVitali Zaidman b6c338780c Use autolinking react-native-config output in iOS artifacts generator (#53503)
Summary:
Resolves https://github.com/facebook/react-native/issues/53501

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

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

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

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

## Changelog:

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

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

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

Reviewed By: cortinico

Differential Revision: D81490755

Pulled By: cipolleschi

fbshipit-source-id: eefe786a116404f4ed24bd7125dfb108a811f71e
2025-09-08 14:32:59 +01:00
Nicola CortiandVitali Zaidman f49ae8a388 Fix build from source for 0.82 due to Gradle 9.0 (#53560)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53560

Since Gradle 9.0, all the projects in the path must have an existing folder.
As we build :packages:react-native:ReactAndroid, we need to declare the folders
for :packages and :packages:react-native as well as otherwise the build from
source will fail with a missing folder exception.

Changelog:
[Android] [Fixed] - Fix build from source due to missing folder error on Gradle 9.0

Reviewed By: fabriziocucci

Differential Revision: D81482789

fbshipit-source-id: 609b503755486e10060a0f321bd0a38bd71864a1
2025-09-08 14:32:28 +01:00
Moti ZilbermanandGitHub fdc4da96e4 Distribute React Native DevTools binaries via GitHub Releases (#52930) (#53604)
Summary:
bypass-github-export-checks

OSS release infrastructure for the (experimental) React Native DevTools standalone shell.

Currently, binaries are built continuously on Meta infra and served from the Meta CDN using fbcdn.net URLs checked into a DotSlash file in the repo, e.g.:

https://github.com/facebook/react-native/blob/15373218ec572c0e43325845b80a849ad5174cc3/packages/debugger-shell/bin/react-native-devtools#L9-L18

For open source releases we want to primarily distribute the binaries as GitHub release assets, while keeping the Meta CDN URLs as a secondary option. This PR makes the necessary changes to the release workflows to support this:

* `workflows/create-release.yml` (modified): As part of the release commit, rewrite the DotSlash file to include the release asset URLs.
  * **NOTE:** After this commit, **the new URLs don't work yet**, because they refer to a release that hasn't been published. Despite this, the DotSlash file remains valid and usable (because DotSlash will happily fall back to the Meta CDN URLs, which are still in the file).
* `workflows/create-draft-release.yml` (modified): After creating a draft release, fetch the binaries from the Meta CDN and reupload them to GitHub as release assets. This is based on the contents of the DotSlash file rewritten by `create-release.yml`.
* `workflows/validate-dotslash-artifacts.yml` (new): After the release is published, all URLs referenced by the DotSlash (both Meta CDN URL and GH release asset URLs) should be valid and refer to the same artifacts. This workflow checks that this is the case.
  * If this workflow fails on a published release, the release may need to be burned or a hotfix release may be necessary - as the release will stop working correctly once the Meta CDN stops serving the assets.
  * This workflow will also be running continuously on `main`. If it fails on a commit in `main`, there might be a connectivity issue between the GHA runner and the Meta CDN, or there might be an issue on the Meta side.

NOTE: These changes to the release pipeline are generic and reusable; if we later add another DotSlash-based tool whose binaries need to be mirrored as GitHub release assets, we just need to add it to the `FIRST_PARTY_DOTSLASH_FILES` array.

[Internal] Mirror React Native DevTools binaries in GitHub Releases

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

Test Plan:

I've added unit tests for `dotslash-utils`, `curl-utils`, and for the majority of the logic that makes up the new release scripts (`write-dotslash-release-assets-urls`, `upload-release-assets-for-dotslash`, `validate-dotslash-artifacts`).

Created a test branch and draft PR: https://github.com/facebook/react-native/pull/53147.

Locally created a release commit, simulating the create-release GH workflow:

```
node scripts/releases/create-release-commit.js --reactNativeVersion 0.82.0-20250903-0830 --no-dry-run
```

This updated the DotSlash file in the branch: https://github.com/facebook/react-native/pull/53147/commits/2deeb7e70376ee80b99f27bea4825789f22a89a3#diff-205a9ff6005e30be061eaa64b9cb50b15b0e909dd188e0866189e952655a3483

NOTE: I've also ensured that the `create-release-commit` script correctly updates the DotSlash file when running from a branch that already has a release commit - see screenshot:
<img width="1483" height="587" alt="image" src="https://github.com/user-attachments/assets/1ffd859b-e02b-483d-8067-9cc9116829a4" />

Enabled testing the create-draft-release GH workflow in the test branch using these temporary hacks:

* https://github.com/facebook/react-native/pull/53147/commits/81f334eac5147d4dbf5f6d7d627ddfa52cd197be
* https://github.com/facebook/react-native/pull/53147/commits/6d8851657629de7e0b710ed8f5dd7d0f7b9847cc
* https://github.com/facebook/react-native/pull/53147/commits/1428a8da8b9fb29c45fc33d79f311dd1fe273433

Workflow run: https://github.com/facebook/react-native/actions/runs/17426711373/job/49475327346
Draft release: https://github.com/facebook/react-native/releases/tag/untagged-c6a62a58e5baa37936e1
Draft release screenshot for posterity (since we'll likely delete the draft release after landing this):

<img width="1024" height="814" alt="image" src="https://github.com/user-attachments/assets/1900da15-48f6-4274-b29c-0ac2019d92c0" />

For obvious reasons, I've avoided actually publishing the above draft release. But I have run the `validate-dotslash-artifacts` workflow on the *current* branch to ensure that the logic is correct: https://github.com/motiz88/react-native/actions/runs/17426885205/job/49475888486

Running `node scripts/releases/validate-dotslash-artifacts.js` in the release branch (without publishing the release first) fails, as expected:

<img width="1105" height="748" alt="image" src="https://github.com/user-attachments/assets/ed23a2e2-7a31-42eb-a324-f1d50eafe2fb" />

This PR is all the infra needed ahead of the 0.82 ~~branch cut~~ infra freeze to support the React Native DevTools standalone shell, at least on the GitHub side. ~~Some minor infra work remains on the Meta side, plus some product/logic changes to the React Native DevTools standalone shell that I'm intending to finish in time for 0.82 (for an experimental rollout).~~ EDIT: All the planned work has landed; the feature is code-complete on `main` as well as in `0.82-stable` (apart from this infra change).

As a one-off, once we've actually published 0.82.0-rc.1, we'll want to have a human look at the published artifacts and CI workflow logs to ensure everything is in order. (I'll make sure to communicate this to the 0.82 release crew.) Afterwards, the automation added in this PR should be sufficient.

Reviewed By: huntie

Differential Revision: D81578704

Pulled By: motiz88

fbshipit-source-id: 6a4a48c3713221a89dd5fc88851674c1ddc6bb10
2025-09-08 14:19:54 +01:00
Vitali Zaidman e5647a18a8 Update Podfile.lock
Changelog: [Internal]
2025-09-02 13:08:14 +01:00
React Native Bot 044d07c670 Release 0.82.0-rc.0
#publish-packages-to-npm&next
2025-09-02 10:05:17 +00:00
Vitali Zaidman 1b359eefba fixed artifacts not found in release-testing script 2025-09-01 18:28:54 +01:00
Vitali Zaidman 92b33c986c Bump hermes version 2025-09-01 16:43:10 +01:00
187 changed files with 5677 additions and 924 deletions
@@ -188,6 +188,7 @@ View the whole changelog in the [CHANGELOG.md file](https://github.com/facebook/
status: 201,
json: () =>
Promise.resolve({
id: 1,
html_url:
'https://github.com/facebook/react-native/releases/tag/v0.77.1',
}),
@@ -208,9 +209,11 @@ View the whole changelog in the [CHANGELOG.md file](https://github.com/facebook/
body: fetchBody,
},
);
expect(response).toEqual(
'https://github.com/facebook/react-native/releases/tag/v0.77.1',
);
expect(response).toEqual({
id: 1,
html_url:
'https://github.com/facebook/react-native/releases/tag/v0.77.1',
});
});
it('creates a draft release for prerelease on GitHub', async () => {
@@ -238,6 +241,7 @@ View the whole changelog in the [CHANGELOG.md file](https://github.com/facebook/
status: 201,
json: () =>
Promise.resolve({
id: 1,
html_url:
'https://github.com/facebook/react-native/releases/tag/v0.77.1',
}),
@@ -258,9 +262,11 @@ View the whole changelog in the [CHANGELOG.md file](https://github.com/facebook/
body: fetchBody,
},
);
expect(response).toEqual(
'https://github.com/facebook/react-native/releases/tag/v0.77.1',
);
expect(response).toEqual({
id: 1,
html_url:
'https://github.com/facebook/react-native/releases/tag/v0.77.1',
});
});
it('throws if the post failes', async () => {
@@ -101,7 +101,11 @@ async function _createDraftReleaseOnGitHub(version, body, latest, token) {
}
const data = await response.json();
return data.html_url;
const {html_url, id} = data;
return {
html_url,
id,
};
}
function moveToChangelogBranch(version) {
@@ -124,7 +128,8 @@ async function createDraftRelease(version, latest, token) {
latest,
token,
);
log(`Created draft release: ${release}`);
log(`Created draft release: ${release.html_url}, ID ${release.id}`);
return release;
}
module.exports = {
+1
View File
@@ -10,6 +10,7 @@ jobs:
- name: Checkout
uses: actions/checkout@v4
with:
token: ${{ secrets.REACT_NATIVE_BOT_GITHUB_TOKEN }}
fetch-depth: 0
fetch-tags: true
- name: Install dependencies
+16 -1
View File
@@ -21,9 +21,24 @@ jobs:
git config --local user.name "React Native Bot"
- name: Create draft release
uses: actions/github-script@v6
id: create-draft-release
with:
script: |
const {createDraftRelease} = require('./.github/workflow-scripts/createDraftRelease.js');
const version = '${{ github.ref_name }}';
const {isLatest} = require('./.github/workflow-scripts/publishTemplate.js');
await createDraftRelease(version, isLatest(), '${{secrets.REACT_NATIVE_BOT_GITHUB_TOKEN}}');
return (await createDraftRelease(version, isLatest(), '${{secrets.REACT_NATIVE_BOT_GITHUB_TOKEN}}')).id;
result-encoding: string
- name: Upload release assets for DotSlash
uses: actions/github-script@v6
env:
RELEASE_ID: ${{ steps.create-draft-release.outputs.result }}
with:
script: |
const {uploadReleaseAssetsForDotSlashFiles} = require('./scripts/releases/upload-release-assets-for-dotslash.js');
const version = '${{ github.ref_name }}';
await uploadReleaseAssetsForDotSlashFiles({
version,
token: '${{secrets.REACT_NATIVE_BOT_GITHUB_TOKEN}}',
releaseId: process.env.RELEASE_ID,
});
+2
View File
@@ -10,6 +10,7 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v4
with:
token: ${{ secrets.REACT_NATIVE_BOT_GITHUB_TOKEN }}
fetch-depth: 0
fetch-tags: true
- name: Install dependencies
@@ -22,6 +23,7 @@ jobs:
- name: Generate Changelog
uses: actions/github-script@v6
with:
github-token: ${{ secrets.REACT_NATIVE_BOT_GITHUB_TOKEN }}
script: |
const {generateChangelog} = require('./.github/workflow-scripts/generateChangelog');
const version = '${{ github.ref_name }}';
+4 -2
View File
@@ -273,7 +273,8 @@ jobs:
NEW_ARCH_ENABLED=1
export RCT_USE_LOCAL_RN_DEP=/tmp/third-party/ReactNativeDependencies${{ matrix.flavor }}.xcframework.tar.gz
export RCT_TESTONLY_RNCORE_TARBALL_PATH="/tmp/ReactCore/ReactCore${{ matrix.flavor }}.xcframework.tar.gz"
# Disable prebuilds for now, as they are causing issues with E2E tests for 0.82-stable branch
# export RCT_TESTONLY_RNCORE_TARBALL_PATH="/tmp/ReactCore/ReactCore${{ matrix.flavor }}.xcframework.tar.gz"
HERMES_ENGINE_TARBALL_PATH=$HERMES_PATH RCT_NEW_ARCH_ENABLED=$NEW_ARCH_ENABLED bundle exec pod install
xcodebuild \
@@ -379,7 +380,8 @@ jobs:
runs-on: 8-core-ubuntu
needs: [set_release_type]
container:
image: reactnativecommunity/react-native-android:latest
# Version is pinned to v18.0 to unblock `run_fantom_tests` - see https://github.com/react-native-community/docker-android/pull/242#issuecomment-3280029122
image: reactnativecommunity/react-native-android:v18.0
env:
TERM: "dumb"
GRADLE_OPTS: "-Dorg.gradle.daemon=false"
@@ -0,0 +1,48 @@
name: Validate DotSlash Artifacts
on:
workflow_dispatch:
release:
types: [published]
push:
branches:
- main
paths:
- packages/debugger-shell/bin/react-native-devtools
- "scripts/releases/**"
- package.json
- yarn.lock
pull_request:
branches:
- main
paths:
- packages/debugger-shell/bin/react-native-devtools
- "scripts/releases/**"
- package.json
- yarn.lock
# Same time as the nightly build: 2:15 AM UTC
schedule:
- cron: "15 2 * * *"
jobs:
validate-dotslash-artifacts:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true
- name: Install dependencies
uses: ./.github/actions/yarn-install
- name: Configure Git
shell: bash
run: |
git config --local user.email "bot@reactnative.dev"
git config --local user.name "React Native Bot"
- name: Validate DotSlash artifacts
uses: actions/github-script@v6
with:
script: |
const {validateDotSlashArtifacts} = require('./scripts/releases/validate-dotslash-artifacts.js');
await validateDotSlashArtifacts();
+1
View File
@@ -135,6 +135,7 @@ if (project.findProperty("react.internal.useHermesNightly")?.toString()?.toBoole
configurations.all {
resolutionStrategy.dependencySubstitution {
substitute(project(":packages:react-native:ReactAndroid:hermes-engine"))
// TODO: T237406039 update coordinates
.using(module("com.facebook.react:hermes-android:0.+"))
.because("Users opted to use hermes from nightly")
}
+46
View File
@@ -0,0 +1,46 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
declare module '@expo/spawn-async' {
type SpawnOptions = {
cwd?: string,
env?: Object,
argv0?: string,
stdio?: string | Array<any>,
detached?: boolean,
uid?: number,
gid?: number,
shell?: boolean | string,
windowsVerbatimArguments?: boolean,
windowsHide?: boolean,
encoding?: string,
ignoreStdio?: boolean,
};
declare class SpawnPromise<T> extends Promise<T> {
child: child_process$ChildProcess;
}
type SpawnResult = {
pid?: number,
output: string[],
stdout: string,
stderr: string,
status: number | null,
signal: string | null,
};
declare function spawnAsync(
command: string,
args?: $ReadOnlyArray<string>,
options?: SpawnOptions,
): SpawnPromise<SpawnResult>;
declare module.exports: typeof spawnAsync;
}
+61
View File
@@ -0,0 +1,61 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
// Partial types for Octokit based on the usage in react-native-github
declare module '@octokit/rest' {
declare class Octokit {
constructor(options?: {auth?: string, ...}): this;
repos: $ReadOnly<{
listReleaseAssets: (
params: $ReadOnly<{
owner: string,
repo: string,
release_id: string,
}>,
) => Promise<{
data: Array<{
id: string,
name: string,
...
}>,
...
}>,
uploadReleaseAsset: (
params: $ReadOnly<{
owner: string,
repo: string,
release_id: string,
name: string,
data: Buffer,
headers: $ReadOnly<{
'content-type': string,
...
}>,
...
}>,
) => Promise<{
data: {
browser_download_url: string,
...
},
...
}>,
deleteReleaseAsset: (params: {
owner: string,
repo: string,
asset_id: string,
...
}) => Promise<mixed>,
}>;
}
declare export {Octokit};
}
+13
View File
@@ -0,0 +1,13 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
declare module 'fb-dotslash' {
declare module.exports: string;
}
+421
View File
@@ -0,0 +1,421 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
declare module 'jsonc-parser' {
/**
* Creates a JSON scanner on the given text.
* If ignoreTrivia is set, whitespaces or comments are ignored.
*/
declare export const createScanner: (
text: string,
ignoreTrivia?: boolean,
) => JSONScanner;
export type ScanError = number;
export type SyntaxKind = number;
/**
* The scanner object, representing a JSON scanner at a position in the input string.
*/
export type JSONScanner = $ReadOnly<{
/**
* Sets the scan position to a new offset. A call to 'scan' is needed to get the first token.
*/
setPosition(pos: number): void,
/**
* Read the next token. Returns the token code.
*/
scan(): SyntaxKind,
/**
* Returns the zero-based current scan position, which is after the last read token.
*/
getPosition(): number,
/**
* Returns the last read token.
*/
getToken(): SyntaxKind,
/**
* Returns the last read token value. The value for strings is the decoded string content. For numbers it's of type number, for boolean it's true or false.
*/
getTokenValue(): string,
/**
* The zero-based start offset of the last read token.
*/
getTokenOffset(): number,
/**
* The length of the last read token.
*/
getTokenLength(): number,
/**
* The zero-based start line number of the last read token.
*/
getTokenStartLine(): number,
/**
* The zero-based start character (column) of the last read token.
*/
getTokenStartCharacter(): number,
/**
* An error code of the last scan.
*/
getTokenError(): ScanError,
}>;
/**
* For a given offset, evaluate the location in the JSON document. Each segment in the location path is either a property name or an array index.
*/
declare export const getLocation: (
text: string,
position: number,
) => Location;
/**
* Parses the given text and returns the object the JSON content represents. On invalid input, the parser tries to be as fault tolerant as possible, but still return a result.
* Therefore, always check the errors list to find out if the input was valid.
*/
declare export const parse: (
text: string,
errors?: ParseError[],
options?: ParseOptions,
) => any;
/**
* Parses the given text and returns a tree representation the JSON content. On invalid input, the parser tries to be as fault tolerant as possible, but still return a result.
*/
declare export const parseTree: (
text: string,
errors?: ParseError[],
options?: ParseOptions,
) => Node | void;
/**
* Finds the node at the given path in a JSON DOM.
*/
declare export const findNodeAtLocation: (
root: Node,
path: JSONPath,
) => Node | void;
/**
* Finds the innermost node at the given offset. If includeRightBound is set, also finds nodes that end at the given offset.
*/
declare export const findNodeAtOffset: (
root: Node,
offset: number,
includeRightBound?: boolean,
) => Node | void;
/**
* Gets the JSON path of the given JSON DOM node
*/
declare export const getNodePath: (node: Node) => JSONPath;
/**
* Evaluates the JavaScript object of the given JSON DOM node
*/
declare export const getNodeValue: (node: Node) => any;
/**
* Parses the given text and invokes the visitor functions for each object, array and literal reached.
*/
declare export const visit: (
text: string,
visitor: JSONVisitor,
options?: ParseOptions,
) => any;
/**
* Takes JSON with JavaScript-style comments and remove
* them. Optionally replaces every none-newline character
* of comments with a replaceCharacter
*/
declare export const stripComments: (
text: string,
replaceCh?: string,
) => string;
export type ParseError = {
error: ParseErrorCode,
offset: number,
length: number,
};
export type ParseErrorCode = number;
declare export function printParseErrorCode(
code: ParseErrorCode,
):
| 'InvalidSymbol'
| 'InvalidNumberFormat'
| 'PropertyNameExpected'
| 'ValueExpected'
| 'ColonExpected'
| 'CommaExpected'
| 'CloseBraceExpected'
| 'CloseBracketExpected'
| 'EndOfFileExpected'
| 'InvalidCommentToken'
| 'UnexpectedEndOfComment'
| 'UnexpectedEndOfString'
| 'UnexpectedEndOfNumber'
| 'InvalidUnicode'
| 'InvalidEscapeCharacter'
| 'InvalidCharacter'
| '<unknown ParseErrorCode>';
export type NodeType =
| 'object'
| 'array'
| 'property'
| 'string'
| 'number'
| 'boolean'
| 'null';
export type Node = {
type: NodeType,
value?: any,
offset: number,
length: number,
colonOffset?: number,
parent?: Node,
children?: Node[],
};
/**
* A {@linkcode JSONPath} segment. Either a string representing an object property name
* or a number (starting at 0) for array indices.
*/
export type Segment = string | number;
export type JSONPath = Segment[];
export type Location = {
/**
* The previous property key or literal value (string, number, boolean or null) or undefined.
*/
previousNode?: Node,
/**
* The path describing the location in the JSON document. The path consists of a sequence of strings
* representing an object property or numbers for array indices.
*/
path: JSONPath,
/**
* Matches the locations path against a pattern consisting of strings (for properties) and numbers (for array indices).
* '*' will match a single segment of any property name or index.
* '**' will match a sequence of segments of any property name or index, or no segment.
*/
matches: (patterns: JSONPath) => boolean,
/**
* If set, the location's offset is at a property key.
*/
isAtPropertyKey: boolean,
};
export type ParseOptions = {
disallowComments?: boolean,
allowTrailingComma?: boolean,
allowEmptyContent?: boolean,
};
/**
* Visitor called by {@linkcode visit} when parsing JSON.
*
* The visitor functions have the following common parameters:
* - `offset`: Global offset within the JSON document, starting at 0
* - `startLine`: Line number, starting at 0
* - `startCharacter`: Start character (column) within the current line, starting at 0
*
* Additionally some functions have a `pathSupplier` parameter which can be used to obtain the
* current `JSONPath` within the document.
*/
export type JSONVisitor = {
/**
* Invoked when an open brace is encountered and an object is started. The offset and length represent the location of the open brace.
*/
onObjectBegin?: (
offset: number,
length: number,
startLine: number,
startCharacter: number,
pathSupplier: () => JSONPath,
) => void,
/**
* Invoked when a property is encountered. The offset and length represent the location of the property name.
* The `JSONPath` created by the `pathSupplier` refers to the enclosing JSON object, it does not include the
* property name yet.
*/
onObjectProperty?: (
property: string,
offset: number,
length: number,
startLine: number,
startCharacter: number,
pathSupplier: () => JSONPath,
) => void,
/**
* Invoked when a closing brace is encountered and an object is completed. The offset and length represent the location of the closing brace.
*/
onObjectEnd?: (
offset: number,
length: number,
startLine: number,
startCharacter: number,
) => void,
/**
* Invoked when an open bracket is encountered. The offset and length represent the location of the open bracket.
*/
onArrayBegin?: (
offset: number,
length: number,
startLine: number,
startCharacter: number,
pathSupplier: () => JSONPath,
) => void,
/**
* Invoked when a closing bracket is encountered. The offset and length represent the location of the closing bracket.
*/
onArrayEnd?: (
offset: number,
length: number,
startLine: number,
startCharacter: number,
) => void,
/**
* Invoked when a literal value is encountered. The offset and length represent the location of the literal value.
*/
onLiteralValue?: (
value: any,
offset: number,
length: number,
startLine: number,
startCharacter: number,
pathSupplier: () => JSONPath,
) => void,
/**
* Invoked when a comma or colon separator is encountered. The offset and length represent the location of the separator.
*/
onSeparator?: (
character: string,
offset: number,
length: number,
startLine: number,
startCharacter: number,
) => void,
/**
* When comments are allowed, invoked when a line or block comment is encountered. The offset and length represent the location of the comment.
*/
onComment?: (
offset: number,
length: number,
startLine: number,
startCharacter: number,
) => void,
/**
* Invoked on an error.
*/
onError?: (
error: ParseErrorCode,
offset: number,
length: number,
startLine: number,
startCharacter: number,
) => void,
};
/**
* An edit result describes a textual edit operation. It is the result of a {@linkcode format} and {@linkcode modify} operation.
* It consist of one or more edits describing insertions, replacements or removals of text segments.
* * The offsets of the edits refer to the original state of the document.
* * No two edits change or remove the same range of text in the original document.
* * Multiple edits can have the same offset if they are multiple inserts, or an insert followed by a remove or replace.
* * The order in the array defines which edit is applied first.
* To apply an edit result use {@linkcode applyEdits}.
* In general multiple EditResults must not be concatenated because they might impact each other, producing incorrect or malformed JSON data.
*/
export type EditResult = Edit[];
/**
* Represents a text modification
*/
export type Edit = {
/**
* The start offset of the modification.
*/
offset: number,
/**
* The length of the modification. Must not be negative. Empty length represents an *insert*.
*/
length: number,
/**
* The new content. Empty content represents a *remove*.
*/
content: string,
};
/**
* A text range in the document
*/
export type Range = {
/**
* The start offset of the range.
*/
offset: number,
/**
* The length of the range. Must not be negative.
*/
length: number,
};
/**
* Options used by {@linkcode format} when computing the formatting edit operations
*/
export type FormattingOptions = $ReadOnly<{
/**
* If indentation is based on spaces (`insertSpaces` = true), the number of spaces that make an indent.
*/
tabSize?: number,
/**
* Is indentation based on spaces?
*/
insertSpaces?: boolean,
/**
* The default 'end of line' character. If not set, '\n' is used as default.
*/
eol?: string,
}>;
/**
* Computes the edit operations needed to format a JSON document.
*
* @param documentText The input text
* @param range The range to format or `undefined` to format the full content
* @param options The formatting options
* @returns The edit operations describing the formatting changes to the original document following the format described in {@linkcode EditResult}.
* To apply the edit operations to the input, use {@linkcode applyEdits}.
*/
declare export function format(
documentText: string,
range: Range | void,
options: FormattingOptions,
): EditResult;
/**
* Options used by {@linkcode modify} when computing the modification edit operations
*/
export type ModificationOptions = {
/**
* Formatting options.
*/
formattingOptions: FormattingOptions,
/**
* Optional function to define the insertion index given an existing list of properties.
*/
getInsertionIndex?: (properties: string[]) => number,
};
/**
* Computes the edit operations needed to modify a value in the JSON document.
*
* @param documentText The input text
* @param path The path of the value to change. The path represents either to the document root, a property or an array item.
* If the path points to an non-existing property or item, it will be created.
* @param value The new value for the specified property or item. If the value is undefined,
* the property or item will be removed.
* @param options Options
* @returns The edit operations describing the changes to the original document, following the format described in {@linkcode EditResult}.
* To apply the edit operations to the input, use {@linkcode applyEdits}.
*/
declare export function modify(
text: string,
path: JSONPath,
value: any,
options: ModificationOptions,
): EditResult;
/**
* Applies edits to an input string.
* @param text The input text
* @param edits Edit operations following the format described in {@linkcode EditResult}.
* @returns The text with the applied edits.
* @throws An error if the edit operations are not well-formed as described in {@linkcode EditResult}.
*/
declare export function applyEdits(text: string, edits: EditResult): string;
}
+3
View File
@@ -12,3 +12,6 @@ reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64
# Controls whether to use Hermes from nightly builds. This will speed up builds
# but should NOT be turned on for CI or release builds.
react.internal.useHermesNightly=false
# Controls whether to use Hermes 1.0. Clean and rebuild when changing.
hermesV1Enabled=false
+7 -2
View File
@@ -54,13 +54,16 @@
"@babel/preset-env": "^7.25.3",
"@babel/preset-flow": "^7.24.7",
"@electron/packager": "^18.3.6",
"@expo/spawn-async": "^1.7.2",
"@jest/create-cache-key-function": "^29.7.0",
"@microsoft/api-extractor": "^7.52.2",
"@react-native/metro-babel-transformer": "0.82.0-main",
"@react-native/metro-config": "0.82.0-main",
"@octokit/rest": "^22.0.0",
"@react-native/metro-babel-transformer": "0.82.0",
"@react-native/metro-config": "0.82.0",
"@tsconfig/node22": "22.0.2",
"@types/react": "^19.1.0",
"@typescript-eslint/parser": "^8.36.0",
"ansi-regex": "^5.0.0",
"ansi-styles": "^4.2.1",
"babel-plugin-minify-dead-code-elimination": "^0.5.2",
"babel-plugin-syntax-hermes-parser": "0.32.0",
@@ -81,6 +84,7 @@
"eslint-plugin-react-native": "^4.0.0",
"eslint-plugin-redundant-undefined": "^0.4.0",
"eslint-plugin-relay": "^1.8.3",
"fb-dotslash": "0.5.8",
"flow-api-translator": "0.32.0",
"flow-bin": "^0.280.0",
"glob": "^7.1.1",
@@ -93,6 +97,7 @@
"jest-diff": "^29.7.0",
"jest-junit": "^16.0.0",
"jest-snapshot": "^29.7.0",
"jsonc-parser": "2.2.1",
"markdownlint-cli2": "^0.17.2",
"markdownlint-rule-relative-links": "^3.0.0",
"memfs": "^4.7.7",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/assets-registry",
"version": "0.82.0-main",
"version": "0.82.0",
"description": "Asset support code for React Native.",
"license": "MIT",
"repository": {
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/babel-plugin-codegen",
"version": "0.82.0-main",
"version": "0.82.0",
"description": "Babel plugin to generate native module and view manager code for React Native.",
"license": "MIT",
"repository": {
@@ -26,7 +26,7 @@
],
"dependencies": {
"@babel/traverse": "^7.25.3",
"@react-native/codegen": "0.82.0-main"
"@react-native/codegen": "0.82.0"
},
"devDependencies": {
"@babel/core": "^7.25.2"
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/community-cli-plugin",
"version": "0.82.0-main",
"version": "0.82.0",
"description": "Core CLI commands for React Native",
"keywords": [
"react-native",
@@ -22,7 +22,7 @@
"dist"
],
"dependencies": {
"@react-native/dev-middleware": "0.82.0-main",
"@react-native/dev-middleware": "0.82.0",
"debug": "^4.4.0",
"invariant": "^2.2.4",
"metro": "^0.83.1",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/core-cli-utils",
"version": "0.82.0-main",
"version": "0.82.0",
"description": "React Native CLI library for Frameworks to build on",
"license": "MIT",
"main": "./src/index.flow.js",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/debugger-frontend",
"version": "0.82.0-main",
"version": "0.82.0",
"description": "Debugger frontend for React Native based on Chrome DevTools",
"keywords": [
"react-native",
@@ -1,6 +1,6 @@
#!/usr/bin/env dotslash
// @generated SignedSource<<e93d55b5e28943e44271f5d3738083e0>>
// @generated SignedSource<<02ab38b39784853e42c1e8cab3894f5b>>
{
@@ -11,6 +11,9 @@
"hash": "sha256",
"digest": "4352f1c9848ca919101ec628bd08b87a72a828d1ab55fa43a02098329fa452fa",
"providers": [
{
"url": "https://github.com/facebook/react-native/releases/download/v0.82.0/React.Native.DevTools-linux-aarch64.tar.gz"
},
{
"type": "http",
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQM24LW0nPZRk0ypuIG9prz_72YjBJNcVlGSIEpO4zdlLXgw4dFNodH7MKg9eKNTnx7wrVDDBNACrnEPt_OfXOjZyZsV9Oaqu0-vNFRdlEyis4YqmpqGLtz3LvD-9R6fzcWxJI9zrhdPvOvlXP-3Syt1UNITaxXDVqIwAAYpCaAh0oLpupAFCc2yvYw"
@@ -24,6 +27,9 @@
"hash": "sha256",
"digest": "11c7b07942928a6301b07fbf2bc77ce1229b2a52891f23541cdd9858b5250e64",
"providers": [
{
"url": "https://github.com/facebook/react-native/releases/download/v0.82.0/React.Native.DevTools-linux-x86_64.tar.gz"
},
{
"type": "http",
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQNDwm7HZRhtNxHqMr1FfSb0afHFGrn1OHxH0gOiggrLrht9QRUgJ3GG5jj7huhQzMRogE-LCMsnxh1ioOZks-YYX4KRt6Kj1-whdWsGFc7lBhPOpk1ssbYFGN1NNyuyFRmH-3nCY3lBC4AmbCUkbDTUeCi9DidCtJeyc73CZJEu7M62rIzxR2yV"
@@ -37,6 +43,9 @@
"hash": "sha256",
"digest": "3cbe8b1b3d17e433347f1601435bb9a6cb758528a5c176a66fc52d9977223175",
"providers": [
{
"url": "https://github.com/facebook/react-native/releases/download/v0.82.0/React.Native.DevTools-macos-aarch64.tar.gz"
},
{
"type": "http",
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQOmC2cqqSv4OrSJKJroYVg_NE8OE4O73AXqY7wXiYqiWQVkDt0Xnyw3ZeUpQT_Qb0-OoT5F8REKoFrB6eqwat8Ovkyina30peYTTwNUzmwnnGQEg7J0fOHNxLF4dkmU1FagXtsoWgex4dKgsK_VpcMsHj3Vp7diomkYvWBVTf_gPVEseYSN9oKq92qa"
@@ -50,6 +59,9 @@
"hash": "sha256",
"digest": "6fb79bc2ba3008401b4c9c128248657b95b98581ccde60f8fadb622163779775",
"providers": [
{
"url": "https://github.com/facebook/react-native/releases/download/v0.82.0/React.Native.DevTools-macos-x86_64.tar.gz"
},
{
"type": "http",
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQMMtGn-YGdfLfTVWC8zbQkQx65Asq6iArKt1t__cjZ8UY_s6-sX5XBHr8k1SaexAO21dFZENQVZ1jW_wn_gJ9ENvosQDG1KfWMViKsHli0xRzZ1HVsgPIj_KVXe907QZwwtJf2XhgH0HT8dfH-AQdDcd0_TB5DFUwOsHzhH0nBrHet7YFkbJtPTaA"
@@ -63,6 +75,9 @@
"hash": "sha256",
"digest": "579a5b0944c51c3b1b541ad5af66c1ffedf93cae2a891ecdf88cb7219fd9b096",
"providers": [
{
"url": "https://github.com/facebook/react-native/releases/download/v0.82.0/React.Native.DevTools-windows-x86_64.tar.gz"
},
{
"type": "http",
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQOQ3E8lBXqdVHbDPyVb5AOQMrDWjFrFV8fnLLBsygQvLWdpu6ixyG9PgWdwpi5jM-XcDdCHkhBdhaq-5dwT_tgRWKCAMsEBoAIUk0Xg77mGyHG2VF7bNfQ2qFBMuObrsTmrKy1nJ-UFDDm29pJD4GkFQW5NesiBwndJj8t3B8Ur8cczh_XR8rF5"
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/debugger-shell",
"version": "0.82.0-main",
"version": "0.82.0",
"description": "Experimental debugger shell for React Native for use with @react-native/debugger-frontend",
"keywords": [
"react-native",
@@ -152,11 +152,7 @@ function getShellBinaryAndArgs(
): [string, Array<string>] {
switch (flavor) {
case 'prebuilt':
return [
// $FlowFixMe[cannot-resolve-module] fb-dotslash includes Flow types but Flow does not pick them up
require('fb-dotslash'),
[DEVTOOLS_BINARY_DOTSLASH_FILE],
];
return [require('fb-dotslash'), [DEVTOOLS_BINARY_DOTSLASH_FILE]];
case 'dev':
return [
// NOTE: Internally at Meta, this is aliased to a workspace that is
@@ -44,11 +44,11 @@ async function spawnAndGetStderr(
async function prepareDebuggerShellFromDotSlashFile(
filePath: string,
): Promise<DebuggerShellPreparationResult> {
const {code, stderr} = await spawnAndGetStderr(
// $FlowFixMe[cannot-resolve-module] fb-dotslash includes Flow types but Flow does not pick them up
require('fb-dotslash'),
['--', 'fetch', filePath],
);
const {code, stderr} = await spawnAndGetStderr(require('fb-dotslash'), [
'--',
'fetch',
filePath,
]);
if (code === 0) {
return {code: 'success'};
}
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/dev-middleware",
"version": "0.82.0-main",
"version": "0.82.0",
"description": "Dev server middleware for React Native",
"keywords": [
"react-native",
@@ -23,8 +23,8 @@
],
"dependencies": {
"@isaacs/ttlcache": "^1.4.1",
"@react-native/debugger-frontend": "0.82.0-main",
"@react-native/debugger-shell": "0.82.0-main",
"@react-native/debugger-frontend": "0.82.0",
"@react-native/debugger-shell": "0.82.0",
"chrome-launcher": "^0.15.2",
"chromium-edge-launcher": "^0.2.0",
"connect": "^3.6.5",
@@ -39,7 +39,7 @@
"node": ">= 20.19.4"
},
"devDependencies": {
"@react-native/debugger-shell": "0.82.0-main",
"@react-native/debugger-shell": "0.82.0",
"selfsigned": "^2.4.1",
"undici": "^5.29.0",
"wait-for-expect": "^3.0.2"
@@ -1,6 +1,6 @@
{
"name": "@react-native/eslint-config",
"version": "0.82.0-main",
"version": "0.82.0",
"description": "ESLint config for React Native",
"license": "MIT",
"repository": {
@@ -22,7 +22,7 @@
"dependencies": {
"@babel/core": "^7.25.2",
"@babel/eslint-parser": "^7.25.1",
"@react-native/eslint-plugin": "0.82.0-main",
"@react-native/eslint-plugin": "0.82.0",
"@typescript-eslint/eslint-plugin": "^8.36.0",
"@typescript-eslint/parser": "^8.36.0",
"eslint-config-prettier": "^8.5.0",
@@ -1,6 +1,6 @@
{
"name": "@react-native/eslint-plugin",
"version": "0.82.0-main",
"version": "0.82.0",
"description": "ESLint rules for @react-native/eslint-config",
"license": "MIT",
"repository": {
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/eslint-plugin-specs",
"version": "0.82.0-main",
"version": "0.82.0",
"description": "ESLint rules to validate NativeModule and Component Specs",
"license": "MIT",
"repository": {
@@ -26,7 +26,7 @@
"dependencies": {
"@babel/core": "^7.25.2",
"@babel/plugin-transform-flow-strip-types": "^7.25.2",
"@react-native/codegen": "0.82.0-main",
"@react-native/codegen": "0.82.0",
"make-dir": "^2.1.0",
"pirates": "^4.0.1",
"source-map-support": "0.5.0"
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/gradle-plugin",
"version": "0.82.0-main",
"version": "0.82.0",
"description": "Gradle Plugin for React Native",
"license": "MIT",
"repository": {
@@ -28,6 +28,7 @@ import com.facebook.react.utils.DependencyUtils.readVersionAndGroupStrings
import com.facebook.react.utils.JdkConfiguratorUtils.configureJavaToolChains
import com.facebook.react.utils.JsonUtils
import com.facebook.react.utils.NdkConfiguratorUtils.configureReactNativeNdk
import com.facebook.react.utils.ProjectUtils.isHermesV1Enabled
import com.facebook.react.utils.ProjectUtils.needsCodegenFromPackageJson
import com.facebook.react.utils.findPackageJsonFile
import java.io.File
@@ -54,6 +55,10 @@ class ReactPlugin : Plugin<Project> {
project,
)
if (project.rootProject.isHermesV1Enabled) {
rootExtension.hermesV1Enabled.set(true)
}
// App Only Configuration
project.pluginManager.withPlugin("com.android.application") {
// We wire the root extension with the values coming from the app (either user populated or
@@ -66,10 +71,12 @@ class ReactPlugin : Plugin<Project> {
project.afterEvaluate {
val reactNativeDir = extension.reactNativeDir.get().asFile
val propertiesFile = File(reactNativeDir, "ReactAndroid/gradle.properties")
val versionAndGroupStrings = readVersionAndGroupStrings(propertiesFile)
val versionString = versionAndGroupStrings.first
val groupString = versionAndGroupStrings.second
configureDependencies(project, versionString, groupString)
val hermesVersionPropertiesFile =
File(reactNativeDir, "sdks/hermes-engine/version.properties")
val versionAndGroupStrings =
readVersionAndGroupStrings(propertiesFile, hermesVersionPropertiesFile)
val hermesV1Enabled = rootExtension.hermesV1Enabled.get()
configureDependencies(project, versionAndGroupStrings, hermesV1Enabled)
configureRepositories(project)
}
@@ -11,6 +11,7 @@ import javax.inject.Inject
import org.gradle.api.Project
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.provider.ListProperty
import org.gradle.api.provider.Property
/**
* A private extension we set on the rootProject to make easier to share values at execution time
@@ -57,4 +58,6 @@ abstract class PrivateReactExtension @Inject constructor(project: Project) {
val codegenDir: DirectoryProperty =
objects.directoryProperty().convention(root.dir("node_modules/@react-native/codegen"))
val hermesV1Enabled: Property<Boolean> = objects.property(Boolean::class.java).convention(false)
}
@@ -94,7 +94,12 @@ abstract class BundleHermesCTask : DefaultTask() {
runCommand(bundleCommand)
if (hermesEnabled.get()) {
val detectedHermesCommand = detectOSAwareHermesCommand(root.get().asFile, hermesCommand.get())
val hermesV1Enabled =
if (project.rootProject.hasProperty("hermesV1Enabled"))
project.rootProject.findProperty("hermesV1Enabled") == "true"
else false
val detectedHermesCommand =
detectOSAwareHermesCommand(root.get().asFile, hermesCommand.get(), hermesV1Enabled)
val bytecodeFile = File("${bundleFile}.hbc")
val outputSourceMap = resolveOutputSourceMap(bundleAssetFilename)
val compilerSourceMap = resolveCompilerSourceMap(bundleAssetFilename)
@@ -7,12 +7,15 @@
package com.facebook.react.utils
import com.facebook.react.utils.PropertyUtils.DEFAULT_INTERNAL_PUBLISHING_GROUP
import com.facebook.react.utils.PropertyUtils.DEFAULT_INTERNAL_HERMES_PUBLISHING_GROUP
import com.facebook.react.utils.PropertyUtils.DEFAULT_INTERNAL_REACT_PUBLISHING_GROUP
import com.facebook.react.utils.PropertyUtils.EXCLUSIVE_ENTEPRISE_REPOSITORY
import com.facebook.react.utils.PropertyUtils.INCLUDE_JITPACK_REPOSITORY
import com.facebook.react.utils.PropertyUtils.INCLUDE_JITPACK_REPOSITORY_DEFAULT
import com.facebook.react.utils.PropertyUtils.INTERNAL_PUBLISHING_GROUP
import com.facebook.react.utils.PropertyUtils.INTERNAL_HERMES_PUBLISHING_GROUP
import com.facebook.react.utils.PropertyUtils.INTERNAL_HERMES_V1_VERSION_NAME
import com.facebook.react.utils.PropertyUtils.INTERNAL_REACT_NATIVE_MAVEN_LOCAL_REPO
import com.facebook.react.utils.PropertyUtils.INTERNAL_REACT_PUBLISHING_GROUP
import com.facebook.react.utils.PropertyUtils.INTERNAL_USE_HERMES_NIGHTLY
import com.facebook.react.utils.PropertyUtils.INTERNAL_VERSION_NAME
import com.facebook.react.utils.PropertyUtils.SCOPED_EXCLUSIVE_ENTEPRISE_REPOSITORY
@@ -25,6 +28,14 @@ import org.gradle.api.artifacts.repositories.MavenArtifactRepository
internal object DependencyUtils {
internal data class Coordinates(
val versionString: String,
val hermesVersionString: String,
val hermesV1VersionString: String,
val reactGroupString: String = DEFAULT_INTERNAL_REACT_PUBLISHING_GROUP,
val hermesGroupString: String = DEFAULT_INTERNAL_HERMES_PUBLISHING_GROUP,
)
/**
* This method takes care of configuring the repositories{} block for both the app and all the 3rd
* party libraries which are auto-linked.
@@ -95,14 +106,20 @@ internal object DependencyUtils {
* This method takes care of configuring the resolution strategy for both the app and all the 3rd
* party libraries which are auto-linked. Specifically it takes care of:
* - Forcing the react-android/hermes-android version to the one specified in the package.json
* - Substituting `react-native` with `react-android` and `hermes-engine` with `hermes-android`.
* - Substituting `react-native` with `react-android` and `hermes-engine` with `hermes-android`
* - Selecting between the classic Hermes and Hermes V1
*/
fun configureDependencies(
project: Project,
versionString: String,
groupString: String = DEFAULT_INTERNAL_PUBLISHING_GROUP,
coordinates: Coordinates,
hermesV1Enabled: Boolean = false,
) {
if (versionString.isBlank()) return
if (
coordinates.versionString.isBlank() ||
(!hermesV1Enabled && coordinates.hermesVersionString.isBlank()) ||
(hermesV1Enabled && coordinates.hermesV1VersionString.isBlank())
)
return
project.rootProject.allprojects { eachProject ->
eachProject.configurations.all { configuration ->
// Here we set a dependencySubstitution for both react-native and hermes-engine as those
@@ -110,61 +127,83 @@ internal object DependencyUtils {
// This allows users to import libraries that are still using
// implementation("com.facebook.react:react-native:+") and resolve the right dependency.
configuration.resolutionStrategy.dependencySubstitution {
getDependencySubstitutions(versionString, groupString).forEach { (module, dest, reason) ->
getDependencySubstitutions(coordinates, hermesV1Enabled).forEach { (module, dest, reason)
->
it.substitute(it.module(module)).using(it.module(dest)).because(reason)
}
}
configuration.resolutionStrategy.force(
"${groupString}:react-android:${versionString}",
"${coordinates.reactGroupString}:react-android:${coordinates.versionString}",
)
if (!(eachProject.findProperty(INTERNAL_USE_HERMES_NIGHTLY) as? String).toBoolean()) {
// Contributors only: The hermes-engine version is forced only if the user has
// not opted into using nightlies for local development.
configuration.resolutionStrategy.force("${groupString}:hermes-android:${versionString}")
configuration.resolutionStrategy.force(
// TODO: T237406039 update coordinates
if (hermesV1Enabled)
"${coordinates.hermesGroupString}:hermes-android:${coordinates.hermesV1VersionString}"
else
"${coordinates.reactGroupString}:hermes-android:${coordinates.hermesVersionString}"
)
}
}
}
}
internal fun getDependencySubstitutions(
versionString: String,
groupString: String = DEFAULT_INTERNAL_PUBLISHING_GROUP,
coordinates: Coordinates,
hermesV1Enabled: Boolean = false,
): List<Triple<String, String, String>> {
// TODO: T231755027 update coordinates and versioning
val dependencySubstitution = mutableListOf<Triple<String, String, String>>()
// TODO: T237406039 update coordinates
val hermesVersionString =
if (hermesV1Enabled)
"${coordinates.hermesGroupString}:hermes-android:${coordinates.hermesV1VersionString}"
else "${coordinates.reactGroupString}:hermes-android:${coordinates.hermesVersionString}"
dependencySubstitution.add(
Triple(
"com.facebook.react:react-native",
"${groupString}:react-android:${versionString}",
"${coordinates.reactGroupString}:react-android:${coordinates.versionString}",
"The react-native artifact was deprecated in favor of react-android due to https://github.com/facebook/react-native/issues/35210.",
)
)
dependencySubstitution.add(
Triple(
"com.facebook.react:hermes-engine",
"${groupString}:hermes-android:${versionString}",
hermesVersionString,
"The hermes-engine artifact was deprecated in favor of hermes-android due to https://github.com/facebook/react-native/issues/35210.",
)
)
if (groupString != DEFAULT_INTERNAL_PUBLISHING_GROUP) {
if (coordinates.reactGroupString != DEFAULT_INTERNAL_REACT_PUBLISHING_GROUP) {
dependencySubstitution.add(
Triple(
"com.facebook.react:react-android",
"${groupString}:react-android:${versionString}",
"${coordinates.reactGroupString}:react-android:${coordinates.versionString}",
"The react-android dependency was modified to use the correct Maven group.",
)
)
// TODO: T237406039 update coordinates
dependencySubstitution.add(
Triple(
"com.facebook.react:hermes-android",
"${groupString}:hermes-android:${versionString}",
hermesVersionString,
"The hermes-android dependency was modified to use the correct Maven group.",
)
)
} else if (hermesV1Enabled) {
dependencySubstitution.add(
Triple(
"com.facebook.react:hermes-android",
hermesVersionString,
"The hermes-android dependency was modified to use Hermes V1.",
)
)
}
return dependencySubstitution
}
fun readVersionAndGroupStrings(propertiesFile: File): Pair<String, String> {
fun readVersionAndGroupStrings(propertiesFile: File, hermesVersionFile: File): Coordinates {
val reactAndroidProperties = Properties()
propertiesFile.inputStream().use { reactAndroidProperties.load(it) }
val versionStringFromFile = (reactAndroidProperties[INTERNAL_VERSION_NAME] as? String).orEmpty()
@@ -176,10 +215,27 @@ internal object DependencyUtils {
versionStringFromFile
}
// Returns Maven group for repos using different group for Maven artifacts
val groupString =
reactAndroidProperties[INTERNAL_PUBLISHING_GROUP] as? String
?: DEFAULT_INTERNAL_PUBLISHING_GROUP
return Pair(versionString, groupString)
val reactGroupString =
reactAndroidProperties[INTERNAL_REACT_PUBLISHING_GROUP] as? String
?: DEFAULT_INTERNAL_REACT_PUBLISHING_GROUP
val hermesGroupString =
reactAndroidProperties[INTERNAL_HERMES_PUBLISHING_GROUP] as? String
?: DEFAULT_INTERNAL_HERMES_PUBLISHING_GROUP
// TODO: T237406039 read both versions from the same file
val hermesVersionProperties = Properties()
hermesVersionFile.inputStream().use { hermesVersionProperties.load(it) }
val hermesVersion = versionString
val hermesV1Version =
(hermesVersionProperties[INTERNAL_HERMES_V1_VERSION_NAME] as? String).orEmpty()
return Coordinates(
versionString,
hermesVersion,
hermesV1Version,
reactGroupString,
hermesGroupString,
)
}
fun Project.mavenRepoFromUrl(
@@ -122,11 +122,16 @@ private fun detectCliFile(reactNativeRoot: File, preconfiguredCliFile: File?): F
* used if the user is building Hermes from source.
* 3. The file located in `node_modules/react-native/sdks/hermesc/%OS-BIN%/hermesc` where `%OS-BIN%`
* is substituted with the correct OS arch. This will be used if the user is using a precompiled
* hermes-engine package.
* hermes-engine package. Or, if the user has opted in to use Hermes V1, the used file will be
* located in `node_modules/hermes-compiler/%OS-BIN%/hermesc` where `%OS-BIN%` is substituted
* with the correct OS arch.
* 4. Fails otherwise
*/
internal fun detectOSAwareHermesCommand(projectRoot: File, hermesCommand: String): String {
// 1. If the project specifies a Hermes command, don't second guess it.
internal fun detectOSAwareHermesCommand(
projectRoot: File,
hermesCommand: String,
hermesV1Enabled: Boolean = false,
): String { // 1. If the project specifies a Hermes command, don't second guess it.
if (hermesCommand.isNotBlank()) {
val osSpecificHermesCommand =
if ("%OS-BIN%" in hermesCommand) {
@@ -146,9 +151,13 @@ internal fun detectOSAwareHermesCommand(projectRoot: File, hermesCommand: String
return builtHermesc.cliPath(projectRoot)
}
// 3. If the react-native contains a pre-built hermesc, use it.
// 3. If Hermes V1 is enabled, use hermes-compiler from npm, otherwise, if the
// react-native contains a pre-built hermesc, use it.
// TODO: T237406039 use hermes-compiler from npm for both
val hermesCPath = if (hermesV1Enabled) HERMES_COMPILER_NPM_DIR else HERMESC_IN_REACT_NATIVE_DIR
val prebuiltHermesPath =
HERMESC_IN_REACT_NATIVE_DIR.plus(getHermesCBin())
hermesCPath
.plus(getHermesCBin())
.replace("%OS-BIN%", getHermesOSBin())
// Execution on Windows fails with / as separator
.replace('/', File.separatorChar)
@@ -233,6 +242,7 @@ internal fun readPackageJsonFile(
return packageJson?.let { JsonUtils.fromPackageJson(it) }
}
private const val HERMES_COMPILER_NPM_DIR = "node_modules/hermes-compiler/hermesc/%OS-BIN%/"
private const val HERMESC_IN_REACT_NATIVE_DIR = "node_modules/react-native/sdks/hermesc/%OS-BIN%/"
private const val HERMESC_BUILT_FROM_SOURCE_DIR =
"node_modules/react-native/ReactAndroid/hermes-engine/build/hermes/bin/"
@@ -13,14 +13,17 @@ import com.facebook.react.utils.KotlinStdlibCompatUtils.lowercaseCompat
import com.facebook.react.utils.KotlinStdlibCompatUtils.toBooleanStrictOrNullCompat
import com.facebook.react.utils.PropertyUtils.EDGE_TO_EDGE_ENABLED
import com.facebook.react.utils.PropertyUtils.HERMES_ENABLED
import com.facebook.react.utils.PropertyUtils.HERMES_V1_ENABLED
import com.facebook.react.utils.PropertyUtils.REACT_NATIVE_ARCHITECTURES
import com.facebook.react.utils.PropertyUtils.SCOPED_EDGE_TO_EDGE_ENABLED
import com.facebook.react.utils.PropertyUtils.SCOPED_HERMES_ENABLED
import com.facebook.react.utils.PropertyUtils.SCOPED_HERMES_V1_ENABLED
import com.facebook.react.utils.PropertyUtils.SCOPED_REACT_NATIVE_ARCHITECTURES
import com.facebook.react.utils.PropertyUtils.SCOPED_USE_THIRD_PARTY_JSC
import com.facebook.react.utils.PropertyUtils.USE_THIRD_PARTY_JSC
import org.gradle.api.Project
import org.gradle.api.file.DirectoryProperty
import org.jetbrains.kotlin.gradle.plugin.extraProperties
internal object ProjectUtils {
@@ -68,6 +71,17 @@ internal object ProjectUtils {
(project.hasProperty(SCOPED_USE_THIRD_PARTY_JSC) &&
project.property(SCOPED_USE_THIRD_PARTY_JSC).toString().toBoolean())
internal val Project.isHermesV1Enabled: Boolean
get() =
(project.hasProperty(HERMES_V1_ENABLED) &&
project.property(HERMES_V1_ENABLED).toString().toBoolean()) ||
(project.hasProperty(SCOPED_HERMES_V1_ENABLED) &&
project.property(SCOPED_HERMES_V1_ENABLED).toString().toBoolean()) ||
(project.extraProperties.has(HERMES_V1_ENABLED) &&
project.extraProperties.get(HERMES_V1_ENABLED).toString().toBoolean()) ||
(project.extraProperties.has(SCOPED_HERMES_V1_ENABLED) &&
project.extraProperties.get(SCOPED_HERMES_V1_ENABLED).toString().toBoolean())
internal fun Project.needsCodegenFromPackageJson(rootProperty: DirectoryProperty): Boolean {
val parsedPackageJson = readPackageJsonFile(this, rootProperty)
return needsCodegenFromPackageJson(parsedPackageJson)
@@ -18,6 +18,10 @@ object PropertyUtils {
const val HERMES_ENABLED = "hermesEnabled"
const val SCOPED_HERMES_ENABLED = "react.hermesEnabled"
/** Public property that toggles Hermes V1 */
const val HERMES_V1_ENABLED = "hermesV1Enabled"
const val SCOPED_HERMES_V1_ENABLED = "react.hermesV1Enabled"
/** Public property that toggles edge-to-edge */
const val EDGE_TO_EDGE_ENABLED = "edgeToEdgeEnabled"
const val SCOPED_EDGE_TO_EDGE_ENABLED = "react.edgeToEdgeEnabled"
@@ -68,9 +72,17 @@ object PropertyUtils {
const val INTERNAL_USE_HERMES_NIGHTLY = "react.internal.useHermesNightly"
/** Internal property used to override the publishing group for the React Native artifacts. */
const val INTERNAL_PUBLISHING_GROUP = "react.internal.publishingGroup"
const val DEFAULT_INTERNAL_PUBLISHING_GROUP = "com.facebook.react"
const val INTERNAL_REACT_PUBLISHING_GROUP = "react.internal.publishingGroup"
const val INTERNAL_HERMES_PUBLISHING_GROUP = "react.internal.hermesPublishingGroup"
const val DEFAULT_INTERNAL_REACT_PUBLISHING_GROUP = "com.facebook.react"
const val DEFAULT_INTERNAL_HERMES_PUBLISHING_GROUP = "com.facebook.hermes"
/** Internal property used to control the version name of React Native */
const val INTERNAL_VERSION_NAME = "VERSION_NAME"
/**
* Internal property, shared with iOS, used to control the version name of Hermes Engine. This is
* stored in sdks/hermes-engine/version.properties
*/
const val INTERNAL_HERMES_V1_VERSION_NAME = "HERMES_V1_VERSION_NAME"
}
@@ -275,71 +275,160 @@ class DependencyUtilsTest {
fun configureDependencies_withEmptyVersion_doesNothing() {
val project = createProject()
configureDependencies(project, "")
configureDependencies(project, DependencyUtils.Coordinates("", "", ""))
assertThat(project.configurations.first().resolutionStrategy.forcedModules.isEmpty()).isTrue()
}
@Test
fun configureDependencies_withVersionString_appliesResolutionStrategy() {
fun configureDependencies_withVersionString_appliesResolutionStrategy_withClassicHermes() {
val project = createProject()
configureDependencies(project, "1.2.3")
configureDependencies(project, DependencyUtils.Coordinates("1.2.3", "4.5.6", "7.8.9"))
val forcedModules = project.configurations.first().resolutionStrategy.forcedModules
assertThat(forcedModules.any { it.toString() == "com.facebook.react:react-android:1.2.3" })
.isTrue()
assertThat(forcedModules.any { it.toString() == "com.facebook.react:hermes-android:1.2.3" })
assertThat(forcedModules.any { it.toString() == "com.facebook.react:hermes-android:4.5.6" })
.isTrue()
}
@Test
fun configureDependencies_withVersionString_appliesOnAllProjects() {
fun configureDependencies_withVersionString_appliesResolutionStrategy_withHermesV1() {
val project = createProject()
configureDependencies(
project,
DependencyUtils.Coordinates("1.2.3", "4.5.6", "7.8.9"),
hermesV1Enabled = true,
)
val forcedModules = project.configurations.first().resolutionStrategy.forcedModules
assertThat(forcedModules.any { it.toString() == "com.facebook.react:react-android:1.2.3" })
.isTrue()
assertThat(forcedModules.any { it.toString() == "com.facebook.hermes:hermes-android:7.8.9" })
.isTrue()
}
@Test
fun configureDependencies_withVersionString_appliesOnAllProjects_withClassicHermes() {
val rootProject = ProjectBuilder.builder().build()
val appProject = ProjectBuilder.builder().withName("app").withParent(rootProject).build()
val libProject = ProjectBuilder.builder().withName("lib").withParent(rootProject).build()
appProject.plugins.apply("com.android.application")
libProject.plugins.apply("com.android.library")
configureDependencies(appProject, "1.2.3")
configureDependencies(appProject, DependencyUtils.Coordinates("1.2.3", "4.5.6", "7.8.9"))
val appForcedModules = appProject.configurations.first().resolutionStrategy.forcedModules
val libForcedModules = libProject.configurations.first().resolutionStrategy.forcedModules
assertThat(appForcedModules.any { it.toString() == "com.facebook.react:react-android:1.2.3" })
.isTrue()
assertThat(appForcedModules.any { it.toString() == "com.facebook.react:hermes-android:1.2.3" })
assertThat(appForcedModules.any { it.toString() == "com.facebook.react:hermes-android:4.5.6" })
.isTrue()
assertThat(libForcedModules.any { it.toString() == "com.facebook.react:react-android:1.2.3" })
.isTrue()
assertThat(libForcedModules.any { it.toString() == "com.facebook.react:hermes-android:1.2.3" })
assertThat(libForcedModules.any { it.toString() == "com.facebook.react:hermes-android:4.5.6" })
.isTrue()
}
@Test
fun configureDependencies_withVersionStringAndGroupString_appliesOnAllProjects() {
fun configureDependencies_withVersionString_appliesOnAllProjects_withHermesV1() {
val rootProject = ProjectBuilder.builder().build()
val appProject = ProjectBuilder.builder().withName("app").withParent(rootProject).build()
val libProject = ProjectBuilder.builder().withName("lib").withParent(rootProject).build()
appProject.plugins.apply("com.android.application")
libProject.plugins.apply("com.android.library")
configureDependencies(appProject, "1.2.3", "io.github.test")
configureDependencies(
appProject,
DependencyUtils.Coordinates("1.2.3", "4.5.6", "7.8.9"),
hermesV1Enabled = true,
)
val appForcedModules = appProject.configurations.first().resolutionStrategy.forcedModules
val libForcedModules = libProject.configurations.first().resolutionStrategy.forcedModules
assertThat(appForcedModules.any { it.toString() == "com.facebook.react:react-android:1.2.3" })
.isTrue()
assertThat(appForcedModules.any { it.toString() == "com.facebook.hermes:hermes-android:7.8.9" })
.isTrue()
assertThat(libForcedModules.any { it.toString() == "com.facebook.react:react-android:1.2.3" })
.isTrue()
assertThat(libForcedModules.any { it.toString() == "com.facebook.hermes:hermes-android:7.8.9" })
.isTrue()
}
@Test
fun configureDependencies_withVersionStringAndGroupString_appliesOnAllProjects_withClassicHermes() {
val rootProject = ProjectBuilder.builder().build()
val appProject = ProjectBuilder.builder().withName("app").withParent(rootProject).build()
val libProject = ProjectBuilder.builder().withName("lib").withParent(rootProject).build()
appProject.plugins.apply("com.android.application")
libProject.plugins.apply("com.android.library")
configureDependencies(
appProject,
DependencyUtils.Coordinates(
"1.2.3",
"4.5.6",
"7.8.9",
"io.github.test",
"io.github.test.hermes",
),
)
val appForcedModules = appProject.configurations.first().resolutionStrategy.forcedModules
val libForcedModules = libProject.configurations.first().resolutionStrategy.forcedModules
assertThat(appForcedModules.any { it.toString() == "io.github.test:react-android:1.2.3" })
.isTrue()
assertThat(appForcedModules.any { it.toString() == "io.github.test:hermes-android:1.2.3" })
assertThat(appForcedModules.any { it.toString() == "io.github.test:hermes-android:4.5.6" })
.isTrue()
assertThat(libForcedModules.any { it.toString() == "io.github.test:react-android:1.2.3" })
.isTrue()
assertThat(libForcedModules.any { it.toString() == "io.github.test:hermes-android:1.2.3" })
assertThat(libForcedModules.any { it.toString() == "io.github.test:hermes-android:4.5.6" })
.isTrue()
}
@Test
fun getDependencySubstitutions_withDefaultGroup_substitutesCorrectly() {
val dependencySubstitutions = getDependencySubstitutions("0.42.0")
fun configureDependencies_withVersionStringAndGroupString_appliesOnAllProjects_withHermesV1() {
val rootProject = ProjectBuilder.builder().build()
val appProject = ProjectBuilder.builder().withName("app").withParent(rootProject).build()
val libProject = ProjectBuilder.builder().withName("lib").withParent(rootProject).build()
appProject.plugins.apply("com.android.application")
libProject.plugins.apply("com.android.library")
configureDependencies(
appProject,
DependencyUtils.Coordinates(
"1.2.3",
"4.5.6",
"7.8.9",
"io.github.test",
"io.github.test.hermes",
),
hermesV1Enabled = true,
)
val appForcedModules = appProject.configurations.first().resolutionStrategy.forcedModules
val libForcedModules = libProject.configurations.first().resolutionStrategy.forcedModules
assertThat(appForcedModules.any { it.toString() == "io.github.test:react-android:1.2.3" })
.isTrue()
assertThat(
appForcedModules.any { it.toString() == "io.github.test.hermes:hermes-android:7.8.9" }
)
.isTrue()
assertThat(libForcedModules.any { it.toString() == "io.github.test:react-android:1.2.3" })
.isTrue()
assertThat(
libForcedModules.any { it.toString() == "io.github.test.hermes:hermes-android:7.8.9" }
)
.isTrue()
}
@Test
fun getDependencySubstitutions_withDefaultGroup_substitutesCorrectly_withClassicHermes() {
val dependencySubstitutions =
getDependencySubstitutions(DependencyUtils.Coordinates("0.42.0", "0.42.0", "0.43.0"))
assertThat("com.facebook.react:react-native").isEqualTo(dependencySubstitutions[0].first)
assertThat("com.facebook.react:react-android:0.42.0")
@@ -358,8 +447,41 @@ class DependencyUtilsTest {
}
@Test
fun getDependencySubstitutions_withCustomGroup_substitutesCorrectly() {
val dependencySubstitutions = getDependencySubstitutions("0.42.0", "io.github.test")
fun getDependencySubstitutions_withDefaultGroup_substitutesCorrectly_withHermesV1() {
val dependencySubstitutions =
getDependencySubstitutions(
DependencyUtils.Coordinates("0.42.0", "0.42.0", "0.43.0"),
hermesV1Enabled = true,
)
assertThat("com.facebook.react:react-native").isEqualTo(dependencySubstitutions[0].first)
assertThat("com.facebook.react:react-android:0.42.0")
.isEqualTo(dependencySubstitutions[0].second)
assertThat(
"The react-native artifact was deprecated in favor of react-android due to https://github.com/facebook/react-native/issues/35210."
)
.isEqualTo(dependencySubstitutions[0].third)
assertThat("com.facebook.react:hermes-engine").isEqualTo(dependencySubstitutions[1].first)
assertThat("com.facebook.hermes:hermes-android:0.43.0")
.isEqualTo(dependencySubstitutions[1].second)
assertThat(
"The hermes-engine artifact was deprecated in favor of hermes-android due to https://github.com/facebook/react-native/issues/35210."
)
.isEqualTo(dependencySubstitutions[1].third)
}
@Test
fun getDependencySubstitutions_withCustomGroup_substitutesCorrectly_withClassicHermes() {
val dependencySubstitutions =
getDependencySubstitutions(
DependencyUtils.Coordinates(
"0.42.0",
"0.42.0",
"0.43.0",
"io.github.test",
"io.github.test.hermes",
)
)
assertThat("com.facebook.react:react-native").isEqualTo(dependencySubstitutions[0].first)
assertThat("io.github.test:react-android:0.42.0").isEqualTo(dependencySubstitutions[0].second)
@@ -383,6 +505,44 @@ class DependencyUtilsTest {
.isEqualTo(dependencySubstitutions[3].third)
}
@Test
fun getDependencySubstitutions_withCustomGroup_substitutesCorrectly_withHermesV1() {
val dependencySubstitutions =
getDependencySubstitutions(
DependencyUtils.Coordinates(
"0.42.0",
"0.42.0",
"0.43.0",
"io.github.test",
"io.github.test.hermes",
),
hermesV1Enabled = true,
)
assertThat("com.facebook.react:react-native").isEqualTo(dependencySubstitutions[0].first)
assertThat("io.github.test:react-android:0.42.0").isEqualTo(dependencySubstitutions[0].second)
assertThat(
"The react-native artifact was deprecated in favor of react-android due to https://github.com/facebook/react-native/issues/35210."
)
.isEqualTo(dependencySubstitutions[0].third)
assertThat("com.facebook.react:hermes-engine").isEqualTo(dependencySubstitutions[1].first)
assertThat("io.github.test.hermes:hermes-android:0.43.0")
.isEqualTo(dependencySubstitutions[1].second)
assertThat(
"The hermes-engine artifact was deprecated in favor of hermes-android due to https://github.com/facebook/react-native/issues/35210."
)
.isEqualTo(dependencySubstitutions[1].third)
assertThat("com.facebook.react:react-android").isEqualTo(dependencySubstitutions[2].first)
assertThat("io.github.test:react-android:0.42.0").isEqualTo(dependencySubstitutions[2].second)
assertThat("The react-android dependency was modified to use the correct Maven group.")
.isEqualTo(dependencySubstitutions[2].third)
assertThat("com.facebook.react:hermes-android").isEqualTo(dependencySubstitutions[3].first)
assertThat("io.github.test.hermes:hermes-android:0.43.0")
.isEqualTo(dependencySubstitutions[3].second)
assertThat("The hermes-android dependency was modified to use the correct Maven group.")
.isEqualTo(dependencySubstitutions[3].third)
}
@Test
fun readVersionString_withCorrectVersionString_returnsIt() {
val propertiesFile =
@@ -396,9 +556,25 @@ class DependencyUtilsTest {
)
}
val versionString = readVersionAndGroupStrings(propertiesFile).first
val hermesVersionFile =
tempFolder.newFile("version.properties").apply {
writeText(
"""
HERMES_V1_VERSION_NAME=1000.0.0
ANOTHER_PROPERTY=true
"""
.trimIndent()
)
}
val strings = readVersionAndGroupStrings(propertiesFile, hermesVersionFile)
val versionString = strings.versionString
val hermesVersionString = strings.hermesVersionString
val hermesV1VersionString = strings.hermesV1VersionString
assertThat(versionString).isEqualTo("1000.0.0")
assertThat(hermesVersionString).isEqualTo("1000.0.0")
assertThat(hermesV1VersionString).isEqualTo("1000.0.0")
}
@Test
@@ -408,15 +584,33 @@ class DependencyUtilsTest {
writeText(
"""
VERSION_NAME=0.0.0-20221101-2019-cfe811ab1
HERMES_VERSION_NAME=0.12.0-commitly-20221101-2019-cfe811ab1
HERMES_V1_VERSION_NAME=250829098.0.0-stable
ANOTHER_PROPERTY=true
"""
.trimIndent()
)
}
val versionString = readVersionAndGroupStrings(propertiesFile).first
val hermesVersionFile =
tempFolder.newFile("version.properties").apply {
writeText(
"""
HERMES_V1_VERSION_NAME=250829098.0.0-stable
ANOTHER_PROPERTY=true
"""
.trimIndent()
)
}
val strings = readVersionAndGroupStrings(propertiesFile, hermesVersionFile)
val versionString = strings.versionString
val hermesVersionString = strings.hermesVersionString
val hermesV1VersionString = strings.hermesV1VersionString
assertThat(versionString).isEqualTo("0.0.0-20221101-2019-cfe811ab1-SNAPSHOT")
assertThat(hermesVersionString).isEqualTo("0.0.0-20221101-2019-cfe811ab1-SNAPSHOT")
assertThat(hermesV1VersionString).isEqualTo("250829098.0.0-stable")
}
@Test
@@ -431,8 +625,23 @@ class DependencyUtilsTest {
)
}
val versionString = readVersionAndGroupStrings(propertiesFile).first
val hermesVersionFile =
tempFolder.newFile("version.properties").apply {
writeText(
"""
ANOTHER_PROPERTY=true
"""
.trimIndent()
)
}
val strings = readVersionAndGroupStrings(propertiesFile, hermesVersionFile)
val versionString = strings.versionString
val hermesVersionString = strings.hermesVersionString
val hermesV1VersionString = strings.hermesV1VersionString
assertThat(versionString).isEqualTo("")
assertThat(hermesVersionString).isEqualTo("")
assertThat(hermesV1VersionString).isEqualTo("")
}
@Test
@@ -448,8 +657,24 @@ class DependencyUtilsTest {
)
}
val versionString = readVersionAndGroupStrings(propertiesFile).first
val hermesVersionFile =
tempFolder.newFile("version.properties").apply {
writeText(
"""
HERMES_V1_VERSION_NAME=
ANOTHER_PROPERTY=true
"""
.trimIndent()
)
}
val strings = readVersionAndGroupStrings(propertiesFile, hermesVersionFile)
val versionString = strings.versionString
val hermesVersionString = strings.hermesVersionString
val hermesV1VersionString = strings.hermesV1VersionString
assertThat(versionString).isEqualTo("")
assertThat(hermesVersionString).isEqualTo("")
assertThat(hermesV1VersionString).isEqualTo("")
}
@Test
@@ -459,15 +684,30 @@ class DependencyUtilsTest {
writeText(
"""
react.internal.publishingGroup=io.github.test
react.internal.hermesPublishingGroup=io.github.test
ANOTHER_PROPERTY=true
"""
.trimIndent()
)
}
val groupString = readVersionAndGroupStrings(propertiesFile).second
val hermesVersionFile =
tempFolder.newFile("version.properties").apply {
writeText(
"""
HERMES_V1_VERSION_NAME=
ANOTHER_PROPERTY=true
"""
.trimIndent()
)
}
assertThat(groupString).isEqualTo("io.github.test")
val strings = readVersionAndGroupStrings(propertiesFile, hermesVersionFile)
val reactGroupString = strings.reactGroupString
val hermesGroupString = strings.hermesGroupString
assertThat(reactGroupString).isEqualTo("io.github.test")
assertThat(hermesGroupString).isEqualTo("io.github.test")
}
@Test
@@ -482,9 +722,23 @@ class DependencyUtilsTest {
)
}
val groupString = readVersionAndGroupStrings(propertiesFile).second
val hermesVersionFile =
tempFolder.newFile("version.properties").apply {
writeText(
"""
HERMES_V1_VERSION_NAME=
ANOTHER_PROPERTY=true
"""
.trimIndent()
)
}
assertThat(groupString).isEqualTo("com.facebook.react")
val strings = readVersionAndGroupStrings(propertiesFile, hermesVersionFile)
val reactGroupString = strings.reactGroupString
val hermesGroupString = strings.hermesGroupString
assertThat(reactGroupString).isEqualTo("com.facebook.react")
assertThat(hermesGroupString).isEqualTo("com.facebook.hermes")
}
@Test
@@ -162,6 +162,16 @@ class PathUtilsTest {
assertThat(detectOSAwareHermesCommand(tempFolder.root, "")).isEqualTo(expected.toString())
}
@Test
@WithOs(OS.MAC)
fun detectOSAwareHermesCommand_withHermesV1Enabled() {
tempFolder.newFolder("node_modules/hermes-compiler/hermesc/osx-bin/")
val expected = tempFolder.newFile("node_modules/hermes-compiler/hermesc/osx-bin/hermesc")
assertThat(detectOSAwareHermesCommand(tempFolder.root, "", hermesV1Enabled = true))
.isEqualTo(expected.toString())
}
@Test(expected = IllegalStateException::class)
@WithOs(OS.MAC)
fun detectOSAwareHermesCommand_failsIfNotFound() {
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/metro-config",
"version": "0.82.0-main",
"version": "0.82.0",
"description": "Metro configuration for React Native.",
"license": "MIT",
"repository": {
@@ -26,8 +26,8 @@
"dist"
],
"dependencies": {
"@react-native/js-polyfills": "0.82.0-main",
"@react-native/metro-babel-transformer": "0.82.0-main",
"@react-native/js-polyfills": "0.82.0",
"@react-native/metro-babel-transformer": "0.82.0",
"metro-config": "^0.83.1",
"metro-runtime": "^0.83.1"
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/new-app-screen",
"version": "0.82.0-main",
"version": "0.82.0",
"description": "NewAppScreen component for React Native",
"keywords": [
"react-native"
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/normalize-colors",
"version": "0.82.0-main",
"version": "0.82.0",
"description": "Color normalization for React Native.",
"license": "MIT",
"repository": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/js-polyfills",
"version": "0.82.0-main",
"version": "0.82.0",
"description": "Polyfills for React Native.",
"license": "MIT",
"repository": {
@@ -1,6 +1,6 @@
{
"name": "@react-native/babel-preset",
"version": "0.82.0-main",
"version": "0.82.0",
"description": "Babel preset for React Native applications",
"repository": {
"type": "git",
@@ -66,7 +66,7 @@
"@babel/plugin-transform-typescript": "^7.25.2",
"@babel/plugin-transform-unicode-regex": "^7.24.7",
"@babel/template": "^7.25.0",
"@react-native/babel-plugin-codegen": "0.82.0-main",
"@react-native/babel-plugin-codegen": "0.82.0",
"babel-plugin-syntax-hermes-parser": "0.32.0",
"babel-plugin-transform-flow-enums": "^0.0.2",
"react-refresh": "^0.14.0"
@@ -1,6 +1,6 @@
{
"name": "@react-native/metro-babel-transformer",
"version": "0.82.0-main",
"version": "0.82.0",
"description": "Babel transformer for React Native applications.",
"repository": {
"type": "git",
@@ -27,7 +27,7 @@
],
"dependencies": {
"@babel/core": "^7.25.2",
"@react-native/babel-preset": "0.82.0-main",
"@react-native/babel-preset": "0.82.0",
"hermes-parser": "0.32.0",
"nullthrows": "^1.1.1"
},
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/codegen",
"version": "0.82.0-main",
"version": "0.82.0",
"description": "Code generation tools for React Native",
"license": "MIT",
"repository": {
@@ -1,6 +1,6 @@
{
"name": "@react-native/compatibility-check",
"version": "0.82.0-main",
"version": "0.82.0",
"description": "Check a React Native app's boundary between JS and Native for incompatibilities",
"license": "MIT",
"repository": {
@@ -29,7 +29,7 @@
"dist"
],
"dependencies": {
"@react-native/codegen": "0.82.0-main"
"@react-native/codegen": "0.82.0"
},
"devDependencies": {
"flow-remove-types": "^2.237.2",
@@ -1,6 +1,6 @@
{
"name": "@react-native/popup-menu-android",
"version": "0.82.0-main",
"version": "0.82.0",
"description": "PopupMenu for the Android platform",
"main": "index.js",
"files": [
@@ -21,7 +21,7 @@
},
"license": "MIT",
"devDependencies": {
"@react-native/codegen": "0.82.0-main"
"@react-native/codegen": "0.82.0"
},
"peerDependencies": {
"@types/react": "^19.1.0",
@@ -873,56 +873,6 @@ describe('Animated', () => {
});
});
describe('Animated Interactions', () => {
let Animated; // eslint-disable-line no-shadow
let InteractionManager;
beforeEach(() => {
jest.mock('../../Interaction/InteractionManager');
Animated = require('../Animated').default;
InteractionManager =
require('../../Interaction/InteractionManager').default;
});
afterEach(() => {
jest.unmock('../../Interaction/InteractionManager');
});
it('registers an interaction by default', () => {
// $FlowFixMe[prop-missing]
InteractionManager.createInteractionHandle.mockReturnValue(777);
const value = new Animated.Value(0);
const callback = jest.fn();
Animated.timing(value, {
toValue: 100,
duration: 100,
useNativeDriver: false,
}).start(callback);
jest.runAllTimers();
expect(InteractionManager.createInteractionHandle).toBeCalled();
expect(InteractionManager.clearInteractionHandle).toBeCalledWith(777);
expect(callback).toBeCalledWith({finished: true});
});
it('does not register an interaction when specified', () => {
const value = new Animated.Value(0);
const callback = jest.fn();
Animated.timing(value, {
toValue: 100,
duration: 100,
isInteraction: false,
useNativeDriver: false,
}).start(callback);
jest.runAllTimers();
expect(InteractionManager.createInteractionHandle).not.toBeCalled();
expect(InteractionManager.clearInteractionHandle).not.toBeCalled();
expect(callback).toBeCalledWith({finished: true});
});
});
describe('Animated Tracking', () => {
it('should track values', () => {
const value1 = new Animated.Value(0);
@@ -18,7 +18,6 @@ import type {AnimatedNodeConfig} from './AnimatedNode';
import type AnimatedTracking from './AnimatedTracking';
import NativeAnimatedHelper from '../../../src/private/animated/NativeAnimatedHelper';
import InteractionManager from '../../Interaction/InteractionManager';
import AnimatedInterpolation from './AnimatedInterpolation';
import AnimatedWithChildren from './AnimatedWithChildren';
@@ -312,10 +311,6 @@ export default class AnimatedValue extends AnimatedWithChildren {
* See https://reactnative.dev/docs/animatedvalue#animate
*/
animate(animation: Animation, callback: ?EndCallback): void {
let handle = null;
if (animation.__isInteraction) {
handle = InteractionManager.createInteractionHandle();
}
const previousAnimation = this._animation;
this._animation && this._animation.stop();
this._animation = animation;
@@ -328,9 +323,6 @@ export default class AnimatedValue extends AnimatedWithChildren {
},
result => {
this._animation = null;
if (handle !== null) {
InteractionManager.clearInteractionHandle(handle);
}
callback && callback(result);
},
previousAnimation,
@@ -6,6 +6,7 @@
*
* @flow strict
* @format
* @deprecated
*/
'use strict';
@@ -6,6 +6,7 @@
*
* @flow strict
* @format
* @deprecated
*/
'use strict';
@@ -264,7 +264,7 @@ const Switch: component(
disabled,
onTintColor: trackColorForTrue,
style: StyleSheet.compose(
{height: 31, width: 51},
{alignSelf: 'flex-start' as const},
StyleSheet.compose(
style,
ios_backgroundColor == null
+2 -2
View File
@@ -26,8 +26,8 @@
* ```
*/
export default class ReactNativeVersion {
static major: number = 1000;
static minor: number = 0;
static major: number = 0;
static minor: number = 82;
static patch: number = 0;
static prerelease: string | null = null;
@@ -6,6 +6,7 @@
*
* @flow
* @format
* @deprecated
*/
import NativeTiming from './NativeTiming';
@@ -6,6 +6,7 @@
*
* @flow strict
* @format
* @deprecated
*/
export * from '../../../src/private/specs_DEPRECATED/modules/NativeTiming';
@@ -6,6 +6,7 @@
*
* @flow
* @format
* @deprecated
*/
'use strict';
+3 -5
View File
@@ -4,19 +4,17 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @flow strict-local
* @format
*/
import setUpPerformanceModern from '../../src/private/setup/setUpPerformanceModern';
import NativePerformance from '../../src/private/webapis/performance/specs/NativePerformance';
// In case if the native implementation of the Performance API is available, use it,
// otherwise fall back to the legacy/default one, which only defines 'Performance.now()'
if (NativePerformance) {
const Performance =
require('../../src/private/webapis/performance/Performance').default;
// $FlowExpectedError[cannot-write]
global.performance = new Performance();
setUpPerformanceModern();
} else {
if (!global.performance) {
// $FlowExpectedError[cannot-write]
+6 -51
View File
@@ -12,7 +12,6 @@
import type {GestureResponderEvent} from '../Types/CoreEventTypes';
const InteractionManager = require('./InteractionManager').default;
const TouchHistoryMath = require('./TouchHistoryMath').default;
const currentCentroidXOfTouchesChangedAfter =
@@ -31,9 +30,6 @@ const currentCentroidY = TouchHistoryMath.currentCentroidY;
* single-touch gestures resilient to extra touches, and can be used to
* recognize simple multi-touch gestures.
*
* By default, `PanResponder` holds an `InteractionManager` handle to block
* long-running JS events from interrupting active gestures.
*
* It provides a predictable wrapper of the responder handlers provided by the
* [gesture responder system](docs/gesture-responder-system.html).
* For each handler, it provides a new `gestureState` object alongside the
@@ -405,9 +401,6 @@ const PanResponder = {
getInteractionHandle: () => ?number,
panHandlers: GestureResponderHandlerMethods,
} {
const interactionState = {
handle: (null: ?number),
};
const gestureState: PanResponderGestureState = {
// Useful for debugging
stateID: Math.random(),
@@ -464,10 +457,6 @@ const PanResponder = {
},
onResponderGrant(event: GestureResponderEvent): boolean {
if (!interactionState.handle) {
interactionState.handle =
InteractionManager.createInteractionHandle();
}
gestureState.x0 = currentCentroidX(event.touchHistory);
gestureState.y0 = currentCentroidY(event.touchHistory);
gestureState.dx = 0;
@@ -482,21 +471,11 @@ const PanResponder = {
},
onResponderReject(event: GestureResponderEvent): void {
clearInteractionHandle(
interactionState,
config.onPanResponderReject,
event,
gestureState,
);
config.onPanResponderReject?.call(undefined, event, gestureState);
},
onResponderRelease(event: GestureResponderEvent): void {
clearInteractionHandle(
interactionState,
config.onPanResponderRelease,
event,
gestureState,
);
config.onPanResponderRelease?.call(undefined, event, gestureState);
PanResponder._initializeGestureState(gestureState);
},
@@ -529,21 +508,11 @@ const PanResponder = {
onResponderEnd(event: GestureResponderEvent): void {
const touchHistory = event.touchHistory;
gestureState.numberActiveTouches = touchHistory.numberActiveTouches;
clearInteractionHandle(
interactionState,
config.onPanResponderEnd,
event,
gestureState,
);
config.onPanResponderEnd?.call(undefined, event, gestureState);
},
onResponderTerminate(event: GestureResponderEvent): void {
clearInteractionHandle(
interactionState,
config.onPanResponderTerminate,
event,
gestureState,
);
config.onPanResponderTerminate?.call(undefined, event, gestureState);
PanResponder._initializeGestureState(gestureState);
},
@@ -556,27 +525,13 @@ const PanResponder = {
return {
panHandlers,
getInteractionHandle(): ?number {
return interactionState.handle;
// TODO: Deprecate and delete this method.
return null;
},
};
},
};
function clearInteractionHandle(
interactionState: {handle: ?number, ...},
callback: ?(ActiveCallback | PassiveCallback),
event: GestureResponderEvent,
gestureState: PanResponderGestureState,
) {
if (interactionState.handle) {
InteractionManager.clearInteractionHandle(interactionState.handle);
interactionState.handle = null;
}
if (callback) {
callback(event, gestureState);
}
}
export type PanResponderInstance = ReturnType<(typeof PanResponder)['create']>;
export default PanResponder;
+9
View File
@@ -304,6 +304,13 @@ let reactIdleCallbacksNativeModule = RNTarget(
dependencies: [.reactNativeDependencies, .reactDebug, .reactFeatureFlags, .reactUtils, .reactPerfLogger, .reactCxxReact, .reactTurboModuleCore]
)
/// React-webperformance.podspec
let reactWebPerformanceNativeModule = RNTarget(
name: .reactWebPerformanceNativeModule,
path: "ReactCommon/react/nativemodule/webperformance",
dependencies: [.reactNativeDependencies, .reactCxxReact, .reactTurboModuleCore, .reactPerformanceTimeline]
)
/// React-featureflagnativemodule.podspec
let reactFeatureflagsNativemodule = RNTarget(
name: .reactFeatureflagsNativemodule,
@@ -590,6 +597,7 @@ let targets = [
reactTurboModuleCoreDefaults,
reactTurboModuleCoreMicrotasks,
reactIdleCallbacksNativeModule,
reactWebPerformanceNativeModule,
reactFeatureflagsNativemodule,
reactNativeModuleDom,
reactAppDelegate,
@@ -764,6 +772,7 @@ extension String {
static let reactTurboModuleCoreDefaults = "ReactCommon/turbomodule/core/defaults"
static let reactTurboModuleCoreMicrotasks = "ReactCommon/turbomodule/core/microtasks"
static let reactIdleCallbacksNativeModule = "React-idlecallbacksnativemodule"
static let reactWebPerformanceNativeModule = "React-webperformancenativemodule"
static let reactFeatureflagsNativemodule = "React-featureflagsnativemodule"
static let reactNativeModuleDom = "React-domnativemodule"
static let reactAppDelegate = "React-RCTAppDelegate"
@@ -380,6 +380,11 @@ static RCTBridge *RCTCurrentBridgeInstance = nil;
moduleProvider:(RCTBridgeModuleListProvider)block
launchOptions:(NSDictionary *)launchOptions
{
// Only enabld this assertion in OSS
#if COCOAPODS
[RCTBridge throwIfOnLegacyArch];
#endif
if (self = [super init]) {
RCTEnforceNewArchitectureValidation(RCTNotAllowedInBridgeless, self, nil);
_delegate = delegate;
@@ -393,6 +398,17 @@ static RCTBridge *RCTCurrentBridgeInstance = nil;
return self;
}
// Wrap the exception throwing in a static method to avoid the warning: "The code following the exception will never be
// executed". This might create build failures internally where we treat warnings as errors.
+ (void)throwIfOnLegacyArch
{
@throw [NSException
exceptionWithName:NSInternalInconsistencyException
reason:
@"You are trying to initialize the legacy architecture. This is not supported anymore and will be removed in the next version of React Native. Please use the New Architecture instead."
userInfo:nil];
}
RCT_NOT_IMPLEMENTED(-(instancetype)init)
- (void)dealloc
@@ -21,8 +21,8 @@ NSDictionary* RCTGetReactNativeVersion(void)
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^(void){
__rnVersion = @{
RCTVersionMajor: @(1000),
RCTVersionMinor: @(0),
RCTVersionMajor: @(0),
RCTVersionMinor: @(82),
RCTVersionPatch: @(0),
RCTVersionPrerelease: [NSNull null],
};
@@ -20,7 +20,12 @@
- (UIWindow *)alertWindow
{
if (_alertWindow == nil) {
_alertWindow = [[UIWindow alloc] initWithWindowScene:RCTKeyWindow().windowScene];
UIWindowScene *scene = RCTKeyWindow().windowScene;
if (scene != nil) {
_alertWindow = [[UIWindow alloc] initWithWindowScene:scene];
} else {
_alertWindow = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
}
if (_alertWindow) {
_alertWindow.rootViewController = [UIViewController new];
@@ -111,6 +111,12 @@ typedef NS_OPTIONS(NSInteger, RNComponentViewUpdateMask) {
*/
- (void)prepareForRecycle;
/*
* Called for unmounted components that won't be moved to a recycle pool.
* Useful for releasing any associated resources.
*/
- (void)invalidate;
/*
* Read the last props used to update the view.
*/
@@ -108,6 +108,7 @@ const NSInteger RCTComponentViewRegistryRecyclePoolMaxSize = 1024;
auto &recycledViews = _recyclePool[componentHandle];
if (recycledViews.size() > RCTComponentViewRegistryRecyclePoolMaxSize || !componentViewDescriptor.shouldBeRecycled) {
[componentViewDescriptor.view invalidate];
return;
}
@@ -37,6 +37,8 @@ NS_ASSUME_NONNULL_BEGIN
- (void)prepareForRecycle;
- (void)invalidate;
- (facebook::react::Props::Shared)props;
- (void)setIsJSResponder:(BOOL)isJSResponder;
@@ -129,6 +129,11 @@ using namespace facebook::react;
// Default implementation does nothing.
}
- (void)invalidate
{
// Default implementation does nothing.
}
- (facebook::react::Props::Shared)props
{
RCTAssert(NO, @"props access should be implemented by RCTViewComponentView.");
@@ -39,6 +39,9 @@ val downloadsDir =
val thirdPartyNdkDir = File("$buildDir/third-party-ndk")
val reactNativeRootDir = projectDir.parent
val hermesV1Enabled =
rootProject.extensions.getByType(PrivateReactExtension::class.java).hermesV1Enabled.get()
// We put the publishing version from gradle.properties inside ext. so other
// subprojects can access it as well.
extra["publishing_version"] = project.findProperty("VERSION_NAME")?.toString()!!
@@ -565,6 +568,10 @@ android {
"-DCMAKE_POLICY_DEFAULT_CMP0069=NEW",
)
if (hermesV1Enabled) {
arguments("-DHERMES_V1_ENABLED=1")
}
targets(
"reactnative",
"jsi",
@@ -1,5 +1,6 @@
VERSION_NAME=1000.0.0
VERSION_NAME=0.82.0
react.internal.publishingGroup=com.facebook.react
react.internal.hermesPublishingGroup=com.facebook.hermes
android.useAndroidX=true
@@ -5,6 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/
import com.facebook.react.internal.PrivateReactExtension
import com.facebook.react.tasks.internal.*
import de.undercouch.gradle.tasks.download.Download
import org.apache.tools.ant.taskdefs.condition.Os
@@ -50,6 +51,8 @@ fun getSDKManagerPath(): String {
}
}
val hermesV1Enabled =
rootProject.extensions.getByType(PrivateReactExtension::class.java).hermesV1Enabled.get()
val reactNativeRootDir = project(":packages:react-native:ReactAndroid").projectDir.parent
val customDownloadDir = System.getenv("REACT_NATIVE_DOWNLOADS_DIR")
val downloadsDir =
@@ -79,12 +82,21 @@ val hermesBuildOutputFileTree =
fileTree(hermesBuildDir.toString())
.include("**/*.cmake", "**/*.marks", "**/compiler_depends.ts", "**/Makefile", "**/link.txt")
var hermesVersion = "main"
val hermesVersionFile = File(reactNativeRootDir, "sdks/.hermesversion")
val hermesVersionProvider: Provider<String> =
providers.provider {
var hermesVersion = if (hermesV1Enabled) "250829098.0.0-stable" else "main"
val hermesVersionFile =
File(
reactNativeRootDir,
if (hermesV1Enabled) "sdks/.hermesv1version" else "sdks/.hermesversion",
)
if (hermesVersionFile.exists()) {
hermesVersion = hermesVersionFile.readText()
}
if (hermesVersionFile.exists()) {
hermesVersion = hermesVersionFile.readText()
}
hermesVersion
}
val ndkBuildJobs = Runtime.getRuntime().availableProcessors().toString()
val prefabHeadersDir = File("$buildDir/prefab-headers")
@@ -95,7 +107,11 @@ val jsiDir = File(reactNativeRootDir, "ReactCommon/jsi")
val downloadHermesDest = File(downloadsDir, "hermes.tar.gz")
val downloadHermes by
tasks.registering(Download::class) {
src("https://github.com/facebook/hermes/tarball/${hermesVersion}")
src(
providers.provider {
"https://github.com/facebook/hermes/tarball/${hermesVersionProvider.get()}"
}
)
onlyIfModified(true)
overwrite(true)
quiet(true)
@@ -151,6 +167,7 @@ val configureBuildForHermes by
"-B",
hermesBuildDir.toString(),
"-DJSI_DIR=" + jsiDir.absolutePath,
"-DCMAKE_BUILD_TYPE=Release",
)
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
cmakeCommandLine = cmakeCommandLine + "-GNMake Makefiles"
@@ -295,7 +312,11 @@ android {
// Therefore we're passing as build type Release, to provide a faster build.
// This has the (unlucky) side effect of letting AGP call the build
// tasks `configureCMakeRelease` while is actually building the debug flavor.
arguments("-DCMAKE_BUILD_TYPE=Release")
arguments(
"-DCMAKE_BUILD_TYPE=Release",
// For debug builds, explicitly enable the Hermes Debugger.
"-DHERMES_ENABLE_DEBUGGER=True",
)
}
}
}
@@ -328,6 +328,15 @@ public class ReactInstanceManager {
}
registerCxxErrorHandlerFunc();
// Using `if (true)` just to prevent tests / lint errors.
if (true) {
// Legacy architecture of React Native is deprecated and can't be initialized anymore.
// More details on:
// https://github.com/react-native-community/discussions-and-proposals/blob/nc/legacy-arch-removal/proposals/0929-legacy-architecture-removal.md
throw new UnsupportedOperationException(
"ReactInstanceManager.createReactContext is unsupported.");
}
}
private ReactInstanceDevHelper createDevHelperInterface() {
@@ -1446,6 +1455,7 @@ public class ReactInstanceManager {
*/
private ReactApplicationContext createReactContext(
JavaScriptExecutor jsExecutor, JSBundleLoader jsBundleLoader) {
FLog.d(ReactConstants.TAG, "ReactInstanceManager.createReactContext()");
ReactMarker.logMarker(CREATE_REACT_CONTEXT_START, jsExecutor.getName());
@@ -125,6 +125,16 @@ public object DefaultNewArchitectureEntryPoint {
privateConcurrentReactEnabled = featureFlags.enableFabricRenderer()
privateBridgelessEnabled = featureFlags.enableBridgelessArchitecture()
val (isValid, errorMessage) =
isConfigurationValid(
privateTurboModulesEnabled,
privateFabricEnabled,
privateBridgelessEnabled,
)
if (!isValid) {
error(errorMessage)
}
DefaultSoLoader.maybeLoadSoLibrary()
}
@@ -158,13 +168,13 @@ public object DefaultNewArchitectureEntryPoint {
fabricEnabled: Boolean,
bridgelessEnabled: Boolean,
): Pair<Boolean, String> =
when {
fabricEnabled && !turboModulesEnabled ->
false to
"fabricEnabled=true requires turboModulesEnabled=true (is now false) - Please update your DefaultNewArchitectureEntryPoint.load() parameters."
bridgelessEnabled && (!turboModulesEnabled || !fabricEnabled) ->
false to
"bridgelessEnabled=true requires (turboModulesEnabled=true AND fabricEnabled=true) - Please update your DefaultNewArchitectureEntryPoint.load() parameters."
else -> true to ""
if (!turboModulesEnabled || !fabricEnabled || !bridgelessEnabled) {
false to
"You cannot load React Native with the New Architecture disabled. " +
"Please use DefaultNewArchitectureEntryPoint.load() instead of " +
"DefaultNewArchitectureEntryPoint.load(turboModulesEnabled=$turboModulesEnabled, " +
"fabricEnabled=$fabricEnabled, bridgelessEnabled=$bridgelessEnabled)"
} else {
true to ""
}
}
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<34c12f5a31aab5bfb874953f1beefef1>>
* @generated SignedSource<<2ecd46fdcab0202d62304dd9cdff76e0>>
*/
/**
@@ -294,6 +294,12 @@ public object ReactNativeFeatureFlags {
@JvmStatic
public fun enableVirtualViewWindowFocusDetection(): Boolean = accessor.enableVirtualViewWindowFocusDetection()
/**
* Enable Web Performance APIs (Performance Timeline, User Timings, etc.) by default.
*/
@JvmStatic
public fun enableWebPerformanceAPIsByDefault(): Boolean = accessor.enableWebPerformanceAPIsByDefault()
/**
* Uses the default event priority instead of the discreet event priority by default when dispatching events from Fabric to React.
*/
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<392da016e0bf4193b72c44a508811e10>>
* @generated SignedSource<<3cbd83777e0840419fee9d582b4da692>>
*/
/**
@@ -64,6 +64,7 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
private var enableVirtualViewDebugFeaturesCache: Boolean? = null
private var enableVirtualViewRenderStateCache: Boolean? = null
private var enableVirtualViewWindowFocusDetectionCache: Boolean? = null
private var enableWebPerformanceAPIsByDefaultCache: Boolean? = null
private var fixMappingOfEventPrioritiesBetweenFabricAndReactCache: Boolean? = null
private var fuseboxEnabledReleaseCache: Boolean? = null
private var fuseboxNetworkInspectionEnabledCache: Boolean? = null
@@ -486,6 +487,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
return cached
}
override fun enableWebPerformanceAPIsByDefault(): Boolean {
var cached = enableWebPerformanceAPIsByDefaultCache
if (cached == null) {
cached = ReactNativeFeatureFlagsCxxInterop.enableWebPerformanceAPIsByDefault()
enableWebPerformanceAPIsByDefaultCache = cached
}
return cached
}
override fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean {
var cached = fixMappingOfEventPrioritiesBetweenFabricAndReactCache
if (cached == null) {
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<a0453230524ebca2bfb8fad656a6f54a>>
* @generated SignedSource<<b92c1fc5d527033d0f7988d88533eb03>>
*/
/**
@@ -116,6 +116,8 @@ public object ReactNativeFeatureFlagsCxxInterop {
@DoNotStrip @JvmStatic public external fun enableVirtualViewWindowFocusDetection(): Boolean
@DoNotStrip @JvmStatic public external fun enableWebPerformanceAPIsByDefault(): Boolean
@DoNotStrip @JvmStatic public external fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean
@DoNotStrip @JvmStatic public external fun fuseboxEnabledRelease(): Boolean
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<719706a983a073b6c286c49d993f7f80>>
* @generated SignedSource<<71354bd41b222239b80129659f5f5d21>>
*/
/**
@@ -111,6 +111,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
override fun enableVirtualViewWindowFocusDetection(): Boolean = false
override fun enableWebPerformanceAPIsByDefault(): Boolean = false
override fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean = false
override fun fuseboxEnabledRelease(): Boolean = false
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<594815ba6a984c460ab8bddd91c5cae2>>
* @generated SignedSource<<4ad6fc15663277c2c8b4843f42a078f8>>
*/
/**
@@ -68,6 +68,7 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
private var enableVirtualViewDebugFeaturesCache: Boolean? = null
private var enableVirtualViewRenderStateCache: Boolean? = null
private var enableVirtualViewWindowFocusDetectionCache: Boolean? = null
private var enableWebPerformanceAPIsByDefaultCache: Boolean? = null
private var fixMappingOfEventPrioritiesBetweenFabricAndReactCache: Boolean? = null
private var fuseboxEnabledReleaseCache: Boolean? = null
private var fuseboxNetworkInspectionEnabledCache: Boolean? = null
@@ -534,6 +535,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
return cached
}
override fun enableWebPerformanceAPIsByDefault(): Boolean {
var cached = enableWebPerformanceAPIsByDefaultCache
if (cached == null) {
cached = currentProvider.enableWebPerformanceAPIsByDefault()
accessedFeatureFlags.add("enableWebPerformanceAPIsByDefault")
enableWebPerformanceAPIsByDefaultCache = cached
}
return cached
}
override fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean {
var cached = fixMappingOfEventPrioritiesBetweenFabricAndReactCache
if (cached == null) {
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<f82b5905d822f8009c054a9443f86e39>>
* @generated SignedSource<<4464982256b8ce543d9235fccbf67054>>
*/
/**
@@ -27,6 +27,8 @@ public open class ReactNativeFeatureFlagsOverrides_RNOSS_Canary_Android : ReactN
override fun enableFabricRenderer(): Boolean = true
override fun enableWebPerformanceAPIsByDefault(): Boolean = true
override fun useNativeViewConfigsInBridgelessMode(): Boolean = true
override fun useTurboModuleInterop(): Boolean = true
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<dfbd5e84392f1fda0e68324582c328b2>>
* @generated SignedSource<<51e9b65c32aa4a990f21afd4f0244223>>
*/
/**
@@ -111,6 +111,8 @@ public interface ReactNativeFeatureFlagsProvider {
@DoNotStrip public fun enableVirtualViewWindowFocusDetection(): Boolean
@DoNotStrip public fun enableWebPerformanceAPIsByDefault(): Boolean
@DoNotStrip public fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean
@DoNotStrip public fun fuseboxEnabledRelease(): Boolean
@@ -1,15 +1,20 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE file in the root
* directory of this source tree.
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated by scripts/releases/set-version.js
*/
package com.facebook.react.modules.systeminfo
public object ReactNativeVersion {
@JvmField
public val VERSION: Map<String, Any?> =
mapOf("major" to 1000, "minor" to 0, "patch" to 0, "prerelease" to null)
public val VERSION: Map<String, Any?> = mapOf(
"major" to 0,
"minor" to 82,
"patch" to 0,
"prerelease" to null
)
}
@@ -22,6 +22,8 @@ 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)
set(HERMES_V1_ENABLED OFF CACHE BOOL "Build with support for Hermes v1")
# If you have ccache installed, we're going to honor it.
find_program(CCACHE_FOUND ccache)
if(CCACHE_FOUND)
@@ -122,6 +124,7 @@ add_react_common_subdir(react/nativemodule/dom)
add_react_common_subdir(react/nativemodule/featureflags)
add_react_common_subdir(react/nativemodule/microtasks)
add_react_common_subdir(react/nativemodule/idlecallbacks)
add_react_common_subdir(react/nativemodule/webperformance)
add_react_common_subdir(jserrorhandler)
add_react_common_subdir(react/runtime)
add_react_common_subdir(react/runtime/hermes)
@@ -188,6 +191,7 @@ add_library(reactnative
$<TARGET_OBJECTS:react_nativemodule_featureflags>
$<TARGET_OBJECTS:react_nativemodule_idlecallbacks>
$<TARGET_OBJECTS:react_nativemodule_microtasks>
$<TARGET_OBJECTS:react_nativemodule_webperformance>
$<TARGET_OBJECTS:react_newarchdefaults>
$<TARGET_OBJECTS:react_performance_cdpmetrics>
$<TARGET_OBJECTS:react_performance_timeline>
@@ -277,6 +281,7 @@ target_include_directories(reactnative
$<TARGET_PROPERTY:react_nativemodule_featureflags,INTERFACE_INCLUDE_DIRECTORIES>
$<TARGET_PROPERTY:react_nativemodule_idlecallbacks,INTERFACE_INCLUDE_DIRECTORIES>
$<TARGET_PROPERTY:react_nativemodule_microtasks,INTERFACE_INCLUDE_DIRECTORIES>
$<TARGET_PROPERTY:react_nativemodule_webperformance,INTERFACE_INCLUDE_DIRECTORIES>
$<TARGET_PROPERTY:react_newarchdefaults,INTERFACE_INCLUDE_DIRECTORIES>
$<TARGET_PROPERTY:react_performance_cdpmetrics,INTERFACE_INCLUDE_DIRECTORIES>
$<TARGET_PROPERTY:react_performance_timeline,INTERFACE_INCLUDE_DIRECTORIES>
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<16b12024bb363358ef09b9a42cb2fc97>>
* @generated SignedSource<<f4ec3b7b6f99dd3409d872470872ece6>>
*/
/**
@@ -303,6 +303,12 @@ class ReactNativeFeatureFlagsJavaProvider
return method(javaProvider_);
}
bool enableWebPerformanceAPIsByDefault() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableWebPerformanceAPIsByDefault");
return method(javaProvider_);
}
bool fixMappingOfEventPrioritiesBetweenFabricAndReact() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("fixMappingOfEventPrioritiesBetweenFabricAndReact");
@@ -677,6 +683,11 @@ bool JReactNativeFeatureFlagsCxxInterop::enableVirtualViewWindowFocusDetection(
return ReactNativeFeatureFlags::enableVirtualViewWindowFocusDetection();
}
bool JReactNativeFeatureFlagsCxxInterop::enableWebPerformanceAPIsByDefault(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::enableWebPerformanceAPIsByDefault();
}
bool JReactNativeFeatureFlagsCxxInterop::fixMappingOfEventPrioritiesBetweenFabricAndReact(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::fixMappingOfEventPrioritiesBetweenFabricAndReact();
@@ -965,6 +976,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
makeNativeMethod(
"enableVirtualViewWindowFocusDetection",
JReactNativeFeatureFlagsCxxInterop::enableVirtualViewWindowFocusDetection),
makeNativeMethod(
"enableWebPerformanceAPIsByDefault",
JReactNativeFeatureFlagsCxxInterop::enableWebPerformanceAPIsByDefault),
makeNativeMethod(
"fixMappingOfEventPrioritiesBetweenFabricAndReact",
JReactNativeFeatureFlagsCxxInterop::fixMappingOfEventPrioritiesBetweenFabricAndReact),
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<54118ccd475a8bf1d7db83304b1f17d0>>
* @generated SignedSource<<d34119ad2e9a068463e8a31ecced59d9>>
*/
/**
@@ -162,6 +162,9 @@ class JReactNativeFeatureFlagsCxxInterop
static bool enableVirtualViewWindowFocusDetection(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static bool enableWebPerformanceAPIsByDefault(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static bool fixMappingOfEventPrioritiesBetweenFabricAndReact(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
@@ -27,4 +27,8 @@ target_link_libraries(
target_compile_reactnative_options(hermes_executor PRIVATE)
if(${CMAKE_BUILD_TYPE} MATCHES Debug OR REACT_NATIVE_DEBUG_OPTIMIZED)
target_compile_options(hermes_executor PRIVATE -DHERMES_ENABLE_DEBUGGER=1)
if (HERMES_V1_ENABLED)
target_compile_options(hermes_executor PRIVATE -DHERMES_V1_ENABLED=1)
endif()
endif()
@@ -29,4 +29,8 @@ target_link_libraries(hermesinstancejni
target_compile_reactnative_options(hermesinstancejni PRIVATE)
if(${CMAKE_BUILD_TYPE} MATCHES Debug OR REACT_NATIVE_DEBUG_OPTIMIZED)
target_compile_options(hermesinstancejni PRIVATE -DHERMES_ENABLE_DEBUGGER=1)
if (HERMES_V1_ENABLED)
target_compile_options(hermesinstancejni PRIVATE -DHERMES_V1_ENABLED=1)
endif()
endif ()
@@ -19,6 +19,10 @@ add_library(rninstance
target_compile_reactnative_options(rninstance PRIVATE)
if(${CMAKE_BUILD_TYPE} MATCHES Debug OR REACT_NATIVE_DEBUG_OPTIMIZED)
target_compile_options(rninstance PRIVATE -DHERMES_ENABLE_DEBUGGER=1)
if (HERMES_V1_ENABLED)
target_compile_options(rninstance PRIVATE -DHERMES_V1_ENABLED=1)
endif()
endif ()
target_merge_so(rninstance)
@@ -13,36 +13,48 @@ import org.junit.Test
class DefaultNewArchitectureEntryPointTest {
@Test
fun isConfigurationValid_withEverythingOff_returnsTrue() {
val (isValid, _) =
fun isConfigurationValid_withEverythingOff_returnsFalse() {
val (isValid, errorMessage) =
DefaultNewArchitectureEntryPoint.isConfigurationValid(
turboModulesEnabled = false,
fabricEnabled = false,
bridgelessEnabled = false,
)
assertThat(isValid).isTrue()
assertThat(isValid).isFalse()
assertThat(errorMessage)
.isEqualTo(
"You cannot load React Native with the New Architecture disabled. Please use DefaultNewArchitectureEntryPoint.load() instead of DefaultNewArchitectureEntryPoint.load(turboModulesEnabled=false, fabricEnabled=false, bridgelessEnabled=false)"
)
}
@Test
fun isConfigurationValid_withNewArchOn_returnsTrue() {
val (isValid, _) =
fun isConfigurationValid_withNewArchOnlyOn_returnsFalse() {
val (isValid, errorMessage) =
DefaultNewArchitectureEntryPoint.isConfigurationValid(
turboModulesEnabled = true,
fabricEnabled = true,
bridgelessEnabled = false,
)
assertThat(isValid).isTrue()
assertThat(isValid).isFalse()
assertThat(errorMessage)
.isEqualTo(
"You cannot load React Native with the New Architecture disabled. Please use DefaultNewArchitectureEntryPoint.load() instead of DefaultNewArchitectureEntryPoint.load(turboModulesEnabled=true, fabricEnabled=true, bridgelessEnabled=false)"
)
}
@Test
fun isConfigurationValid_withTurboModulesOnlyOn_returnsTrue() {
val (isValid, _) =
fun isConfigurationValid_withTurboModulesOnlyOn_returnsFalse() {
val (isValid, errorMessage) =
DefaultNewArchitectureEntryPoint.isConfigurationValid(
turboModulesEnabled = true,
fabricEnabled = false,
bridgelessEnabled = false,
)
assertThat(isValid).isTrue()
assertThat(isValid).isFalse()
assertThat(errorMessage)
.isEqualTo(
"You cannot load React Native with the New Architecture disabled. Please use DefaultNewArchitectureEntryPoint.load() instead of DefaultNewArchitectureEntryPoint.load(turboModulesEnabled=true, fabricEnabled=false, bridgelessEnabled=false)"
)
}
@Test
@@ -67,7 +79,7 @@ class DefaultNewArchitectureEntryPointTest {
assertThat(isValid).isFalse()
assertThat(errorMessage)
.isEqualTo(
"fabricEnabled=true requires turboModulesEnabled=true (is now false) - Please update your DefaultNewArchitectureEntryPoint.load() parameters."
"You cannot load React Native with the New Architecture disabled. Please use DefaultNewArchitectureEntryPoint.load() instead of DefaultNewArchitectureEntryPoint.load(turboModulesEnabled=false, fabricEnabled=true, bridgelessEnabled=false)"
)
}
@@ -82,7 +94,7 @@ class DefaultNewArchitectureEntryPointTest {
assertThat(isValid).isFalse()
assertThat(errorMessage)
.isEqualTo(
"fabricEnabled=true requires turboModulesEnabled=true (is now false) - Please update your DefaultNewArchitectureEntryPoint.load() parameters."
"You cannot load React Native with the New Architecture disabled. Please use DefaultNewArchitectureEntryPoint.load() instead of DefaultNewArchitectureEntryPoint.load(turboModulesEnabled=false, fabricEnabled=true, bridgelessEnabled=true)"
)
}
@@ -97,7 +109,7 @@ class DefaultNewArchitectureEntryPointTest {
assertThat(isValid).isFalse()
assertThat(errorMessage)
.isEqualTo(
"bridgelessEnabled=true requires (turboModulesEnabled=true AND fabricEnabled=true) - Please update your DefaultNewArchitectureEntryPoint.load() parameters."
"You cannot load React Native with the New Architecture disabled. Please use DefaultNewArchitectureEntryPoint.load() instead of DefaultNewArchitectureEntryPoint.load(turboModulesEnabled=true, fabricEnabled=false, bridgelessEnabled=true)"
)
}
}
@@ -12,15 +12,15 @@
#include <cstdint>
#include <string_view>
#define REACT_NATIVE_VERSION_MAJOR 1000
#define REACT_NATIVE_VERSION_MINOR 0
#define REACT_NATIVE_VERSION_MAJOR 0
#define REACT_NATIVE_VERSION_MINOR 82
#define REACT_NATIVE_VERSION_PATCH 0
namespace facebook::react {
constexpr struct {
int32_t Major = 1000;
int32_t Minor = 0;
int32_t Major = 0;
int32_t Minor = 82;
int32_t Patch = 0;
std::string_view Prerelease = "";
} ReactNativeVersion;
@@ -32,6 +32,10 @@ if(${CMAKE_BUILD_TYPE} MATCHES Debug OR REACT_NATIVE_DEBUG_OPTIMIZED)
PRIVATE
-DHERMES_ENABLE_DEBUGGER=1
)
if (HERMES_V1_ENABLED)
target_compile_options(hermes_executor_common PRIVATE -DHERMES_V1_ENABLED=1)
endif()
else()
target_compile_options(
hermes_executor_common
@@ -14,8 +14,11 @@
#include <jsinspector-modern/InspectorFlags.h>
#include <hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.h>
#if defined(HERMES_ENABLE_DEBUGGER) && !defined(HERMES_V1_ENABLED)
#include <hermes/inspector-modern/chrome/Registration.h>
#include <hermes/inspector/RuntimeAdapter.h>
#endif
using namespace facebook::hermes;
using namespace facebook::jsi;
@@ -24,7 +27,7 @@ namespace facebook::react {
namespace {
#ifdef HERMES_ENABLE_DEBUGGER
#if defined(HERMES_ENABLE_DEBUGGER) && !defined(HERMES_V1_ENABLED)
class HermesExecutorRuntimeAdapter
: public facebook::hermes::inspector_modern::RuntimeAdapter {
@@ -59,7 +62,7 @@ class HermesExecutorRuntimeAdapter
std::shared_ptr<MessageQueueThread> thread_;
};
#endif // HERMES_ENABLE_DEBUGGER
#endif // defined(HERMES_ENABLE_DEBUGGER) && !defined(HERMES_V1_ENABLED)
struct ReentrancyCheck {
// This is effectively a very subtle and complex assert, so only
@@ -144,7 +147,7 @@ class DecoratedRuntime : public jsi::WithRuntimeDecorator<ReentrancyCheck> {
const std::string& debuggerName)
: jsi::WithRuntimeDecorator<ReentrancyCheck>(*runtime, reentrancyCheck_),
runtime_(std::move(runtime)) {
#ifdef HERMES_ENABLE_DEBUGGER
#if defined(HERMES_ENABLE_DEBUGGER) && !defined(HERMES_V1_ENABLED)
enableDebugger_ = enableDebugger;
if (enableDebugger_) {
std::shared_ptr<HermesRuntime> rt(runtime_, &hermesRuntime);
@@ -159,7 +162,7 @@ class DecoratedRuntime : public jsi::WithRuntimeDecorator<ReentrancyCheck> {
}
~DecoratedRuntime() {
#ifdef HERMES_ENABLE_DEBUGGER
#if defined(HERMES_ENABLE_DEBUGGER) && !defined(HERMES_V1_ENABLED)
if (enableDebugger_) {
facebook::hermes::inspector_modern::chrome::disableDebugging(debugToken_);
}
@@ -176,7 +179,7 @@ class DecoratedRuntime : public jsi::WithRuntimeDecorator<ReentrancyCheck> {
std::shared_ptr<Runtime> runtime_;
ReentrancyCheck reentrancyCheck_;
#ifdef HERMES_ENABLE_DEBUGGER
#if defined(HERMES_ENABLE_DEBUGGER) && !defined(HERMES_V1_ENABLED)
bool enableDebugger_;
facebook::hermes::inspector_modern::chrome::DebugSessionToken debugToken_;
#endif // HERMES_ENABLE_DEBUGGER
@@ -23,6 +23,10 @@ if(${CMAKE_BUILD_TYPE} MATCHES Debug OR REACT_NATIVE_DEBUG_OPTIMIZED)
PRIVATE
-DHERMES_ENABLE_DEBUGGER=1
)
if (HERMES_V1_ENABLED)
target_compile_options(hermes_inspector_modern PRIVATE -DHERMES_V1_ENABLED=1)
endif()
endif()
target_include_directories(hermes_inspector_modern PUBLIC ${REACT_COMMON_DIR})
@@ -7,7 +7,7 @@
#include "ConnectionDemux.h"
#ifdef HERMES_ENABLE_DEBUGGER
#if defined(HERMES_ENABLE_DEBUGGER) && !defined(HERMES_V1_ENABLED)
#include <hermes/inspector/RuntimeAdapter.h>
#include <hermes/inspector/chrome/CDPHandler.h>
@@ -139,4 +139,4 @@ void ConnectionDemux::removePage(int pageId) {
} // namespace facebook::hermes::inspector_modern::chrome
#endif // HERMES_ENABLE_DEBUGGER
#endif // defined(HERMES_ENABLE_DEBUGGER) && !defined(HERMES_V1_ENABLED)
@@ -7,7 +7,7 @@
#pragma once
#ifdef HERMES_ENABLE_DEBUGGER
#if defined(HERMES_ENABLE_DEBUGGER) && !defined(HERMES_V1_ENABLED)
#include <memory>
#include <mutex>
@@ -59,4 +59,4 @@ class ConnectionDemux {
} // namespace facebook::hermes::inspector_modern::chrome
#endif // HERMES_ENABLE_DEBUGGER
#endif // defined(HERMES_ENABLE_DEBUGGER) && !defined(HERMES_V1_ENABLED)
@@ -8,7 +8,7 @@
#include "Registration.h"
#include "ConnectionDemux.h"
#ifdef HERMES_ENABLE_DEBUGGER
#if defined(HERMES_ENABLE_DEBUGGER) && !defined(HERMES_V1_ENABLED)
namespace facebook::hermes::inspector_modern::chrome {
@@ -34,4 +34,4 @@ void disableDebugging(DebugSessionToken session) {
} // namespace facebook::hermes::inspector_modern::chrome
#endif // HERMES_ENABLE_DEBUGGER
#endif // defined(HERMES_ENABLE_DEBUGGER) && !defined(HERMES_V1_ENABLED)
@@ -7,7 +7,7 @@
#pragma once
#ifdef HERMES_ENABLE_DEBUGGER
#if defined(HERMES_ENABLE_DEBUGGER) && !defined(HERMES_V1_ENABLED)
#include <memory>
#include <string>
@@ -38,4 +38,4 @@ extern void disableDebugging(DebugSessionToken session);
} // namespace facebook::hermes::inspector_modern::chrome
#endif // HERMES_ENABLE_DEBUGGER
#endif // defined(HERMES_ENABLE_DEBUGGER) && !defined(HERMES_V1_ENABLED)
@@ -54,6 +54,8 @@ Pod::Spec.new do |s|
add_dependency(s, "React-jsinspectornetwork", :framework_name => 'jsinspector_modernnetwork')
add_dependency(s, "React-jsinspectortracing", :framework_name => 'jsinspector_moderntracing')
s.dependency "React-perflogger", version
add_dependency(s, "React-oscompat")
if use_hermes()
s.dependency "hermes-engine"
end
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<12a06ea04fc09c34f1fbdcbdf6046d81>>
* @generated SignedSource<<ce235bb558df2f110e0446e68cf6bc6a>>
*/
/**
@@ -202,6 +202,10 @@ bool ReactNativeFeatureFlags::enableVirtualViewWindowFocusDetection() {
return getAccessor().enableVirtualViewWindowFocusDetection();
}
bool ReactNativeFeatureFlags::enableWebPerformanceAPIsByDefault() {
return getAccessor().enableWebPerformanceAPIsByDefault();
}
bool ReactNativeFeatureFlags::fixMappingOfEventPrioritiesBetweenFabricAndReact() {
return getAccessor().fixMappingOfEventPrioritiesBetweenFabricAndReact();
}
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<eee81e4e9bb13ef5134d4e2d79876b38>>
* @generated SignedSource<<55cd4ef6cd8902af5c0959077336b0bb>>
*/
/**
@@ -259,6 +259,11 @@ class ReactNativeFeatureFlags {
*/
RN_EXPORT static bool enableVirtualViewWindowFocusDetection();
/**
* Enable Web Performance APIs (Performance Timeline, User Timings, etc.) by default.
*/
RN_EXPORT static bool enableWebPerformanceAPIsByDefault();
/**
* Uses the default event priority instead of the discreet event priority by default when dispatching events from Fabric to React.
*/
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<3c5588a851e6cdefaba22236c5ebb828>>
* @generated SignedSource<<bccad78ad6684e7aeb741e3cbf1b8331>>
*/
/**
@@ -821,6 +821,24 @@ bool ReactNativeFeatureFlagsAccessor::enableVirtualViewWindowFocusDetection() {
return flagValue.value();
}
bool ReactNativeFeatureFlagsAccessor::enableWebPerformanceAPIsByDefault() {
auto flagValue = enableWebPerformanceAPIsByDefault_.load();
if (!flagValue.has_value()) {
// This block is not exclusive but it is not necessary.
// If multiple threads try to initialize the feature flag, we would only
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(44, "enableWebPerformanceAPIsByDefault");
flagValue = currentProvider_->enableWebPerformanceAPIsByDefault();
enableWebPerformanceAPIsByDefault_ = flagValue;
}
return flagValue.value();
}
bool ReactNativeFeatureFlagsAccessor::fixMappingOfEventPrioritiesBetweenFabricAndReact() {
auto flagValue = fixMappingOfEventPrioritiesBetweenFabricAndReact_.load();
@@ -830,7 +848,7 @@ bool ReactNativeFeatureFlagsAccessor::fixMappingOfEventPrioritiesBetweenFabricAn
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(44, "fixMappingOfEventPrioritiesBetweenFabricAndReact");
markFlagAsAccessed(45, "fixMappingOfEventPrioritiesBetweenFabricAndReact");
flagValue = currentProvider_->fixMappingOfEventPrioritiesBetweenFabricAndReact();
fixMappingOfEventPrioritiesBetweenFabricAndReact_ = flagValue;
@@ -848,7 +866,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxEnabledRelease() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(45, "fuseboxEnabledRelease");
markFlagAsAccessed(46, "fuseboxEnabledRelease");
flagValue = currentProvider_->fuseboxEnabledRelease();
fuseboxEnabledRelease_ = flagValue;
@@ -866,7 +884,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxNetworkInspectionEnabled() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(46, "fuseboxNetworkInspectionEnabled");
markFlagAsAccessed(47, "fuseboxNetworkInspectionEnabled");
flagValue = currentProvider_->fuseboxNetworkInspectionEnabled();
fuseboxNetworkInspectionEnabled_ = flagValue;
@@ -884,7 +902,7 @@ bool ReactNativeFeatureFlagsAccessor::hideOffscreenVirtualViewsOnIOS() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(47, "hideOffscreenVirtualViewsOnIOS");
markFlagAsAccessed(48, "hideOffscreenVirtualViewsOnIOS");
flagValue = currentProvider_->hideOffscreenVirtualViewsOnIOS();
hideOffscreenVirtualViewsOnIOS_ = flagValue;
@@ -902,7 +920,7 @@ bool ReactNativeFeatureFlagsAccessor::perfMonitorV2Enabled() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(48, "perfMonitorV2Enabled");
markFlagAsAccessed(49, "perfMonitorV2Enabled");
flagValue = currentProvider_->perfMonitorV2Enabled();
perfMonitorV2Enabled_ = flagValue;
@@ -920,7 +938,7 @@ double ReactNativeFeatureFlagsAccessor::preparedTextCacheSize() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(49, "preparedTextCacheSize");
markFlagAsAccessed(50, "preparedTextCacheSize");
flagValue = currentProvider_->preparedTextCacheSize();
preparedTextCacheSize_ = flagValue;
@@ -938,7 +956,7 @@ bool ReactNativeFeatureFlagsAccessor::preventShadowTreeCommitExhaustion() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(50, "preventShadowTreeCommitExhaustion");
markFlagAsAccessed(51, "preventShadowTreeCommitExhaustion");
flagValue = currentProvider_->preventShadowTreeCommitExhaustion();
preventShadowTreeCommitExhaustion_ = flagValue;
@@ -956,7 +974,7 @@ bool ReactNativeFeatureFlagsAccessor::releaseImageDataWhenConsumed() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(51, "releaseImageDataWhenConsumed");
markFlagAsAccessed(52, "releaseImageDataWhenConsumed");
flagValue = currentProvider_->releaseImageDataWhenConsumed();
releaseImageDataWhenConsumed_ = flagValue;
@@ -974,7 +992,7 @@ bool ReactNativeFeatureFlagsAccessor::shouldPressibilityUseW3CPointerEventsForHo
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(52, "shouldPressibilityUseW3CPointerEventsForHover");
markFlagAsAccessed(53, "shouldPressibilityUseW3CPointerEventsForHover");
flagValue = currentProvider_->shouldPressibilityUseW3CPointerEventsForHover();
shouldPressibilityUseW3CPointerEventsForHover_ = flagValue;
@@ -992,7 +1010,7 @@ bool ReactNativeFeatureFlagsAccessor::skipActivityIdentityAssertionOnHostPause()
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(53, "skipActivityIdentityAssertionOnHostPause");
markFlagAsAccessed(54, "skipActivityIdentityAssertionOnHostPause");
flagValue = currentProvider_->skipActivityIdentityAssertionOnHostPause();
skipActivityIdentityAssertionOnHostPause_ = flagValue;
@@ -1010,7 +1028,7 @@ bool ReactNativeFeatureFlagsAccessor::sweepActiveTouchOnChildNativeGesturesAndro
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(54, "sweepActiveTouchOnChildNativeGesturesAndroid");
markFlagAsAccessed(55, "sweepActiveTouchOnChildNativeGesturesAndroid");
flagValue = currentProvider_->sweepActiveTouchOnChildNativeGesturesAndroid();
sweepActiveTouchOnChildNativeGesturesAndroid_ = flagValue;
@@ -1028,7 +1046,7 @@ bool ReactNativeFeatureFlagsAccessor::traceTurboModulePromiseRejectionsOnAndroid
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(55, "traceTurboModulePromiseRejectionsOnAndroid");
markFlagAsAccessed(56, "traceTurboModulePromiseRejectionsOnAndroid");
flagValue = currentProvider_->traceTurboModulePromiseRejectionsOnAndroid();
traceTurboModulePromiseRejectionsOnAndroid_ = flagValue;
@@ -1046,7 +1064,7 @@ bool ReactNativeFeatureFlagsAccessor::updateRuntimeShadowNodeReferencesOnCommit(
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(56, "updateRuntimeShadowNodeReferencesOnCommit");
markFlagAsAccessed(57, "updateRuntimeShadowNodeReferencesOnCommit");
flagValue = currentProvider_->updateRuntimeShadowNodeReferencesOnCommit();
updateRuntimeShadowNodeReferencesOnCommit_ = flagValue;
@@ -1064,7 +1082,7 @@ bool ReactNativeFeatureFlagsAccessor::useAlwaysAvailableJSErrorHandling() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(57, "useAlwaysAvailableJSErrorHandling");
markFlagAsAccessed(58, "useAlwaysAvailableJSErrorHandling");
flagValue = currentProvider_->useAlwaysAvailableJSErrorHandling();
useAlwaysAvailableJSErrorHandling_ = flagValue;
@@ -1082,7 +1100,7 @@ bool ReactNativeFeatureFlagsAccessor::useFabricInterop() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(58, "useFabricInterop");
markFlagAsAccessed(59, "useFabricInterop");
flagValue = currentProvider_->useFabricInterop();
useFabricInterop_ = flagValue;
@@ -1100,7 +1118,7 @@ bool ReactNativeFeatureFlagsAccessor::useNativeEqualsInNativeReadableArrayAndroi
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(59, "useNativeEqualsInNativeReadableArrayAndroid");
markFlagAsAccessed(60, "useNativeEqualsInNativeReadableArrayAndroid");
flagValue = currentProvider_->useNativeEqualsInNativeReadableArrayAndroid();
useNativeEqualsInNativeReadableArrayAndroid_ = flagValue;
@@ -1118,7 +1136,7 @@ bool ReactNativeFeatureFlagsAccessor::useNativeTransformHelperAndroid() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(60, "useNativeTransformHelperAndroid");
markFlagAsAccessed(61, "useNativeTransformHelperAndroid");
flagValue = currentProvider_->useNativeTransformHelperAndroid();
useNativeTransformHelperAndroid_ = flagValue;
@@ -1136,7 +1154,7 @@ bool ReactNativeFeatureFlagsAccessor::useNativeViewConfigsInBridgelessMode() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(61, "useNativeViewConfigsInBridgelessMode");
markFlagAsAccessed(62, "useNativeViewConfigsInBridgelessMode");
flagValue = currentProvider_->useNativeViewConfigsInBridgelessMode();
useNativeViewConfigsInBridgelessMode_ = flagValue;
@@ -1154,7 +1172,7 @@ bool ReactNativeFeatureFlagsAccessor::useOptimizedEventBatchingOnAndroid() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(62, "useOptimizedEventBatchingOnAndroid");
markFlagAsAccessed(63, "useOptimizedEventBatchingOnAndroid");
flagValue = currentProvider_->useOptimizedEventBatchingOnAndroid();
useOptimizedEventBatchingOnAndroid_ = flagValue;
@@ -1172,7 +1190,7 @@ bool ReactNativeFeatureFlagsAccessor::useRawPropsJsiValue() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(63, "useRawPropsJsiValue");
markFlagAsAccessed(64, "useRawPropsJsiValue");
flagValue = currentProvider_->useRawPropsJsiValue();
useRawPropsJsiValue_ = flagValue;
@@ -1190,7 +1208,7 @@ bool ReactNativeFeatureFlagsAccessor::useShadowNodeStateOnClone() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(64, "useShadowNodeStateOnClone");
markFlagAsAccessed(65, "useShadowNodeStateOnClone");
flagValue = currentProvider_->useShadowNodeStateOnClone();
useShadowNodeStateOnClone_ = flagValue;
@@ -1208,7 +1226,7 @@ bool ReactNativeFeatureFlagsAccessor::useTurboModuleInterop() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(65, "useTurboModuleInterop");
markFlagAsAccessed(66, "useTurboModuleInterop");
flagValue = currentProvider_->useTurboModuleInterop();
useTurboModuleInterop_ = flagValue;
@@ -1226,7 +1244,7 @@ bool ReactNativeFeatureFlagsAccessor::useTurboModules() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(66, "useTurboModules");
markFlagAsAccessed(67, "useTurboModules");
flagValue = currentProvider_->useTurboModules();
useTurboModules_ = flagValue;
@@ -1244,7 +1262,7 @@ double ReactNativeFeatureFlagsAccessor::virtualViewHysteresisRatio() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(67, "virtualViewHysteresisRatio");
markFlagAsAccessed(68, "virtualViewHysteresisRatio");
flagValue = currentProvider_->virtualViewHysteresisRatio();
virtualViewHysteresisRatio_ = flagValue;
@@ -1262,7 +1280,7 @@ double ReactNativeFeatureFlagsAccessor::virtualViewPrerenderRatio() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(68, "virtualViewPrerenderRatio");
markFlagAsAccessed(69, "virtualViewPrerenderRatio");
flagValue = currentProvider_->virtualViewPrerenderRatio();
virtualViewPrerenderRatio_ = flagValue;
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<f1eb31a7412bff743a5c581224d71e2a>>
* @generated SignedSource<<8131db9fc73621cf2a63be9d775dfc3d>>
*/
/**
@@ -76,6 +76,7 @@ class ReactNativeFeatureFlagsAccessor {
bool enableVirtualViewDebugFeatures();
bool enableVirtualViewRenderState();
bool enableVirtualViewWindowFocusDetection();
bool enableWebPerformanceAPIsByDefault();
bool fixMappingOfEventPrioritiesBetweenFabricAndReact();
bool fuseboxEnabledRelease();
bool fuseboxNetworkInspectionEnabled();
@@ -112,7 +113,7 @@ class ReactNativeFeatureFlagsAccessor {
std::unique_ptr<ReactNativeFeatureFlagsProvider> currentProvider_;
bool wasOverridden_;
std::array<std::atomic<const char*>, 69> accessedFeatureFlags_;
std::array<std::atomic<const char*>, 70> accessedFeatureFlags_;
std::atomic<std::optional<bool>> commonTestFlag_;
std::atomic<std::optional<bool>> cdpInteractionMetricsEnabled_;
@@ -158,6 +159,7 @@ class ReactNativeFeatureFlagsAccessor {
std::atomic<std::optional<bool>> enableVirtualViewDebugFeatures_;
std::atomic<std::optional<bool>> enableVirtualViewRenderState_;
std::atomic<std::optional<bool>> enableVirtualViewWindowFocusDetection_;
std::atomic<std::optional<bool>> enableWebPerformanceAPIsByDefault_;
std::atomic<std::optional<bool>> fixMappingOfEventPrioritiesBetweenFabricAndReact_;
std::atomic<std::optional<bool>> fuseboxEnabledRelease_;
std::atomic<std::optional<bool>> fuseboxNetworkInspectionEnabled_;
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<a76f1a1e8ba0d65b689b4b87d33d7ced>>
* @generated SignedSource<<ca1bff402a7b8c5048b50e0a7c09c0da>>
*/
/**
@@ -203,6 +203,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider {
return false;
}
bool enableWebPerformanceAPIsByDefault() override {
return false;
}
bool fixMappingOfEventPrioritiesBetweenFabricAndReact() override {
return false;
}
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<e2a5086e5586caf4c90ef503416a0e83>>
* @generated SignedSource<<4c8f1e40192bfd2c7ad52d7316aec273>>
*/
/**
@@ -441,6 +441,15 @@ class ReactNativeFeatureFlagsDynamicProvider : public ReactNativeFeatureFlagsDef
return ReactNativeFeatureFlagsDefaults::enableVirtualViewWindowFocusDetection();
}
bool enableWebPerformanceAPIsByDefault() override {
auto value = values_["enableWebPerformanceAPIsByDefault"];
if (!value.isNull()) {
return value.getBool();
}
return ReactNativeFeatureFlagsDefaults::enableWebPerformanceAPIsByDefault();
}
bool fixMappingOfEventPrioritiesBetweenFabricAndReact() override {
auto value = values_["fixMappingOfEventPrioritiesBetweenFabricAndReact"];
if (!value.isNull()) {

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