Compare commits

..
Author SHA1 Message Date
CodemodService Bot a8a8001c94 Fix CQS signal readability-avoid-const-params-in-decls in xplat/js/react-native-github/packages [A]
Reviewed By: javache

Differential Revision: D83033417
2025-09-23 02:37:27 -07:00
Vitali Zaidman 6936bd9f6b Dismiss DevLoadingView toast on touch (#53885)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53885

Changelog: [General][Added] DevServer banners can now be closed on tap. On iOS, don't close them after 15s anymore.

Banners, on iOS, but not Android, are currently closed after 15s since {D47478373} where it was introduced to deal with the banner telling users they need to connect to Metro stuck forever.

Instead of closing it after 15 seconds, allow the users on both Android and iOS to close it via a touch.

Reviewed By: huntie

Differential Revision: D82727997

fbshipit-source-id: 5aa2af78a4dbcd95b69423d52421900d4ab35244
2025-09-23 02:06:18 -07:00
generatedunixname1395667395051502 8c2f9e47fa Update React Native DevTools binaries
Summary:
Automated update of React Native DevTools binaries
bypass-github-export-checks
Changelog: [Internal]

Reviewed By: robhogan

Differential Revision: D83031681

fbshipit-source-id: 0290d423b758ce42cd9a9c8cccc0f2cf16ad992b
2025-09-23 01:46:27 -07:00
Gabriel Donadel ee811a82ec Add changelog for v0.81.4 (#53720)
Summary:
Add Changelog for 0.81.4

## Changelog:
[Internal] - Add Changelog for 0.81.4

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

Test Plan: N/A

Reviewed By: cortinico

Differential Revision: D83013088

Pulled By: arushikesarwani94

fbshipit-source-id: 3693bf6582543465102cea5dbd7dd17dffe0a272
2025-09-23 01:19:46 -07:00
Marco Wang 2e55154665 Deploy 0.285.0 to xplat (#53895)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53895

[changelog](https://github.com/facebook/flow/blob/main/Changelog.md)
Changelog: [Internal]

Reviewed By: SamChou19815

Differential Revision: D83000230

fbshipit-source-id: 7c070358623e9b68043bb8666f5c9dfc632ff2fb
2025-09-22 22:42:28 -07:00
Sam Zhou 5c369aa34c Add annotations to fix future natural inference errors in xplat/js: 6/n (#53894)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53894

Changelog: [Internal]

Reviewed By: marcoww6

Differential Revision: D83000736

fbshipit-source-id: 3ba5c59d9b2f7b967c0dccd24a73056430153bdc
2025-09-22 21:55:34 -07:00
Arushi Kesarwani 2065c31800 Updating ReactAndroid.api to unblock stable (#53891)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53891

D82726743 missed updating the ReactAndroid.api which was blocking fbandroid/stable:

https://www.internalfb.com/sandcastle/workflow/797137134054937206

Hence ran `buck2 run //xplat/js/scripts/rn-api:generate-rn-api-metadata` to update

Changelog: [Android][Fixed] - Fixed ReactAndroid.api

Reviewed By: mdvacca, sumkit, jorge-cab

Differential Revision: D83001140

fbshipit-source-id: 85e4f2005a28a3c98999198284133e4af1eaed89
2025-09-22 18:32:51 -07:00
David Vacca 5684546251 Delete LayoutAnimation (#53785)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53785

LayoutAnimation is part of legacy architecture and unused, let's delete it

changelog: [internal] internal

Reviewed By: cortinico

Differential Revision: D82235542

fbshipit-source-id: c0e2f08bcdffb9c5e102df7cca799f3a25296afe
2025-09-22 17:45:08 -07:00
David Vacca f09f4a779e Remove code from public LayoutAnimationController class (#53784)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53784

LayoutAnimation is part of legacy architecture, I'm deleting the code used from its non supported public APIs

changelog: [internal] internal

Reviewed By: shwanton

Differential Revision: D82235545

fbshipit-source-id: 9665c57b68eba9d958d3f8b9dd4224558cc8e9f6
2025-09-22 17:45:08 -07:00
David Vacca ec5bc3b285 Delete LayoutAnimation tests (#53783)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53783

LayoutAnimation is part of legacy architecture, I'm deleting unused tests

changelog: [internal] internal

Reviewed By: shwanton

Differential Revision: D82254268

fbshipit-source-id: df53215f126e37d8422ece46552596c31b11f61b
2025-09-22 17:45:08 -07:00
Christoph Purrer 46c75c1043 Add ImagePrefetching feature flag for JNI calls (#53865)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53865

This adds an additional feature flag to enable/disable image prefetch requests via JNI batching

Changelog: [Internal]

Reviewed By: rshest

Differential Revision: D82871006

fbshipit-source-id: 6cd2577f26e6d4c906e7be2f62a397177691538f
2025-09-22 17:04:55 -07:00
Vitali Zaidman e3bf881ae6 remove connection hints from being logged for the user (#53884)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53884

Changelog: [Internal]

Now that there's a clear display for when HMR is disconnected, we don't want to show messages regardless devices connection and disconnection to the DevServer because they are too partial.

Reviewed By: huntie

Differential Revision: D82727105

fbshipit-source-id: 32dd077f85d2044f89ae2d8d60a37c0ec6cccbbf
2025-09-22 15:55:25 -07:00
Sam Zhou e4368154a5 Turn on react.ref_as_prop=experimental.store_ref_in_props
Summary: Changelog: [Internal]

Reviewed By: marcoww6

Differential Revision: D82932016

fbshipit-source-id: a391bdc06eef60d3054b8440c4ccfbaf62bc931a
2025-09-22 14:46:56 -07:00
Vitali Zaidman 4148746941 add disconnection message (#53883)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53883

Changelog: [General][Added] - new banner added to indicate that Fast Refresh has lost connection, and that the app needs to be restarted to reconnect

When HMR were getting disconnected, we were not giving any indication for the user.

This lead to situations were the connection is re-established, but HMR is still disconnected, which is unexpected for users.

Instead, raise a banner hinting the user to reload the app to reconnect.

Reviewed By: huntie

Differential Revision: D82726853

fbshipit-source-id: d5f264547b2af89e9dc2a9046d063efe1145d690
2025-09-22 13:25:42 -07:00
generatedunixname537391475639613 34f7137cdc xplat/js/react-native-github/packages/react-native/ReactCommon/react/renderer/components/text/RawTextShadowNode.cpp (#53874)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/53874

Reviewed By: rshest

Differential Revision: D82804676

fbshipit-source-id: 90a426cfeb4fe264d523dafe56d2d83f1ed3da11
2025-09-22 12:35:11 -07:00
Vitali Zaidman 4d45e5987c Align Android with iOS in displaying HMR "refreshing" in color (#53846)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53846

Changelog: [Android][Added] - hot reload banner is now displayed in blue background like on iOS

iOS has a colorful "Refreshing..." banner:
 {F1982086204}

While android doesn't respect the color HMR asks it to set up for the banner:
 {F1982086218}

Reviewed By: cortinico

Differential Revision: D82726743

fbshipit-source-id: 4042851f5a8fd7d4f238f25e2d83f77144742de9
2025-09-22 11:41:38 -07:00
Andrew Datsenko 2e4da10b52 fix coverage patterns (#53881)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53881

Changelog: [Internal]
To make sure that coverage is insertect correctly when run in different metro setup where patterns do not match perfectly, we need to add glob prefix

Reviewed By: sammy-SC

Differential Revision: D82968565

fbshipit-source-id: c2676ef4c774411938039fc5b98a3b953f6ec916
2025-09-22 10:48:45 -07:00
Riccardo Cipolleschi b10faf6c02 Create the orchestration function to coordinate the creation of the hard links (#53642)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53642

## Context

One of the quirk of SwiftPM is that the packages has to have access to the headers they need. Usually this is solved by properly setting the header_search_path. However, in  SwiftPM, we are not allowed to use headers search path that escape the package itself (basically, header search path can't start with `../`).

To work around this limitation we are recreating the correct Header structure by using hardlinks to the actual headers.

## Changed

In this change we are adding a function that is used to orchestrate the helpers function defined in previous changes.

## Changelog:
[Internal] -

Reviewed By: cortinico

Differential Revision: D81778457

fbshipit-source-id: b4ab8c902d6d7e6ca4b89ccbab75c1b5d84ce00a
2025-09-22 10:14:58 -07:00
Riccardo Cipolleschi c6395eccd4 add function hard links for headers from ReactCodegen (#53640)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53640

## Context

One of the quirk of SwiftPM is that the packages has to have access to the headers they need. Usually this is solved by properly setting the header_search_path. However, in  SwiftPM, we are not allowed to use headers search path that escape the package itself (basically, header search path can't start with `../`).

To work around this limitation we are recreating the correct Header structure by using hardlinks to the actual headers.

## Changed

In this change we are adding an helper function to create hard links to Codegen Headers so that other libraries can access them.

## Changelog:
[Internal] -

Reviewed By: cortinico

Differential Revision: D81778450

fbshipit-source-id: e9f62f1c81ce8a635cc880007f495de342342a25
2025-09-22 10:14:58 -07:00
Riccardo Cipolleschi 515c735347 Add function to create hard links for headers of the third-party dependencies (#53638)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53638

## Context

One of the quirk of SwiftPM is that the packages has to have access to the headers they need. Usually this is solved by properly setting the header_search_path. However, in  SwiftPM, we are not allowed to use headers search path that escape the package itself (basically, header search path can't start with `../`).

To work around this limitation we are recreating the correct Header structure by using hardlinks to the actual headers.

## Changed

In this change we are adding an helper function that creates links for the ThirdPartyDependencies that React native and libraries might need to access.

## Changelog:
[Internal] -

Reviewed By: cortinico

Differential Revision: D81778459

fbshipit-source-id: b8f9f207a0fbe2265e2861bf508516946905b472
2025-09-22 10:14:58 -07:00
Riccardo Cipolleschi 6807231120 Create function to create hardlink to header required to build React Native Core (#53635)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53635

## Context

One of the quirk of SwiftPM is that the packages has to have access to the headers they need. Usually this is solved by properly setting the header_search_path. However, in  SwiftPM, we are not allowed to use headers search path that escape the package itself (basically, header search path can't start with `../`).

To work around this limitation we are recreating the correct Header structure by using hardlinks to the actual headers.

## Changed

In this change we did two things:
1. we move the helper functions to a headers-utils.js file (and the tests to the `headers-utils-test.js` file)
2. we added a function that coordinates the creation of the header links *and added tests for it)

## Changelog:
[Internal] -

Reviewed By: cortinico

Differential Revision: D81778464

fbshipit-source-id: fd8eb5a7af55db0a08c4d299c5470058d5424768
2025-09-22 10:14:58 -07:00
Riccardo Cipolleschi fc4a692b8e Create utility function to create the right folder structure for headers in the ReactCommon folder (#53631)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53631

## Context

One of the quirk of SwiftPM is that the packages has to have access to the headers they need. Usually this is solved by properly setting the header_search_path. However, in  SwiftPM, we are not allowed to use headers search path that escape the package itself (basically, header search path can't start with `../`).

To work around this limitation we are recreating the correct Header structure by using hardlinks to the actual headers.

## Changed

In this change we are adding an helper function that creates links for the ReactCommon folder that has a complex structure and complex mapping requirements

## Changelog:
[Internal] -

Reviewed By: cortinico

Differential Revision: D81778470

fbshipit-source-id: e0f4001048fcde0e988fc3a05b53efb1de70460b
2025-09-22 10:14:58 -07:00
Riccardo Cipolleschi 8db93abf12 Create utility function to create the right folder structure for headers in the ReactApple folder (#53629)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53629

## Context

One of the quirk of SwiftPM is that the packages has to have access to the headers they need. Usually this is solved by properly setting the header_search_path. However, in  SwiftPM, we are not allowed to use headers search path that escape the package itself (basically, header search path can't start with `../`).

To work around this limitation we are recreating the correct Header structure by using hardlinks to the actual headers.

## Changed

In this change we are adding a function to properly create the header structure for the headers in ReactApple that requires a special case.

## Changelog:
[Internal] -

Reviewed By: cortinico

Differential Revision: D81778471

fbshipit-source-id: 095d901dce139cf8221251f952f474be943a5ab3
2025-09-22 10:14:58 -07:00
Riccardo Cipolleschi 7cd3328b21 Create script to create hard links for headers from a source path to a destination path (#53620)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53620

## Context

One of the quirk of SwiftPM is that the packages has to have access to the headers they need. Usually this is solved by properly setting the header_search_path. However, in  SwiftPM, we are not allowed to use headers search path that escape the package itself (basically, header search path can't start with `../`).

To work around this limitation we are recreating the correct Header structure by using hardlinks to the actual headers.

## Changed

In this change we are adding an helper function that creates links between a source folder and a destination folder.

## Changelog:
[Internal] -

Reviewed By: cortinico

Differential Revision: D81778469

fbshipit-source-id: 3954bc219f32ea53744393a83f3179beeaca95b3
2025-09-22 10:14:58 -07:00
Riccardo Cipolleschi 072b105f52 Add function to extract headers from a folder (#53737)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53737

This change add a utility function to extract headers (both .h and .hpp) from a folder. It also allow to exclude some specific folders (e.g.: `tests`, non supported platforms, ...)

## Context
SwiftPM is very picky in how the header structure must be.
In order to preserve the import/include statements as much as possible when building from source, we can recreate the header structure in a temporary folder inside the react-native package using symlinks.

In this way, users can still modify the headers and build RNTester and HelloWorld using SwiftPM without breaking changes.

## Changelog:
[Internal] -

Reviewed By: cortinico

Differential Revision: D82205692

fbshipit-source-id: 4fa6dee2ae4790c583beb96a959b0c3045c7b50a
2025-09-22 10:14:58 -07:00
Riccardo Cipolleschi c1827fcd04 Add simple function to handle symlinks (#53736)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53736

This change adds a simple function that manages symlinks. This is used through the stack of changes to avoid code repetition.

## Context
SwiftPM is very picky in how the header structure must be.
In order to preserve the import/include statements as much as possible when building from source, we can recreate the header structure in a temporary folder inside the react-native package using symlinks.

In this way, users can still modify the headers and build RNTester and HelloWorld using SwiftPM without breaking changes.

## Changelog:
[Internal] -

Reviewed By: cortinico

Differential Revision: D82202860

fbshipit-source-id: 0baa348c84f966a2e1eeb85b008f8e653bffe96c
2025-09-22 10:14:58 -07:00
Nicola Corti 0915833f7c Follow-up from previous transform matrix fix (#53876)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53876

This is just a couple of small nits after D82836192

Changelog:
[Internal] [Changed] -

Reviewed By: javache

Differential Revision: D82953710

fbshipit-source-id: 1a98c54a110ee1a72225de331bfe2efa4e4225c0
2025-09-22 09:48:59 -07:00
Pieter De Baets 57a1820c85 Remove unused RCTHermesInstance field (#53858)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53858

We only use static methods from `HermesInstance`

Changelog: [Internal]

Reviewed By: christophpurrer

Differential Revision: D82816061

fbshipit-source-id: 515dad2e8d6e0a6f6ac26f93d5a86aedf875f93e
2025-09-22 08:47:33 -07:00
Nick Lefever e1a6c38cc1 Fix overflow with Props 2.0 in horizonal scroll view (#53872)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53872

This diff fixes the mismatch between the overflow initial value between the horizontal scroll view component initialization and the React core props instance initial value by applying the same correction as for the vertical scroll view component.

Changelog: [Internal]

Reviewed By: rshest

Differential Revision: D82919365

fbshipit-source-id: 70e40f56ffa3ea87fa74035c885608f633890610
2025-09-22 04:19:36 -07:00
Nick Lefever e314f6161a Fix scrollview overflow prop not set with Props 2.0 (#53871)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53871

The props defined in `YogaStylableProps` define the overflow to be set to `Overflow::Visible` by default.

The scroll view initialized the overflow setting to `Overflow.SCROLL`. This meant that Props 2.0 would only set the overflow prop if it was different from Visible, leading to the scroll view not being configured correctly when asking for the overflow to be visible.

This diff assigns the correct initial value to the scrollview overflow setting only when enabling Props 2.0 to avoid any unexpected behavior changes when not using Props 2.0.

Changelog: [Internal]

Reviewed By: rshest

Differential Revision: D82919286

fbshipit-source-id: d5368500cc4504164d6fdf7cf60042a9d5792853
2025-09-22 04:19:36 -07:00
Nicola Corti ce243df972 Correctly implement transform: matrix with 2d matrices (#53860)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53860

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

I've realized that our docs and validation logic states that we do support
3x3 matrixes (for 2d transforms). However they're not properly processed
as the values are just copied into a 4x4 matrix.

This can be verified by applying the 3x3 identity matrix on any transform.

I'm fixing it by correctly populating the 4x4 matrix getting the values from the 3x3 matrix in input.

Changelog:
[General] [Fixed] - 9-element (2d) transform matrix are not correctly working

Reviewed By: christophpurrer

Differential Revision: D82836192

fbshipit-source-id: 12029b37ffd8375fff48ea7f9386b849dfe96a62
2025-09-22 03:28:31 -07:00
David Vacca 23b2b99c4b 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
2025-09-22 02:34:59 -07:00
Sam Zhou 5ef054921c Turn on react.ref_as_prop=experimental.store_ref_in_props_but_remove_ref_in_react_element_config in fbsource (#53870)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53870

Changelog: [Internal]

Reviewed By: jbrown215

Differential Revision: D82913848

fbshipit-source-id: c23f564404143535622fab3133d092d1fb566711
2025-09-21 14:04:21 -07:00
Sam Zhou 71b7dd8519 Prepare createAnimatedComponent API for flow's upcoming better react 19 ref-as-prop support (#53869)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53869

This is a prep step to enable better Flow support for react 19 ref-as-prop. While it causes changes in the ReactNativeApi.d.ts snapshot, it should preserve the existing type behavior, since in the TS version, the ref prop will be excluded anyways: https://github.com/facebook/react-native/blob/a4d43290c82e8ad93f03b304a78cdf0eaf41fba1/packages/react-native/ReactNativeApi.d.ts#L1434

Changelog: [Internal]

Reviewed By: jbrown215

Differential Revision: D82916014

fbshipit-source-id: 2e62aab493dcf6f8f5e382c0739060c88e6f7ed5
2025-09-21 10:49:53 -07:00
Sam Zhou 5b544c7cd8 Simplify some RN types (#53868)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53868

This is a prep step to enable better Flow support for react 19 ref-as-prop. While it causes changes in the ReactNativeApi.d.ts snapshot, this diff simply inlines what these `React.ElementRef` evaluates into.

Changelog: [Internal]

Reviewed By: jbrown215

Differential Revision: D82915646

fbshipit-source-id: 64179eac7dde91381361fb9f1053d58100d864c3
2025-09-21 10:49:53 -07:00
Alex Hunt a4d43290c8 Tweak Dev Menu appearance for iOS 26 (#53844)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53844

Small UI tweaks that help when scanning more visually spread out alert actions on iOS 26.

- Use bold (iOS 26 style) alert title.
- Differentiate "Cancel" actions with red system style.

Changelog: [Internal]

Reviewed By: christophpurrer

Differential Revision: D82731784

fbshipit-source-id: 0a0215fc75a4832e742e22328d5e21eee3808972
2025-09-20 03:23:31 -07:00
Nikita Lutsenko 7fb90c3f1b jsi | Remove unnecessary semicolons. (#53864)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53864

Changelog: [Internal] Removed unnecessary semicolons, improving code quality.

Reviewed By: cortinico

Differential Revision: D82828986

fbshipit-source-id: aaafc332a1dc5944cb136bf6dd105d68c1c99e8d
2025-09-20 03:15:57 -07:00
Christoph Purrer 362ed179a8 Fix race condition between experimental_prefetchResources and surface stop (#53861)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53861

Changelog: [Internal]

The issue is a race condition in the React Native Fabric mounting system where `experimental_prefetchResources` is called on a `SurfaceMountingManager` after the surface has been stopped.

1.) `experimental_prefetchResources` is called
2.) Concurrently, `stopSurface()` *can be* called, which sets `mThemedReactContext = null`
3.) `experimental_prefetchResources` then tries to access `mThemedReactContext` via `Assertions.assertNotNull(mThemedReactContext)`
4.) Since `mThemedReactContext` is now `null`, the assertion fails and throws an AssertionError

The fix involves adding a guard to check if the surface is stopped before accessing `mThemedReactContext`

Follows existing patterns used by other methods in the same class

https://github.com/facebook/react-native/blob/main/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.java#L201-L213

Reviewed By: lenaic

Differential Revision: D82842572

fbshipit-source-id: 723bad24a075efa219766b0e148080dd42d59fba
2025-09-19 17:27:14 -07:00
Pieter De Baets fcbe4d1677 Split off MessageQueueThread header to separate target (#53857)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53857

Changelog: [Internal]

Reviewed By: cortinico

Differential Revision: D82625359

fbshipit-source-id: 7650dcd424299a21388c7bcf6c33c89b9f09171d
2025-09-19 14:02:47 -07:00
Christoph Purrer 390c9d30dc Update ## v0.82.0-rc.0 (#53847)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53847

Changelog: [Internal]

Reviewed By: cortinico

Differential Revision: D82753924

fbshipit-source-id: a5a2036ccd74cc7f7dd463d82e96f156a4e309e2
2025-09-19 13:46:17 -07:00
Kræn Hansen 0198c92c71 Export @react-native/typescript-config/strict shorthand (#53564)
Summary:
Extending a tsconfig seems simpler than adding `compilerOptions` with `customConditions`.

### Before

```jsonc
{
  "extends": "react-native/typescript-config",
  "compilerOptions": {
    // ...
    "customConditions": ["react-native-strict-api", "react-native"]
  }
}
```

### After

```jsonc
{
  "extends": "react-native/typescript-config/strict"
  // ...
}
```

## Changelog:

[GENERAL] [ADDED] - Add `react-native/typescript-config/strict` export enabling the `react-native-strict-api` custom condition.

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

Test Plan:
### `package.json`

```
{
  "name": "react-native-ts-test",
  "private": true,
  "version": "0.1.0",
  "scripts": {
    "build": "tsc --noEmit"
  },
  "devDependencies": {
    "react-native/typescript-config": "^0.81.1",
    "typescript": "^5.9.2",
    "jest": "^30.1.2"
  },
  "dependencies": {
    "react-native": "^0.81.1"
  }
}
```

### `tsconfig.json`

```
{
  "extends": "react-native/typescript-config/strict",
  "include": ["src/index.ts"]
}
```

### `src/index.ts`

```
import { View } from "react-native";
```

Run `npx resolution-explorer` and select "react-native from src/index.ts to node_modules/react-native/types_generated/index.d.ts" to verify the types are resolved correctly.

```
Explicitly specified module resolution kind: 'Bundler'.
Resolving in CJS mode with conditions 'import', 'types', 'react-native-strict-api'.
File '/Users/kraen.hansen/Repositories/react-native-ts-test/src/package.json' does not exist.
Found 'package.json' at '/Users/kraen.hansen/Repositories/react-native-ts-test/package.json'.
Loading module 'react-native' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
Directory '/Users/kraen.hansen/Repositories/react-native-ts-test/src/node_modules' does not exist, skipping all lookups in it.
Found 'package.json' at '/Users/kraen.hansen/Repositories/react-native-ts-test/node_modules/react-native/package.json'.
Entering conditional exports.
Matched 'exports' condition 'react-native-strict-api'.
Using 'exports' subpath '.' with target './types_generated/index.d.ts'.
File '/Users/kraen.hansen/Repositories/react-native-ts-test/node_modules/react-native/types_generated/index.d.ts' exists - use it as a name resolution result.
'package.json' has a 'peerDependencies' field.
Resolving real path for '/Users/kraen.hansen/Repositories/react-native-ts-test/node_modules/react-native', result
'/Users/kraen.hansen/Repositories/react-native-ts-test/node_modules/react-native'.
Failed to find peerDependency 'types/react'.
Found 'package.json' at '/Users/kraen.hansen/Repositories/react-native-ts-test/node_modules/react/package.json'.
Found peerDependency 'react' with '19.1.1' version.
Resolved under condition 'react-native-strict-api'.
Exiting conditional exports.
Resolving real path for '/Users/kraen.hansen/Repositories/react-native-ts-test/node_modules/react-native/types_generated/index.d.ts', result
'/Users/kraen.hansen/Repositories/react-native-ts-test/node_modules/react-native/types_generated/index.d.ts'.
======== Module name 'react-native' was successfully resolved to
'/Users/kraen.hansen/Repositories/react-native-ts-test/node_modules/react-native/types_generated/index.d.ts' with Package ID
'react-native/types_generated/index.d.ts@0.81.1+react@19.1.1'. ========
```

Reviewed By: robhogan

Differential Revision: D82791201

Pulled By: philIip

fbshipit-source-id: f58d3b8fcf3d7f18dd29eef18a3c8c0cb57d1d78
2025-09-19 13:28:31 -07:00
Simek 34cd61f0d5 fix C++ in-code docs comments to silence warnings (#53835)
Summary:
Address invalid C++ in-code docs comments to silence few warnings. Ref:
* https://www.doxygen.nl/manual/commands.html#cmdtparam

## Changelog:

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

Pick one each for the category and type tags:

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

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

[INTERNAL][FIXED] - Address invalid C++ in-code docs comments to silence the warnings.

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

Test Plan: Building RNTester app locally does not output the warnings related to in-code docs comments.

Reviewed By: cortinico

Differential Revision: D82791099

Pulled By: philIip

fbshipit-source-id: 2f93bfd4cd303471b2c52fcdf74871e5dee8c06a
2025-09-19 13:12:23 -07:00
David Vacca e349009cb8 Refactor ReactNativeNewArchitectureFeatureFlagsDefaults to remove legacy architecture configuration (#53791)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53791

I'm removing parameter to configure new architecture in ReactNativeNewArchitectureFeatureFlagsDefaults because the new architecture is enabled by default everywhere.

changelog: [internal] internal

Reviewed By: cortinico

Differential Revision: D82241552

fbshipit-source-id: 9c5cee4befc914d95b84b01325485923e17ff6da
2025-09-19 13:01:08 -07:00
David Vacca f847496749 Refactor ReactNativeFeatureFlagsOverrides_RNOSS_Stable_Android to enable new arch (#53790)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53790

New architecture should we enabled by default everywhere, Stable releases should use new arch now

changelog: [internal] internal

Reviewed By: cortinico

Differential Revision: D82241551

fbshipit-source-id: 2a1bf14f2f1da6e441a58b083ca5a55618eec256
2025-09-19 13:01:08 -07:00
Sam Zhou 2590cd739a Deploy 0.284.0 to xplat
Summary:
[changelog](https://github.com/facebook/flow/blob/main/Changelog.md)
Changelog: [Internal]

Reviewed By: marcoww6

Differential Revision: D82786580

fbshipit-source-id: 8caa7802025004fce6cb5067c191b681087cb979
2025-09-19 07:33:42 -07:00
Sam Zhou 7ba64ca0f1 Pre-suppress errors for improved typing of Array.{includes,indexOf,lastIndexOf} in xplat
Summary:
In Flow 0.284, we will have a stricter version of `Array<T>.includes`. Instead of accepting `mixed`, we will only accept `T` to help catch logical errors. We did the same for `Array.indexOf` and `Array.lastIndexOf` as well.

This diff pre-suppresses newly discovered errors in part of the codebase.

Changelog: [Internal]

Reviewed By: marcoww6

Differential Revision: D82784398

fbshipit-source-id: 6cb11809844f964e0604d33b9f7a3989074cd1cc
2025-09-19 07:17:14 -07:00
Ruslan Lesiutin 0e77015a85 Fix unkown name for Timestamps on Timings track (#53854)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53854

# Changelog: [Internal]

This fixes the unkown names message for TimeStamps on Timings track

Reviewed By: rubennorte

Differential Revision: D82812849

fbshipit-source-id: 91101998b4b7befa08bf0e45cae494765d5f2b6d
2025-09-19 06:53:23 -07:00
Ruslan Lesiutin 1b5e8e63b6 Manually preserve ordering for Scheduler and Components tracks (#53853)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53853

# Changelog: [Internal]

Chrome DevTools orders tracks based on the timestamp of the first entry.

For React on Web we emit a few entries to establish the ordering:
https://github.com/facebook/react/blob/6eda534718d09a26d58d65c0a376e05d7e2a3358/packages/react-reconciler/src/ReactFiberPerformanceTrack.js#L57-L96

We are doing the same thing here, but in C++.

Reviewed By: rubennorte

Differential Revision: D82811889

fbshipit-source-id: cfc4060de05a3d74e240f019dbeaa910fa93eb0b
2025-09-19 06:53:23 -07:00
Tim Yung 03d9f34a82 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-19 05:10:47 -07:00
Tim Yung 4a1388268d 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-19 05:10:47 -07:00
generatedunixname1395667395051502 b821bc3aba Update React Native DevTools binaries
Summary:
Automated update of React Native DevTools binaries
bypass-github-export-checks
Changelog: [Internal]

Reviewed By: robhogan

Differential Revision: D82813624

fbshipit-source-id: 51fe7a84af2d4f2da7027e1649ec038517f9d561
2025-09-19 04:53:33 -07:00
Moti Zilberman e16b6470e4 Backout D82236159: [RN][debugger-shell] Implement saved window positioning per target (#53816)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53816

Changelog: [Internal]

D82236159 introduced the first `node_modules` dependency in the Electron part of `react-native/debugger-shell`. This is not currently handled correctly by the build script, so this resulted in an instacrashing binary.

I'm temporarily backing out D82236159 until we have a proper fix for the build script.

Reviewed By: robhogan

Differential Revision: D82632937

fbshipit-source-id: 6c7c182e2a7c89e6ea2761096dcc426dbf2ae5cb
2025-09-19 02:38:00 -07:00
Alex Hunt cb7453fb9f Improve Network trace event field coverage (#53840)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53840

After this diff, successful network events are displayed as fully hydrated timespans in the Performance panel network track, with all metadata needed to usefully populate the UI.

**Changes**

Adds:
- `"ResourceFinish"`: `encodedDataLength`, `decodedBodyLength`
- `"ResourceReceiveResponse"`: Populates `data.timing` members, which enables *"Request sent and waiting"* to be rendered correctly in the timeline.

Removes:

- `"ResourceWillSendRequest"` events — very rarely emitted by Chrome and are extraneous for our use case.

Changelog: [Internal]

Reviewed By: hoxyq

Differential Revision: D82636798

fbshipit-source-id: a4b0f0671b97aaadc279ac56d39fee0c95d4ddc7
2025-09-18 14:41:16 -07:00
nishan (o^▽^o) c8e5f9766b fix(iOS): boxShadow + overflow hidden combination affecting pointer event box-none and scale transform. (#52413)
Summary:
This issue is only reproducible with combination of `overflow: hidden` and `boxShadow` i.e. when a [container view](https://github.com/facebook/react-native/blob/2ce7eab5f998788ffa8346b63cc4901d026456ba/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm#L799) is added to the hierarchy.

### Case 1:

```jsx
<Pressable
  pointerEvents="box-none"
  style={{ width: 300, height: 300, boxShadow: "0 0 100px 0 rgba(0, 0, 0, 0.5)", overflow: "hidden" }}
  onPress={() => {
    alert("Tapped");
  }}
/>
```

Here the view has `box-none` but it will still trigger the press event because this [line](https://github.com/facebook/react-native/blob/2ce7eab5f998788ffa8346b63cc4901d026456ba/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm#L658) returns the `_containerView` as `hitView` and this condition gets [fullfilled](https://github.com/facebook/react-native/blob/2ce7eab5f998788ffa8346b63cc4901d026456ba/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm#L676) (since it is not self). To fix this issue we should iterate on `self.currentContainerView.subviews`.

### Case 2:

Transform scale clipping child view.

```jsx
<Pressable
  pointerEvents="box-none"
  style={{ width: 300, height: 300, overflow: "hidden",
    transform: [
      { scale: 0.5 },
    ],
    boxShadow: "0 0 100px 0 rgba(0, 0, 0, 0.5)",
  }}
  onPress={() => {
    alert("parent view");
  }}
>
  <Pressable
    style={{
      position: "absolute",
      bottom: 0,
      right: 0,
      backgroundColor: "blue",
      height: 50,
      width: 100,
    }}
    onPress={() => {
      alert("child view");
    }}
  >
    <Text>Press me</Text>
  </Pressable>
</Pressable>;
```

The above style hides the child view on iOS whereas it is visible on android.

| iOS | Android |
   |---|---|
   | <img src="https://github.com/user-attachments/assets/14713ec9-1ae7-4425-9348-946d507188e8" width="200px" /> | <img src="https://github.com/user-attachments/assets/0f6e2368-037d-4b03-8a85-8a08f1578ff6" width="200px" /> |

This happens because `containerView` uses `self.frame` property which gets mutated due to scale transform. So containerView becomes `actualSize * scale * scale` instead of `actualSize * scale` and ends up clipping child views because of overflow hidden. Please checkout the layout hierarchy in the below screenshot. To fix it we need to use `self.bounds` instead of `self.frame` when setting the frame for container.

<img src="https://github.com/user-attachments/assets/9ce41756-f41f-4782-bfc9-b0c281f314b7" width="300px" />

## Changelog:

[IOS] [FIXED] - boxShadow + overflow hidden combination interfering with pointerEvents and transform scale.

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

Pick one each for the category and type tags:

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

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

Test Plan:
Test above example snippets and pointer events examples in RNTester.

cc - joevilches

Reviewed By: cortinico, jorge-cab

Differential Revision: D77872110

Pulled By: joevilches

fbshipit-source-id: e9693c79b47379531510607921ffaa6d6cc5c17b
2025-09-18 14:06:00 -07:00
Nicola Corti 1c5e0ffd9f Do not reset the native artifacts version to 1000.0.0 on release branches (#53817)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53817

What is currently happening, is that the various commits on the release branches like `0.82-stable` are resetting the version of native artifacts to `1000.0.0-<SHA>`.

The reason is that during the `test-all` workflow, we pass the `dry-run` as release type.
That's to prevent the various tools from calling `npm publish` and so on.

The problem is that on the releases branches, the version was already set at branch cut time.
Therefore, we see the version 1000.0.0 reappearing during Android E2E test in the emulator. Similary this is also affecting iOS prebuilds so I'm attempting to fix it here.

Changelog:
[Internal] [Changed] -

Reviewed By: huntie

Differential Revision: D82553599

fbshipit-source-id: 31a52e7df036e700663b3d3dd677973a7a210a30
2025-09-18 10:53:25 -07:00
Alex Hunt 5b8827939d Support additional PerformanceResourceTiming fields (#53815)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53815

Changelog: [Internal]

Reviewed By: rubennorte

Differential Revision: D82561777

fbshipit-source-id: f387c4bca2112111e736433af90ada16efd14e8b
2025-09-18 09:57:25 -07:00
Andrew Datsenko e97ef8f1fb Fix dotslash issue in OD (#53842)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53842

Changelog: [Internal]
There is a conflict between dotslash in node_modules and in OD it does not invoke buck2

Reviewed By: javache

Differential Revision: D82724326

fbshipit-source-id: c90cab58818e0245f8763b729c7e5432735eb05e
2025-09-18 07:39:22 -07:00
Nick Lefever e6390703e7 Fix scroll view FPS listener reset on init (#53838)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53838

The FPS listener is being assigned to all scroll view instances by the scroll view manager. This listener should not be reset when the view is being recycled and should stay assigned at all times.

Changelog: [Internal]

Reviewed By: javache

Differential Revision: D82720151

fbshipit-source-id: a2a37bad93efaa6e435725adf16c9ad1b4207ba0
2025-09-18 05:35:09 -07:00
generatedunixname537391475639613 aacb9898f2 xplat/js/react-native-github/packages/react-native/ReactCommon/react/utils/TemplateStringLiteral.h (#53836)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/53836

Reviewed By: rshest

Differential Revision: D82428779

fbshipit-source-id: 2716784a85c4885fe438348666b4772c2da3c400
2025-09-18 04:56:38 -07:00
Nicola Corti 460394e4b8 Turn on enableSwiftUIBasedFilters in the experimental channel (#53794)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53794

Basically what the title says. This is needed by Expo for experimetation.

Changelog:
[Internal] [Changed] -

Reviewed By: joevilches

Differential Revision: D82530292

fbshipit-source-id: 82ce8b1e8fc8d954cc04ec456ad80f769aedafe7
2025-09-18 04:34:47 -07:00
Nicola Corti 968ec9e093 Unpin version from react-native-android in run_fantom_tests (#53795)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53795

I've published another docker image that should now work and unblock `run_fantom_tests`
so we don't need to pin the version to `v18.0` anymore:
https://github.com/react-native-community/docker-android

Changelog:
[Internal] [Changed] -

Reviewed By: huntie

Differential Revision: D82532516

fbshipit-source-id: 980c2feb053f9d096e70f37bb690e18cc8b87dc0
2025-09-18 04:12:50 -07:00
Alex Hunt 6ef351b3ce Move trace event handling into NetworkReporter (#53776)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53776

Refactor and improve how we emit CDP trace events for network requests.

Key changes:
- Split up `PerformanceTracer` methods into discrete trace events.
- Move event calls out of `PerformanceEntryReporter` (upwards) into `NetworkReporter`. This now:
    - Aligns better with the matching source `NetworkReporter` events.
    - Removes metadata pieces from `PerformanceEntryReporter` that weren't part of the Web `PerformanceResourceTiming` API.
- Populate additional fields on `ResourceReceiveResponse`.

Changelog: [Internal]

Reviewed By: hoxyq

Differential Revision: D82433225

fbshipit-source-id: 4fce219f0c86a7257b8df250ef9f2b4ec8bd8de3
2025-09-18 03:01:22 -07:00
Jakub Piasecki 674fb77d93 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-18 01:26:08 -07:00
Devan Buggay 14458d8699 Add focus/blur commands to View (#53828)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53828

Adds focus and blur commands to Android views.

Changelog: [Internal]

Reviewed By: rozele

Differential Revision: D82644681

fbshipit-source-id: 96fa6370e177c91742d285b0b158b77447d105f6
2025-09-18 00:36:55 -07:00
Devan Buggay 2945fa6e0e Hook up focus/blur events (#53827)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53827

Hook up focus/blur events to view.

Changelog: [Internal]

Reviewed By: rozele

Differential Revision: D82146291

fbshipit-source-id: 3cb90d22c00d067099c4c6fac734f27030d87639
2025-09-18 00:36:55 -07:00
Devan Buggay 07b5802ee5 focus/blur event emission (#53826)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53826

Wires up focus/blur events to the base event emitter, gated by enabledImperativeFocus feature flag.

https://docs.google.com/document/d/1L4ViBnXq5hw858VoecZPmJE2llOB97Tjs2VtJ7RHlNI/edit?tab=t.0

Changelog: [Internal]

Reviewed By: rozele

Differential Revision: D82146275

fbshipit-source-id: 4b7bb1336f74bb0de2d7ecf0737dd63067bd558f
2025-09-18 00:36:55 -07:00
Devan Buggay 3e5838086f Add focus/blur commands to View (#53825)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53825

Adds focus/blur commands to View on iOS.
https://docs.google.com/document/d/1L4ViBnXq5hw858VoecZPmJE2llOB97Tjs2VtJ7RHlNI/edit?tab=t.0#heading=h.azm4b33t75uk

Changelog: [Internal]

Reviewed By: rozele

Differential Revision: D82146249

fbshipit-source-id: 582f448f4d7525560ef74a23c0762e86d74550d4
2025-09-18 00:36:55 -07:00
Devan Buggay 596dece4c0 enableImperativeFocus feature flag (#53824)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53824

Creates a new feature flag to control focus/blur commands and event emissions for arbitrary views https://docs.google.com/document/d/1L4ViBnXq5hw858VoecZPmJE2llOB97Tjs2VtJ7RHlNI/edit?tab=t.0#heading=h.azm4b33t75uk

Changelog: [Internal]

Reviewed By: Abbondanzo

Differential Revision: D82146210

fbshipit-source-id: 59f3e6c8740b0c006f8930541205aa15192a9f59
2025-09-18 00:36:55 -07:00
Sam Zhou 4d2e38edd9 Deploy 0.283.0 to xplat (#53820)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53820

[changelog](https://github.com/facebook/flow/blob/main/Changelog.md)
Changelog: [Internal]

Reviewed By: panagosg7

Differential Revision: D82636194

fbshipit-source-id: 620016043bed481e43d0d4216280517c2890bfd7
2025-09-17 09:29:52 -07:00
React Native Bot 926af3bc36 Add changelog for v0.82.0-rc.3 (#53813)
Summary:
Add Changelog for 0.82.0-rc.3

## Changelog:
[Internal] - Add Changelog for 0.82.0-rc.3

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

Test Plan: N/A

Reviewed By: cortinico

Differential Revision: D82628336

Pulled By: vzaidman

fbshipit-source-id: 2ade8a48981a70e571e7a8db0e15af0c722f82ba
2025-09-17 06:03:11 -07:00
Vitali Zaidman de4e01bcc6 add the nodejs type for process.memoryUsage.rss() (#53805)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53805

Changelog: [Internal]

https://nodejs.org/docs/latest-v24.x/api/process.html#processmemoryusagerss

Reviewed By: huntie

Differential Revision: D82550739

fbshipit-source-id: 11026fb82608e004b10426776592f22e67eb0720
2025-09-17 01:24:59 -07:00
Marco Wang 7d73d39535 Deploy 0.282.0 to xplat (#53810)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53810

[changelog](https://github.com/facebook/flow/blob/main/Changelog.md)
Changelog: [Internal]

Reviewed By: SamChou19815

Differential Revision: D82597378

fbshipit-source-id: 40d601956d9f69ec8d68a2c324bb3449ee27c931
2025-09-16 23:32:23 -07:00
Eric Rozell eba38b831c 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
2025-09-16 20:20:14 -07:00
David Vacca 18cb4edfa7 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
2025-09-16 17:33:14 -07:00
Sam Zhou dadd7cdaf7 Make ref prop optional in xplat: 1/n (#53801)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53801

Changelog: [Internal]

Reviewed By: panagosg7

Differential Revision: D82507711

fbshipit-source-id: 27c8004c0475765705a01c0b6afb274dab443a38
2025-09-16 09:10:22 -07:00
Tom Scallon 4308185b64 Allow EventEmitters to be reported as optional (#53804)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53804

## Changelog:

[General] [Fixed] - Allow `EventEmitter`s to be optional (for push safety)

Reviewed By: javache

Differential Revision: D82509571

fbshipit-source-id: 801a22b10b2709968009527130cfa890d30a4f3a
2025-09-16 08:59:12 -07:00
Nicola Corti d0d08e4554 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
2025-09-16 07:30:55 -07:00
Nicola Corti 4858a0f469 Mark ReactTextInlineImageShadowNode as @LegacyArchitecture (#53735)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53735

This class should have been marked as LegacyArchitecture back then but was forgotten.
I'm doing it now.

Changelog:
[Internal] -

Reviewed By: javache

Differential Revision: D82219780

fbshipit-source-id: 5119b7469733d5d2d4b16e976b09231ad5f71f5f
2025-09-16 07:23:51 -07:00
Vitali Zaidman f93506fb23 Fix typo in CHANGELOG.md (#53796)
Summary:
Fix typo in CHANGELOG.md

Changelog: [INTERNAL]

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

Test Plan: Fix typo in CHANGELOG.md

Reviewed By: fabriziocucci

Differential Revision: D82535096

Pulled By: vzaidman

fbshipit-source-id: fe93adf86ff48f0095312edbfce7b3ae6984198a
2025-09-16 06:49:03 -07:00
Moti Zilberman f4aef39563 Revert D82459089: Update React Native DevTools binaries
Differential Revision:
D82459089

Original commit changeset: 3ccf7a1f07da

Original Phabricator Diff: D82459089

fbshipit-source-id: 9ab8827bfb534e5236c37a8a47206f891741a8e0
2025-09-16 05:33:44 -07:00
Ruslan Lesiutin af7fc1b424 Update debugger-frontend from 5a792db...8b84a77 (#53789)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53789

Changelog: [Internal] - Update `react-native/debugger-frontend` from 5a792db...8b84a77

Resyncs `react-native/debugger-frontend` from GitHub - see `rn-chrome-devtools-frontend` [changelog](https://github.com/facebook/react-native-devtools-frontend/compare/5a792db1225adda206313e9bf751198a1ca7851a...8b84a77b2c82c670886ef064dfc92d6bce83e579).

### Changelog

| Commit | Author | Date/Time | Subject |
| ------ | ------ | --------- | ------- |
| [8b84a77b2](https://github.com/facebook/react-native-devtools-frontend/commit/8b84a77b2) | Ruslan Lesiutin (28902667+hoxyq@users.noreply.github.com) | 2025-09-15T17:28:39+01:00 | [fix: avoid race conditions when fetching background trace (#206)](https://github.com/facebook/react-native-devtools-frontend/commit/8b84a77b2) |
| [95bd36ce9](https://github.com/facebook/react-native-devtools-frontend/commit/95bd36ce9) | Ruslan Lesiutin (28902667+hoxyq@users.noreply.github.com) | 2025-09-15T14:45:07+01:00 | [feat: use application display name for trace title (#207)](https://github.com/facebook/react-native-devtools-frontend/commit/95bd36ce9) |

Reviewed By: huntie

Differential Revision: D82464061

fbshipit-source-id: c33db7a535a148f8316730009580aef00afe04f1
2025-09-16 05:18:00 -07:00
Zeya Peng 8d03e63265 Revert D82461457: Clean up batchingControlledByJS in NativeAnimated kotlin
Differential Revision:
D82461457

Original commit changeset: a1208720b83e

Original Phabricator Diff: D82461457

fbshipit-source-id: 99416873f66c45ccf61614d3e356e6a777bbad6b
2025-09-16 03:39:45 -07:00
170 changed files with 4303 additions and 2479 deletions
+1 -1
View File
@@ -98,4 +98,4 @@ untyped-import
untyped-type-import
[version]
^0.281.0
^0.285.0
+3
View File
@@ -17,6 +17,9 @@ runs:
- name: Install node dependencies
uses: ./.github/actions/yarn-install
- name: Set React Native Version
# We don't want to set the version for stable branches, because this has been
# already set from the 'create release' commits on the release branch.
if: ${{ !endsWith(github.ref_name, '-stable') }}
shell: bash
run: node ./scripts/releases/set-rn-artifacts-version.js --build-type ${{ inputs.release-type }}
- name: Setup gradle
+1 -2
View File
@@ -383,8 +383,7 @@ jobs:
runs-on: 8-core-ubuntu
needs: [set_release_type]
container:
# Version is pinned to v18.0 to unblock `run_fantom_tests` - see https://github.com/react-native-community/docker-android/pull/242#issuecomment-3280029122
image: reactnativecommunity/react-native-android:v18.0
image: reactnativecommunity/react-native-android:latest
env:
TERM: "dumb"
GRADLE_OPTS: "-Dorg.gradle.daemon=false"
+1
View File
@@ -133,6 +133,7 @@ vendor/
# Swift Package build folder
/packages/react-native/.build
/packages/react-native/.swiftpm
/packages/react-native/React/includes/
# @react-native/codegen
/packages/react-native/React/FBReactNativeSpec/
+28 -2
View File
@@ -1,5 +1,30 @@
# Changelog
## v0.81.4
### Fixed
#### iOS specific
- Fix regression that skips artifacts code generation ([f6f5ea0b2e](https://github.com/facebook/react-native/commit/f6f5ea0b2eed894725d8f6e8bd045c99c3182026) by [@kitten](https://github.com/kitten))
- Reapplied "Use autolinking-generated react-native-config output in second step of cocoapods linking that generates artifacts and generated source" ([bb73315a3f](https://github.com/facebook/react-native/commit/bb73315a3fd8cd203c4ddb3ffa10bfec307c7e92) by [@kitten](https://github.com/kitten))
## v0.82.0-rc.3
### Added
- **Hermes V1:** Added a dependency on hermes-compiler ([0caf8e70d5](https://github.com/facebook/react-native/commit/0caf8e70d53f611a73ad9b55879dfe0a5f036371) by [@j-piasecki](https://github.com/j-piasecki))
### Fixed
#### Android specific
- **Hermes V1:** Changed the coordinates of hermes artifacts when using Hermes V1 ([d0fb33822d](https://github.com/facebook/react-native/commit/d0fb33822de38183895c8b3421f46966909beaf3) by [@j-piasecki](https://github.com/j-piasecki))
#### iOS specific
- **Codegen:** Fix regression that skips artifacts code generation ([f6f5ea0b2e](https://github.com/facebook/react-native/commit/f6f5ea0b2eed894725d8f6e8bd045c99c3182026) by [@kitten](https://github.com/kitten))
## v0.81.3
### Fixed
@@ -66,6 +91,7 @@
- **Error Handling:** Unhandled promises are now handled by ExceptionsManager.handleException, instead of being swallowed as Logbox Warnings. ([c4082c9ce2](https://github.com/facebook/react-native/commit/c4082c9ce208a324c2d011823ca2ba432411aafc) by [@krystofwoldrich](https://github.com/krystofwoldrich))
- **`shouldEmitW3CPointerEvents`:** Migrate `shouldPressibilityUseW3CPointerEventsForHover` to common private feature flags and remove `shouldEmitW3CPointerEvents` flag. ([fb4587780e](https://github.com/facebook/react-native/commit/fb4587780e8d6111139d73598a9a26ff392dee28) by [@coado](https://github.com/coado))
- **TurboModuleUtils:** Remove unused ReactCommon/TurboModuleUtils functions #deepCopyJSIObject and #deepCopyJSIArray ([ead669ade3](https://github.com/facebook/react-native/commit/ead669ade31ee703c407f96c0ce98d8f2991bdc8) by [@christophpurrer](https://github.com/christophpurrer))
- **TurboModules:** Delete old location of CallbackWrapper.h / LongLivedObject.h by ([cb94e71](https://github.com/facebook/react-native/commit/cb94e71845259ae7fa823eb4d21cde74fccd7435) [@christophpurrer](https://github.com/christophpurrer))
#### Android specific
@@ -80,7 +106,7 @@
### Added
- **Animated:** `Animated.CompositeAnomation` is now exposed when using `"react-native-strict-api"` ([024d25794a](https://github.com/facebook/react-native/commit/024d25794a51c94c877c1dfa115a82ebbf559614) by [@huntie](https://github.com/huntie))
- **Animated:** `Animated.CompositeAnimation` is now exposed when using `"react-native-strict-api"` ([024d25794a](https://github.com/facebook/react-native/commit/024d25794a51c94c877c1dfa115a82ebbf559614) by [@huntie](https://github.com/huntie))
- **Animated:** Allow calling createAnimatedNode without batching ([d9d9a49e18](https://github.com/facebook/react-native/commit/d9d9a49e18f3c51caa18cf7da0a1fcd62f1ecf18) by [@zeyap](https://github.com/zeyap))
- **Animated:** Allow filter usage with native animated driver. ([138d0eb01d](https://github.com/facebook/react-native/commit/138d0eb01dbe597261459a37d364d1780c3ef228) by [@intergalacticspacehighway](https://github.com/intergalacticspacehighway))
- **API:** Expose NativeComponentRegistry API as JavaScript root export ([f936780cd5](https://github.com/facebook/react-native/commit/f936780cd5c0c17797f9d2bbc8f5cee81c2eefce) by [@zhongwuzw](https://github.com/zhongwuzw))
@@ -117,7 +143,7 @@
- **AGP:** AGP to 8.12.0 ([742ef3d661](https://github.com/facebook/react-native/commit/742ef3d6615c8c1202e9f683e6127ac97d7a9e23) by [@cortinico](https://github.com/cortinico))
- **DevSupportManager:** DevSupport `openDebugger()` methods now accept a `panel: String?` param. Frameworks directly implementing `DevSupportManager` will need to adjust call signatures. ([9dba7112cf](https://github.com/facebook/react-native/commit/9dba7112cfd09b02300869a77dba3dca16f49a28) by [@huntie](https://github.com/huntie))
- **Kotlin:**Migrated TextAttributeProps to Kotlin. You might need to update your property access to use camelCase instead of Hungarian notation. ([fa921b3c7b](https://github.com/facebook/react-native/commit/fa921b3c7b289800a79196468f993a0eb0bf693f) by [@mateoguzmana](https://github.com/mateoguzmana))
- **Kotlin:** Migrated TextAttributeProps to Kotlin. You might need to update your property access to use camelCase instead of Hungarian notation. ([fa921b3c7b](https://github.com/facebook/react-native/commit/fa921b3c7b289800a79196468f993a0eb0bf693f) by [@mateoguzmana](https://github.com/mateoguzmana))
- **Kotlin:** Migrated ReactBaseTextShadowNode to Kotlin. You might need to update your property access to use camelCase instead of Hungarian notation. ([8ccfff9a46](https://github.com/facebook/react-native/commit/8ccfff9a46f317fd78f478c8b3f180441535d1ca) by [@mateoguzmana](https://github.com/mateoguzmana))
- **Kotlin:** Migrated com.facebook.react.bridge.Arguments to Kotlin. ([2534aeaddb](https://github.com/facebook/react-native/commit/2534aeaddb0490b69dfaba6b8d316616c7e10a9c) by [@mateoguzmana](https://github.com/mateoguzmana))
- **Kotlin:** Migrate `YogaConfig` to Kotlin ([4d5caef76b](https://github.com/facebook/react-native/commit/4d5caef76b83eb7e983364ecc81abb6027e5f98e) by [@mateoguzmana](https://github.com/mateoguzmana))
+19 -16
View File
@@ -3057,30 +3057,30 @@ type util$InspectOptions = {
};
declare type util$ParseArgsOption =
| {|
| $ReadOnly<{|
type: 'boolean',
multiple?: false,
short?: string,
default?: boolean,
|}
| {|
|}>
| $ReadOnly<{|
type: 'boolean',
multiple: true,
short?: string,
default?: Array<boolean>,
|}
| {|
|}>
| $ReadOnly<{|
type: 'string',
multiple?: false,
short?: string,
default?: string,
|}
| {|
|}>
| $ReadOnly<{|
type: 'string',
multiple: true,
short?: string,
default?: Array<string>,
|};
|}>;
type util$ParseArgsOptionToValue<TOption> = TOption['type'] extends 'boolean'
? TOption['multiple'] extends true
@@ -3137,7 +3137,7 @@ declare module 'util' {
declare function stripVTControlCharacters(str: string): string;
declare function parseArgs<
TOptions: {[string]: util$ParseArgsOption} = {||},
TOptions: {+[string]: util$ParseArgsOption} = {||},
>(config: {|
args?: Array<string>,
options?: TOptions,
@@ -3995,13 +3995,16 @@ declare class Process extends events$EventEmitter {
initgroups?: (user: number | string, extra_group: number | string) => void;
kill(pid: number, signal?: string | number): void;
mainModule: Object;
memoryUsage(): {
arrayBuffers: number,
rss: number,
heapTotal: number,
heapUsed: number,
external: number,
...
memoryUsage: {
(): {
arrayBuffers: number,
rss: number,
heapTotal: number,
heapUsed: number,
external: number,
...
},
rss: () => number,
};
nextTick: <T>(cb: (...T) => mixed, ...T) => void;
pid: number;
-41
View File
@@ -1,41 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
* @format
*/
declare module 'electron-store' {
declare export type Schema = any;
declare export type Options = {
+name?: string,
defaults?: Object,
schema?: any,
migrations?: any,
beforeEachMigration?: any,
clearInvalidConfig?: boolean,
serialize?: any,
deserialize?: any,
accessPropertiesByDotNotation?: boolean,
watch?: boolean,
encryptionKey?: string | Buffer | $ReadOnlyArray<number>,
...
};
declare class ElectronStore {
constructor(options?: Options): this;
get(key: string): any;
get(key: string, defaultValue: any): any;
set(key: string, value: any): void;
set(object: Object): void;
has(key: string): boolean;
delete(key: string): void;
clear(): void;
}
declare module.exports: Class<ElectronStore>;
}
+1 -1
View File
@@ -86,7 +86,7 @@
"eslint-plugin-relay": "^1.8.3",
"fb-dotslash": "0.5.8",
"flow-api-translator": "0.32.0",
"flow-bin": "^0.281.0",
"flow-bin": "^0.285.0",
"glob": "^7.1.1",
"hermes-eslint": "0.32.0",
"hermes-transform": "0.32.0",
+2 -2
View File
@@ -1,5 +1,5 @@
@generated SignedSource<<0b54f75686e4893a5444839bf621a317>>
Git revision: 5a792db1225adda206313e9bf751198a1ca7851a
@generated SignedSource<<d090ed9a9e781c82884f22944254ed65>>
Git revision: 8b84a77b2c82c670886ef064dfc92d6bce83e579
Built with --nohooks: false
Is local checkout: false
Remote URL: https://github.com/facebook/react-native-devtools-frontend
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,71 +1,71 @@
#!/usr/bin/env dotslash
// @generated SignedSource<<9df662721aea6e3774a8677e2a6065e4>>
// @generated SignedSource<<80974ea6ac4427cf5fd9f14f6779b5c6>>
{
"name": "React Native DevTools",
"platforms": {
"linux-aarch64": {
"size": 116056584,
"size": 116072551,
"hash": "sha256",
"digest": "fac3912f10e3c373c874be6c4696f11e05cbaa754c116db6ea72189afae5efe6",
"digest": "3fd69eff02f4a41818a7ecb252ab0de449fa1f88fe0dd1de474bd15dd2e63856",
"providers": [
{
"type": "http",
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQPdlYV_w4y_wxd5Rs8c_F-soLMbY1zwXJjD-JM4TkOtOELyxZGyreTb6dTehp_X6e3qVFZUT05ETRs0MbvqYr4mqdb6dkG9DqNQEVv3TBoHwl7TYSygtHJEs3gXTAtMLYEKW9xXODJlVF-9II7fdTdHU7x7Pyf6NR6S3nv7sKUVD-zKpxF50L2TwUQ"
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQOBrLd2GhnOLBe4XfcroGD8Uh8odfhSuE5y5f6WSUCPAD93HJyyUbNxvU8rneUBXRi6SjftdBfU9ggRGlEdLVoTt3bp1bS8C370rWXH5oZIPkX87SovgSPmlCQygx8OQIUmShnoHVMSa3xArpSdXRdOvqNrwiOsmBkmxJXm_NycW502xfhcL6A6d38"
}
],
"format": "tar.gz",
"path": "React Native DevTools-linux-arm64/React Native DevTools"
},
"linux-x86_64": {
"size": 115929093,
"size": 115924495,
"hash": "sha256",
"digest": "06bbaeb62ae2e0081d184eba42b9f15be0d0b3f4901142b08a8a1430ff83e722",
"digest": "d154ffed0d8a66849da78baebf78e1323ecb8bbeda30d27b82a9b507196266c1",
"providers": [
{
"type": "http",
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQPENbrxrg0RF_TiyxSY_YVYqC1UfRKj_bMfKb3qHUsIhBlya8n3FkbfJqTXTNdqL4riFRulXS5ecXZprtvk_9kao-zY59r3kiTRwobzF0jnjM507_9UOnEHWzG5ZJYzQyOtS3kQmT0HwZabVj9qw38OB9mk-MPVCZIPZay2PRnIThBzpKDoOOP9"
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQPp7lTIJZPh1_Bz1ONneTDc_i5ScY8TLzgHe4DzvYz6e7z-QHdBKhUNbNVBInrYrJaPKPum8FOGcvFW9JsvPNpsdMiAbjivdKQPAEkGOZ-unSOqL1dPPjW-yZYSBGucXmcgQiXVaDhqG3Wcu04JLsFKlKb9QvAZZ-tyN72E8ndAQ0mgDyhzEhwB"
}
],
"format": "tar.gz",
"path": "React Native DevTools-linux-x64/React Native DevTools"
},
"macos-aarch64": {
"size": 110891603,
"size": 110891525,
"hash": "sha256",
"digest": "eeb9cc1399c0c38c429848dbf622f1b46e88d7d97788dcdc4c30a9fcce37705c",
"digest": "b05e1ae5528dcfcff5178d943d90128c9bf28ecd89da4dc303fd4ca748e5fc88",
"providers": [
{
"type": "http",
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQN9bd7nbXi-uF_MooJEiUL2jJVifMqgQxZ236aqbSdiJe5Uzjud5ANf0LDAl8GDVVRShd6x4B-gsZ-qRowH0qJikoGatQIkBgyzp4i8ors52etGOIIwdAxdNIng5Vtp441j2_N__btkJqlHcMMbbqvO8fg9oeYTlhMpOx3MLLWXIlG7ix5IFUDiYChf"
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQMfoVd8CCoqS0ETntAOKhks2FtIDsyoPEeJHLIc-bxPESxTSHf02xDSSM-vjCG9gBitObq3iZECz1LGwbYS9qrjqXdrf7oljIWzK-eszvQwDe0wzCsywqRXBtLlDBb5h8a1WxjA_scRqoGCDbvk7-XovnJNdmTX4vq0CFb8QUUcEz31sVQ_v5IRjDdF"
}
],
"format": "tar.gz",
"path": "React Native DevTools.app/Contents/MacOS/React Native DevTools"
},
"macos-x86_64": {
"size": 117770388,
"size": 117767014,
"hash": "sha256",
"digest": "a65e446e526502b267cbe6800ae031e4e1b5b0aca21412152a66ffe1d3a29410",
"digest": "6aa15f6dc13bea46503fcad1b9ba93b3007ea659abb63a2f6bf9b34c3abf834a",
"providers": [
{
"type": "http",
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQN29ukKLZS48QcCU-gms06YFnG-fxxDfrWTup-Z6KoIAP-QEu3sFzrpqeZz4g-jFsh3o-IIoHJsdbu4a2U7ROjPfWGguGJrPK8fdc3iV67Qw1_VAPU13dm0dI1DbSY50ah05wh43jdBG3LGCAYYJ-W8_mZMC3HqM2v-8KVd-DoPT4hOh1s9CCFgEQ"
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQM57KwrYx0XeV3M8JrX_StgCFVbMHB5L-ShQfzIdoG4jfz71Z7U7CtK5FZ72Uwzm9wmzx5n0-w_3P8DRd24gvMWUSaN8QNdyxIUxd1n0BqJRYsvsbc8w2YpNeWadcce701zV5dYgQg7PIjPzDSuhYWM_7ih_QtZIBIHUUjCtr0sJBUYZVaqBQag6Q"
}
],
"format": "tar.gz",
"path": "React Native DevTools.app/Contents/MacOS/React Native DevTools"
},
"windows-x86_64": {
"size": 125526370,
"size": 125530089,
"hash": "sha256",
"digest": "26b190c0f85249dee91999e020b8fe7ffd5c007458a2103ed3822558861dbe87",
"digest": "da1747672dd222b1389f6ad9e1c67778ea0bc4e8859ddee23222a92bcaaed48f",
"providers": [
{
"type": "http",
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQO0mdIJx1eYiSDJNiAZ2soaeECILayWnvOeiey-fpS4ydDTreAMfwL4QZ5GZo4-AsGwOXCSdF3hBMM2ufnvw6BDFg5UEiTc4DALJu7o6YBBG4wlVZbI-2kkaXd7u8RhBQPjmhsdcX3sDmCGmSr3WK9EkTRKStE2lb6ilOn-969h4dYWekwUUCSX"
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQN_2xTT04YUkfSPrA0LaBIHmjUTCCxBkiTgUpb3TUn02lpaFas2x3asL1LeHpZHlUmb_NiLE0PLZYg3T232fdIbmLaquPST7lQpsXDDMG-ykGK7-xxfK5CMU608Pd5Crw5YZBPF3O2PCtiIIcR85tWSqmyWYuoX-PnIhLnBWHjbpNcMcj9RkVqB"
}
],
"format": "tar.gz",
-1
View File
@@ -35,7 +35,6 @@
},
"devDependencies": {
"electron": "37.2.6",
"electron-store": "^8.2.0",
"semver": "^7.1.3"
},
"files": [
@@ -10,11 +10,9 @@
// $FlowFixMe[unclear-type] We have no Flow types for the Electron API.
const {BrowserWindow, Menu, app, shell, ipcMain} = require('electron') as any;
const Store = require('electron-store');
const path = require('path');
const util = require('util');
const appSettings = new Store();
const windowMetadata = new WeakMap<
typeof BrowserWindow,
$ReadOnly<{
@@ -55,11 +53,10 @@ function handleLaunchArgs(argv: string[]) {
}, 1000);
}
} else {
// Create the browser window.
frontendWindow = new BrowserWindow({
...(getSavedWindowPosition(windowKey) ?? {
width: 1200,
height: 600,
}),
width: 1200,
height: 600,
webPreferences: {
partition: 'persist:react-native-devtools',
preload: require.resolve('./preload.js'),
@@ -69,8 +66,6 @@ function handleLaunchArgs(argv: string[]) {
});
// Auto-hide the Windows/Linux menu bar
frontendWindow.setMenuBarVisibility(false);
// Observe and update saved window position
setupWindowResizeListeners(frontendWindow, windowKey);
}
// Open links in the default browser instead of in new Electron windows.
@@ -124,37 +119,6 @@ function configureAppMenu() {
Menu.setApplicationMenu(menu);
}
function getSavedWindowPosition(
windowKey: string,
): ?{width: number, height: number, x?: number, y?: number} {
return appSettings.get('windowArrangements', {})[windowKey];
}
function saveWindowPosition(
windowKey: string,
position: {x: number, y: number, width: number, height: number},
) {
const windowArrangements = appSettings.get('windowArrangements', {});
windowArrangements[windowKey] = position;
appSettings.set('windowArrangements', windowArrangements);
}
function setupWindowResizeListeners(
browserWindow: typeof BrowserWindow,
windowKey: string,
) {
const savePosition = () => {
if (!browserWindow.isDestroyed()) {
const [x, y] = browserWindow.getPosition();
const [width, height] = browserWindow.getSize();
saveWindowPosition(windowKey, {x, y, width, height});
}
};
browserWindow.on('moved', savePosition);
browserWindow.on('resized', savePosition);
browserWindow.on('closed', savePosition);
}
app.whenReady().then(() => {
handleLaunchArgs(process.argv.slice(app.isPackaged ? 1 : 2));
configureAppMenu();
@@ -25,7 +25,9 @@ app.setVersion(pkg.version + '-' + buildInfo.revision);
const {
values: {version = false},
} = util.parseArgs({
options: {version: {type: 'boolean'}},
options: {
version: {type: 'boolean'},
},
args: process.argv.slice(app.isPackaged ? 1 : 2),
strict: false,
});
@@ -372,12 +372,6 @@ export default class InspectorProxy implements InspectorProxyQueries {
this.#devices.set(deviceId, newDevice);
this.#logger?.info(
"Connection established to app='%s' on device='%s'.",
appName,
deviceName,
);
debug(
"Got new device connection: name='%s', app=%s, device=%s, via=%s",
deviceName,
@@ -450,7 +444,7 @@ export default class InspectorProxy implements InspectorProxyQueries {
);
socket.on('close', (code: number, reason: string) => {
this.#logger?.info(
debug(
"Connection closed to device='%s' for app='%s' with code='%s' and reason='%s'.",
deviceName,
appName,
@@ -526,7 +520,7 @@ export default class InspectorProxy implements InspectorProxyQueries {
throw new Error(INTERNAL_ERROR_MESSAGES.UNREGISTERED_DEVICE);
}
this.#logger?.info(
debug(
"Connection established to DevTools for app='%s' on device='%s'.",
device.getApp() || 'unknown',
device.getName() || 'unknown',
@@ -594,7 +588,7 @@ export default class InspectorProxy implements InspectorProxyQueries {
});
socket.on('close', (code: number, reason: string) => {
this.#logger?.info(
debug(
"Connection closed to DevTools for app='%s' on device='%s' with code='%s' and reason='%s'.",
device.getApp() || 'unknown',
device.getName() || 'unknown',
@@ -191,6 +191,14 @@ internal object DependencyUtils {
"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
}
@@ -242,7 +242,7 @@ internal fun readPackageJsonFile(
return packageJson?.let { JsonUtils.fromPackageJson(it) }
}
private const val HERMES_COMPILER_NPM_DIR = "node_modules/hermes-compiler/%OS-BIN%/"
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/"
@@ -165,8 +165,8 @@ class PathUtilsTest {
@Test
@WithOs(OS.MAC)
fun detectOSAwareHermesCommand_withHermesV1Enabled() {
tempFolder.newFolder("node_modules/hermes-compiler/osx-bin/")
val expected = tempFolder.newFile("node_modules/hermes-compiler/osx-bin/hermesc")
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())
@@ -47,7 +47,7 @@ function combineSchemas(
}
return merged;
},
{modules: {}},
{modules: {} /*:: as SchemaType['modules'] */},
);
return {
@@ -540,7 +540,7 @@ function buildEventEmitterSchema(
return {
name: eventemitterName,
optional: false,
optional: Boolean(property.optional),
typeAnnotation: {
type: 'EventEmitterTypeAnnotation',
typeAnnotation: eventTypeAnnotation,
@@ -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);
@@ -14,8 +14,10 @@ import FlatList, {type FlatListProps} from '../../Lists/FlatList';
import createAnimatedComponent from '../createAnimatedComponent';
import * as React from 'react';
// $FlowExpectedError[unclear-type]
export default (createAnimatedComponent(FlatList): component<ItemT = any>(
export default createAnimatedComponent(FlatList) as $FlowFixMe as component<
// $FlowExpectedError[unclear-type]
ItemT = any,
>(
ref?: React.RefSetter<FlatList<ItemT>>,
...props: AnimatedProps<FlatListProps<ItemT>>
));
);
@@ -14,9 +14,10 @@ import Image from '../../Image/Image';
import createAnimatedComponent from '../createAnimatedComponent';
import * as React from 'react';
export default (createAnimatedComponent(
(Image: $FlowFixMe),
): AnimatedComponentType<
export default (createAnimatedComponent<
$FlowFixMe,
React.ElementRef<typeof Image>,
>((Image: $FlowFixMe)): AnimatedComponentType<
React.ElementConfig<typeof Image>,
React.ElementRef<typeof Image>,
>);
@@ -15,7 +15,7 @@ import createAnimatedComponent from '../createAnimatedComponent';
import * as React from 'react';
// $FlowFixMe[incompatible-type]
export default (createAnimatedComponent(SectionList): component<
export default createAnimatedComponent(SectionList) as $FlowFixMe as component<
// $FlowExpectedError[unclear-type]
ItemT = any,
// $FlowExpectedError[unclear-type]
@@ -23,4 +23,4 @@ export default (createAnimatedComponent(SectionList): component<
>(
ref?: React.RefSetter<SectionList<ItemT, SectionT>>,
...props: AnimatedProps<SectionListProps<ItemT, SectionT>>
));
);
@@ -14,6 +14,10 @@ import Text, {type TextProps} from '../../Text/Text';
import createAnimatedComponent from '../createAnimatedComponent';
import * as React from 'react';
export default (createAnimatedComponent(
(Text: $FlowFixMe),
): AnimatedComponentType<TextProps, React.ElementRef<typeof Text>>);
export default (createAnimatedComponent<
$FlowFixMe,
React.ElementRef<typeof Text>,
>((Text: $FlowFixMe)): AnimatedComponentType<
TextProps,
React.ElementRef<typeof Text>,
>);
@@ -15,7 +15,8 @@ import View from '../../Components/View/View';
import createAnimatedComponent from '../createAnimatedComponent';
import * as React from 'react';
export default (createAnimatedComponent(View): AnimatedComponentType<
// $FlowFixMe[incompatible-type]
export default createAnimatedComponent(View) as AnimatedComponentType<
ViewProps,
React.ElementRef<typeof View>,
>);
>;
@@ -63,17 +63,29 @@ type PassThroughProps = $ReadOnly<{
passthroughAnimatedPropExplicitValues?: ViewProps | null,
}>;
export type AnimatedProps<Props: {...}> = {
[K in keyof Props]: K extends NonAnimatedProps
? Props[K]
: WithAnimatedValue<Props[K]>,
} & PassThroughProps;
type LooseOmit<O: interface {}, K: $Keys<$FlowFixMe>> = Pick<
O,
Exclude<$Keys<O>, K>,
>;
export type AnimatedBaseProps<Props: {...}> = {
[K in keyof Props]: K extends NonAnimatedProps
? Props[K]
: WithAnimatedValue<Props[K]>,
};
export type AnimatedProps<Props: {...}> = LooseOmit<
{
[K in keyof Props]: K extends NonAnimatedProps
? Props[K]
: WithAnimatedValue<Props[K]>,
},
'ref',
> &
PassThroughProps;
export type AnimatedBaseProps<Props: {...}> = LooseOmit<
{
[K in keyof Props]: K extends NonAnimatedProps
? Props[K]
: WithAnimatedValue<Props[K]>,
},
'ref',
>;
export type AnimatedComponentType<Props: {...}, +Instance = mixed> = component(
ref?: React.RefSetter<Instance>,
@@ -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,
@@ -1690,6 +1690,7 @@ class ScrollView extends React.Component<ScrollViewProps, ScrollViewState> {
return (
<StickyHeaderComponent
key={key}
/* $FlowFixMe[incompatible-type] */
ref={ref => this._setStickyHeaderRef(key, ref)}
nextHeaderLayoutY={this._headerLayoutYs.get(
this._getKeyForIndex(nextIndex, children),
@@ -44,7 +44,7 @@ interface Instance extends React.ElementRef<typeof Animated.View> {
}
const ScrollViewStickyHeader: component(
ref: React.RefSetter<Instance>,
ref?: React.RefSetter<Instance>,
...props: ScrollViewStickyHeaderProps
) = function ScrollViewStickyHeader({
ref: forwardedRef,
@@ -282,7 +282,7 @@ const ScrollViewStickyHeader: component(
const passthroughAnimatedPropExplicitValues =
isFabric && translateY != null
? {
style: {transform: [{translateY: translateY}]},
style: {transform: [{translateY}]},
}
: null;
@@ -303,20 +303,20 @@ const ScrollViewStickyHeader: component(
passthroughAnimatedPropExplicitValues
}>
{cloneElement(child, {
style: styles.fill, // We transfer the child style to the wrapper.
onLayout: undefined, // we call this manually through our this._onLayout
style: styles.fill, // We transfer the child style to the wrapper.
})}
</Animated.View>
);
};
const styles = StyleSheet.create({
header: {
zIndex: 10,
},
fill: {
flex: 1,
},
header: {
zIndex: 10,
},
});
export default ScrollViewStickyHeader;
@@ -47,15 +47,14 @@ class TouchableBounce extends React.Component<
_createPressabilityConfig(): PressabilityConfig {
return {
android_disableSound: this.props.touchSoundDisabled,
cancelable: !this.props.rejectResponderTermination,
disabled: this.props.disabled,
hitSlop: this.props.hitSlop,
delayLongPress: this.props.delayLongPress,
delayPressIn: this.props.delayPressIn,
delayPressOut: this.props.delayPressOut,
disabled: this.props.disabled,
hitSlop: this.props.hitSlop,
minPressDuration: 0,
pressRectOffset: this.props.pressRetentionOffset,
android_disableSound: this.props.touchSoundDisabled,
onBlur: event => {
if (Platform.isTV) {
this._bounceTo(1, 0.4, 0);
@@ -113,6 +112,7 @@ class TouchableBounce extends React.Component<
this.props.onPressOut(event);
}
},
pressRectOffset: this.props.pressRetentionOffset,
};
}
@@ -123,10 +123,10 @@ class TouchableBounce extends React.Component<
callback?: ?() => void,
) {
Animated.spring(this.state.scale, {
toValue,
velocity,
bounciness,
toValue,
useNativeDriver: true,
velocity,
}).start(callback);
}
@@ -230,6 +230,6 @@ export default (function TouchableBounceWrapper({
}) {
return <TouchableBounce {...props} hostRef={hostRef} />;
} as component(
ref: React.RefSetter<mixed>,
ref?: React.RefSetter<mixed>,
...props: $ReadOnly<Omit<TouchableBounceProps, 'hostRef'>>
));
@@ -21,12 +21,14 @@ const ViewNativeComponent: HostComponent<Props> =
}));
interface NativeCommands {
+focus: () => void;
+blur: () => void;
+hotspotUpdate: (viewRef: HostInstance, x: number, y: number) => void;
+setPressed: (viewRef: HostInstance, pressed: boolean) => void;
}
export const Commands: NativeCommands = codegenNativeCommands<NativeCommands>({
supportedCommands: ['hotspotUpdate', 'setPressed'],
supportedCommands: ['focus', 'blur', 'hotspotUpdate', 'setPressed'],
});
/**
+21 -21
View File
@@ -39,6 +39,24 @@ function DebuggingOverlay({
useImperativeHandle(
ref,
() => ({
clearElementsHighlight() {
if (!isNativeComponentReady) {
return;
}
if (nativeComponentRef.current != null) {
Commands.clearElementsHighlights(nativeComponentRef.current);
}
},
highlightElements(elements) {
if (!isNativeComponentReady) {
return;
}
if (nativeComponentRef.current != null) {
Commands.highlightElements(nativeComponentRef.current, elements);
}
},
highlightTraceUpdates(updates) {
if (!isNativeComponentReady) {
return;
@@ -55,24 +73,6 @@ function DebuggingOverlay({
);
}
},
highlightElements(elements) {
if (!isNativeComponentReady) {
return;
}
if (nativeComponentRef.current != null) {
Commands.highlightElements(nativeComponentRef.current, elements);
}
},
clearElementsHighlight() {
if (!isNativeComponentReady) {
return;
}
if (nativeComponentRef.current != null) {
Commands.clearElementsHighlights(nativeComponentRef.current);
}
},
}),
[],
);
@@ -95,14 +95,14 @@ function DebuggingOverlay({
const styles = StyleSheet.create({
overlay: {
position: 'absolute',
top: 0,
bottom: 0,
left: 0,
position: 'absolute',
right: 0,
top: 0,
},
});
export default DebuggingOverlay as component(
ref: React.RefSetter<DebuggingOverlayHandle>,
ref?: React.RefSetter<DebuggingOverlayHandle>,
);
+3 -6
View File
@@ -8,11 +8,8 @@
* @format
*/
import type {
AbstractImageAndroid,
AbstractImageIOS,
ImageType as ImageComponent,
} from './ImageTypes.flow';
import type {HostInstance} from '../..';
import type {AbstractImageAndroid, AbstractImageIOS} from './ImageTypes.flow';
import useMergeRefs from '../Utilities/useMergeRefs';
import * as React from 'react';
@@ -33,7 +30,7 @@ export function unstable_getImageComponentDecorator(): ?ImageComponentDecorator
return injectedImageComponentDecorator;
}
type ImageInstance = React.ElementRef<ImageComponent>;
type ImageInstance = HostInstance;
type ImageAttachedCallback = (
imageInstance: ImageInstance,
@@ -8,12 +8,11 @@
* @format
*/
import type {HostInstance} from '../..';
import type {RootTag} from '../Types/RootTagTypes';
import type {ResolvedAssetSource} from './AssetSourceResolver';
import type {ImageProps as ImagePropsType} from './ImageProps';
import type {ImageSource} from './ImageSource';
import typeof ImageViewNativeComponent from './ImageViewNativeComponent';
import typeof TextInlineImageNativeComponent from './TextInlineImageNativeComponent';
import * as React from 'react';
@@ -67,17 +66,14 @@ type ImageComponentStaticsAndroid = $ReadOnly<{
}>;
export type AbstractImageAndroid = component(
ref?: React.RefSetter<
| React.ElementRef<TextInlineImageNativeComponent>
| React.ElementRef<ImageViewNativeComponent>,
>,
ref?: React.RefSetter<HostInstance>,
...props: ImagePropsType
);
export type ImageAndroid = AbstractImageAndroid & ImageComponentStaticsAndroid;
export type AbstractImageIOS = component(
ref?: React.RefSetter<React.ElementRef<ImageViewNativeComponent>>,
ref?: React.RefSetter<HostInstance>,
...props: ImagePropsType
);
+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;
@@ -129,11 +129,13 @@ export function getWithFallback_DEPRECATED<Config: {...}>(
// `getRuntimeConfig == null` when static view configs are disabled
// If `setRuntimeConfigProvider` is not configured, use native reflection.
if (hasNativeViewConfig(name)) {
/* $FlowFixMe[incompatible-type] Extra ref prop */
return get<Config>(name, viewConfigProvider);
}
} else {
// If there is no runtime config, then the native component is unavailable.
if (getRuntimeConfig(name) != null) {
/* $FlowFixMe[incompatible-type] Extra ref prop */
return get<Config>(name, viewConfigProvider);
}
}
+15 -7
View File
@@ -14,29 +14,37 @@ import NativeDevLoadingView from './NativeDevLoadingView';
const COLOR_SCHEME = {
dark: {
refresh: {
backgroundColor: '#2584e8',
textColor: '#ffffff',
},
load: {
backgroundColor: '#fafafa',
textColor: '#242526',
},
},
default: {
refresh: {
backgroundColor: '#2584e8',
textColor: '#ffffff',
},
error: {
backgroundColor: '#1065AF',
textColor: '#ffffff',
},
},
default: {
load: {
backgroundColor: '#404040',
textColor: '#ffffff',
},
refresh: {
backgroundColor: '#2584e8',
textColor: '#ffffff',
},
error: {
backgroundColor: '#1065AF',
textColor: '#ffffff',
},
},
};
export default {
showMessage(message: string, type: 'load' | 'refresh') {
showMessage(message: string, type: 'load' | 'refresh' | 'error') {
if (NativeDevLoadingView) {
const colorScheme =
getColorScheme() === 'dark' ? COLOR_SCHEME.dark : COLOR_SCHEME.default;
+7 -4
View File
@@ -232,8 +232,6 @@ Error: ${e.message}`;
});
client.on('error', data => {
DevLoadingView.hide();
if (data.type === 'GraphNotFoundError') {
client.close();
setHMRUnavailableReason(
@@ -253,8 +251,6 @@ Error: ${e.message}`;
});
client.on('close', closeEvent => {
DevLoadingView.hide();
// https://www.rfc-editor.org/rfc/rfc6455.html#section-7.4.1
// https://www.rfc-editor.org/rfc/rfc6455.html#section-7.1.5
const isNormalOrUnsetCloseReason =
@@ -296,10 +292,17 @@ function setHMRUnavailableReason(reason: string) {
}
hmrUnavailableReason = reason;
const DevLoadingView = require('./DevLoadingView').default;
DevLoadingView.hide();
// We only want to show a warning if Fast Refresh is on *and* if we ever
// previously managed to connect successfully. We don't want to show
// the warning to native engineers who use cached bundles without Metro.
if (hmrClient.isEnabled() && didConnect) {
DevLoadingView.showMessage(
'Fast Refresh disconnected. Reload app to reconnect.',
'error',
);
console.warn(reason);
// (Not using the `warning` module to prevent a Buck cycle.)
}
+1 -1
View File
@@ -161,7 +161,7 @@ let reactJsInspectorTracing = RNTarget(
name: .reactJsInspectorTracing,
path: "ReactCommon/jsinspector-modern/tracing",
excludedPaths: ["tests"],
dependencies: [.reactNativeDependencies, .reactFeatureFlags, .jsi, .reactOSCompat]
dependencies: [.reactNativeDependencies, .reactFeatureFlags, .reactJsInspectorNetwork, .jsi, .reactOSCompat]
)
/// React-jsinspectornetwork.podspec
@@ -12,7 +12,7 @@
#import <React/RCTEventEmitter.h>
RCT_EXTERN void RCTEnableAppearancePreference(BOOL enabled);
RCT_EXTERN void RCTOverrideAppearancePreference(NSString *const);
RCT_EXTERN void RCTOverrideAppearancePreference(NSString *);
RCT_EXTERN void RCTUseKeyWindowForSystemStyle(BOOL useMainScreen);
RCT_EXTERN NSString *RCTCurrentOverrideAppearancePreference(void);
RCT_EXTERN NSString *RCTColorSchemePreference(UITraitCollection *traitCollection);
@@ -85,14 +85,6 @@ RCT_EXPORT_MODULE()
dispatch_time(DISPATCH_TIME_NOW, 0.2 * NSEC_PER_SEC), dispatch_get_main_queue(), self->_initialMessageBlock);
}
- (void)hideBannerAfter:(CGFloat)delay
{
// Cancel previous hide call after the delay.
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(hide) object:nil];
// Set new hide call after a delay.
[self performSelector:@selector(hide) withObject:nil afterDelay:delay];
}
- (void)showMessage:(NSString *)message color:(UIColor *)color backgroundColor:(UIColor *)backgroundColor
{
if (!RCTDevLoadingViewGetEnabled() || _hiding) {
@@ -128,6 +120,9 @@ RCT_EXPORT_MODULE()
self->_container = [[UIView alloc] init];
self->_container.backgroundColor = backgroundColor;
self->_container.translatesAutoresizingMaskIntoConstraints = NO;
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hide)];
[self->_container addGestureRecognizer:tapGesture];
self->_container.userInteractionEnabled = YES;
self->_label = [[UILabel alloc] init];
self->_label.translatesAutoresizingMaskIntoConstraints = NO;
@@ -158,8 +153,6 @@ RCT_EXPORT_MODULE()
[self->_label.centerXAnchor constraintEqualToAnchor:self->_container.centerXAnchor],
[self->_label.bottomAnchor constraintEqualToAnchor:self->_container.bottomAnchor constant:-5],
]];
[self hideBannerAfter:15.0];
});
}
@@ -365,11 +365,14 @@ RCT_EXPORT_MODULE()
handler:^(__unused UIAlertAction *action) {
[weakSelf setDefaultJSBundle];
}]];
[alertController addAction:[UIAlertAction actionWithTitle:@"Cancel"
style:UIAlertActionStyleCancel
handler:^(__unused UIAlertAction *action) {
return;
}]];
UIAlertAction *configCancelAction =
[UIAlertAction actionWithTitle:@"Cancel"
style:UIAlertActionStyleCancel
handler:^(__unused UIAlertAction *action) {
return;
}];
[configCancelAction setValue:[UIColor systemRedColor] forKey:@"titleTextColor"];
[alertController addAction:configCancelAction];
[RCTPresentedViewController() presentViewController:alertController animated:YES completion:NULL];
}]];
@@ -390,6 +393,11 @@ RCT_EXPORT_METHOD(show)
_actionSheet = [UIAlertController alertControllerWithTitle:@"React Native Dev Menu" message:nil preferredStyle:style];
NSAttributedString *title =
[[NSAttributedString alloc] initWithString:@"React Native Dev Menu"
attributes:@{NSFontAttributeName : [UIFont boldSystemFontOfSize:17]}];
[_actionSheet setValue:title forKey:@"_attributedTitle"];
NSArray<RCTDevMenuItem *> *items = [self _menuItemsToPresent];
for (RCTDevMenuItem *item in items) {
UIAlertAction *action = [UIAlertAction actionWithTitle:item.title
@@ -399,9 +407,11 @@ RCT_EXPORT_METHOD(show)
[_actionSheet addAction:action];
}
[_actionSheet addAction:[UIAlertAction actionWithTitle:@"Cancel"
style:UIAlertActionStyleCancel
handler:[self alertActionHandlerForDevItem:nil]]];
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel"
style:UIAlertActionStyleCancel
handler:[self alertActionHandlerForDevItem:nil]];
[cancelAction setValue:[UIColor systemRedColor] forKey:@"titleTextColor"];
[_actionSheet addAction:cancelAction];
_presentedItems = items;
[RCTPresentedViewController() presentViewController:_actionSheet animated:YES completion:nil];
@@ -650,7 +650,9 @@ const CGFloat BACKGROUND_COLOR_ZPOSITION = -1024.0f;
BOOL isPointInside = [self pointInside:point withEvent:event];
BOOL clipsToBounds = self.currentContainerView.clipsToBounds;
UIView *currentContainerView = self.currentContainerView;
BOOL clipsToBounds = currentContainerView.clipsToBounds;
clipsToBounds = clipsToBounds || _layoutMetrics.overflowInset == EdgeInsets{};
@@ -658,8 +660,8 @@ const CGFloat BACKGROUND_COLOR_ZPOSITION = -1024.0f;
return nil;
}
for (UIView *subview in [self.subviews reverseObjectEnumerator]) {
UIView *hitView = [subview hitTest:[subview convertPoint:point fromView:self] withEvent:event];
for (UIView *subview = nullptr in [currentContainerView.subviews reverseObjectEnumerator]) {
UIView *hitView = [subview hitTest:[subview convertPoint:point fromView:currentContainerView] withEvent:event];
if (hitView) {
return hitView;
}
@@ -859,7 +861,7 @@ static RCTBorderStyle RCTBorderStyleFromOutlineStyle(OutlineStyle outlineStyle)
if (_useCustomContainerView) {
if (!_containerView) {
_containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
_containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height)];
for (UIView *subview = nullptr in effectiveContentView.subviews) {
[_containerView addSubview:subview];
}
@@ -1540,6 +1542,62 @@ static NSString *RCTRecursiveAccessibilityLabel(UIView *view)
}
}
- (BOOL)canBecomeFirstResponder
{
return YES;
}
- (void)handleCommand:(const NSString *)commandName args:(const NSArray *)args
{
if ([commandName isEqualToString:@"focus"]) {
[self focus];
return;
}
if ([commandName isEqualToString:@"blur"]) {
[self blur];
return;
}
}
- (void)focus
{
[self becomeFirstResponder];
}
- (void)blur
{
[self resignFirstResponder];
}
#pragma mark - Focus Events
- (BOOL)becomeFirstResponder
{
if (![super becomeFirstResponder]) {
return NO;
}
if (_eventEmitter && ReactNativeFeatureFlags::enableImperativeFocus()) {
_eventEmitter->onFocus();
}
return YES;
}
- (BOOL)resignFirstResponder
{
if (![super resignFirstResponder]) {
return NO;
}
if (_eventEmitter && ReactNativeFeatureFlags::enableImperativeFocus()) {
_eventEmitter->onBlur();
}
return YES;
}
@end
#ifdef __cplusplus
@@ -61,7 +61,7 @@ RCT_EXTERN CGPathRef RCTPathCreateWithRoundedRect(
CGRect bounds,
RCTCornerInsets cornerInsets,
const CGAffineTransform *transform,
const BOOL inverted);
BOOL inverted);
/**
* Draw a CSS-compliant border as an image. You can determine if it's scalable
@@ -1892,6 +1892,7 @@ public final class com/facebook/react/devsupport/DefaultDevLoadingViewImplementa
public fun <init> (Lcom/facebook/react/devsupport/ReactInstanceDevHelper;)V
public fun hide ()V
public fun showMessage (Ljava/lang/String;)V
public fun showMessage (Ljava/lang/String;Ljava/lang/Double;Ljava/lang/Double;)V
public fun updateProgress (Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Integer;)V
}
@@ -2119,6 +2120,7 @@ public abstract interface class com/facebook/react/devsupport/interfaces/DevBund
public abstract interface class com/facebook/react/devsupport/interfaces/DevLoadingViewManager {
public abstract fun hide ()V
public abstract fun showMessage (Ljava/lang/String;)V
public abstract fun showMessage (Ljava/lang/String;Ljava/lang/Double;Ljava/lang/Double;)V
public abstract fun updateProgress (Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Integer;)V
}
@@ -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());
@@ -196,9 +196,11 @@ public class NativeAnimatedModule(reactContext: ReactApplicationContext) :
private val nodesManagerRef = AtomicReference<NativeAnimatedNodesManager?>()
@Volatile private var currentFrameNumber: Long = 0
private var batchingControlledByJS = false // TODO T71377544: delete
@Volatile private var currentBatchNumber: Long = 0 // frame number at last operations dispatch
@Volatile private var currentFrameNumber: Long = 0 // TODO T71377544: delete
@Volatile private var currentBatchNumber: Long = 0
private var initializedForFabric = false
private var initializedForNonFabric = false
@@ -280,19 +282,22 @@ public class NativeAnimatedModule(reactContext: ReactApplicationContext) :
var batchNumber = currentBatchNumber - 1
// The problem we're trying to solve here: we could be in the middle of queueing
// a batch of related animation operations when Fabric flushes a batch of MountItems.
// It's visually bad if we execute half of the animation ops and then wait another frame
// (or more) to execute the rest.
// See mFrameNumber. If the dispatchedFrameNumber drifts too far - that
// is, if no MountItems are scheduled for a while, which can happen if a tree
// is committed but there are no changes - bring these counts back in sync and
// execute any queued operations. This number is arbitrary, but we want it low
// enough that the user shouldn't be able to see this delay in most cases.
currentFrameNumber++
if ((currentFrameNumber - currentBatchNumber) > 2) {
currentBatchNumber = currentFrameNumber
batchNumber = currentBatchNumber
// TODO T71377544: delete this when the JS method is confirmed safe
if (!batchingControlledByJS) {
// The problem we're trying to solve here: we could be in the middle of queueing
// a batch of related animation operations when Fabric flushes a batch of MountItems.
// It's visually bad if we execute half of the animation ops and then wait another frame
// (or more) to execute the rest.
// See mFrameNumber. If the dispatchedFrameNumber drifts too far - that
// is, if no MountItems are scheduled for a while, which can happen if a tree
// is committed but there are no changes - bring these counts back in sync and
// execute any queued operations. This number is arbitrary, but we want it low
// enough that the user shouldn't be able to see this delay in most cases.
currentFrameNumber++
if ((currentFrameNumber - currentBatchNumber) > 2) {
currentBatchNumber = currentFrameNumber
batchNumber = currentBatchNumber
}
}
preOperations.executeBatch(batchNumber, nodesManager)
@@ -479,14 +484,14 @@ public class NativeAnimatedModule(reactContext: ReactApplicationContext) :
}
}
@Suppress("DEPRECATION")
override fun startOperationBatch() {
// no-op
batchingControlledByJS = true
currentBatchNumber++
}
@Suppress("DEPRECATION")
override fun finishOperationBatch() {
// no-op
batchingControlledByJS = false
currentBatchNumber++
}
override fun createAnimatedNode(tagDouble: Double, config: ReadableMap) {
@@ -774,8 +774,12 @@ public class NativeAnimatedNodesManager(
("Looks like animated nodes graph has ${reason}, there are $activeNodesCount but toposort visited only $updatedNodesCount")
)
if (eventListenerInitializedForFabric && cyclesDetected == 0) {
// TODO T71377544: investigate these SoftExceptions and see if we can remove entirely
// or fix the root cause
ReactSoftExceptionLogger.logSoftException(TAG, ReactNoCrashSoftException(ex))
} else if (eventListenerInitializedForFabric) {
// TODO T71377544: investigate these SoftExceptions and see if we can remove entirely
// or fix the root cause
ReactSoftExceptionLogger.logSoftException(TAG, ReactNoCrashSoftException(ex))
} else {
throw ex
@@ -98,13 +98,7 @@ public object DefaultNewArchitectureEntryPoint {
ReactNativeFeatureFlags.override(ReactNativeFeatureFlagsOverrides_RNOSS_Canary_Android())
}
ReleaseLevel.STABLE -> {
ReactNativeFeatureFlags.override(
ReactNativeFeatureFlagsOverrides_RNOSS_Stable_Android(
fabricEnabled,
bridgelessEnabled,
turboModulesEnabled,
)
)
ReactNativeFeatureFlags.override(ReactNativeFeatureFlagsOverrides_RNOSS_Stable_Android())
}
}
@@ -125,6 +119,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 +162,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 ""
}
}
@@ -33,10 +33,14 @@ public class DefaultDevLoadingViewImplementation(
private var devLoadingPopup: PopupWindow? = null
override fun showMessage(message: String) {
showMessage(message, color = null, backgroundColor = null)
}
override fun showMessage(message: String, color: Double?, backgroundColor: Double?) {
if (!isEnabled) {
return
}
UiThreadUtil.runOnUiThread { showInternal(message) }
UiThreadUtil.runOnUiThread { showInternal(message, color, backgroundColor) }
}
override fun updateProgress(status: String?, done: Int?, total: Int?) {
@@ -59,7 +63,7 @@ public class DefaultDevLoadingViewImplementation(
}
}
private fun showInternal(message: String) {
private fun showInternal(message: String, color: Double?, backgroundColor: Double?) {
if (devLoadingPopup?.isShowing == true) {
// already showing
return
@@ -84,13 +88,19 @@ public class DefaultDevLoadingViewImplementation(
currentActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
val view = inflater.inflate(R.layout.dev_loading_view, null) as TextView
view.text = message
if (color != null) {
view.setTextColor(color.toInt())
}
if (backgroundColor != null) {
view.setBackgroundColor(backgroundColor.toInt())
}
view.setOnClickListener { hideInternal() }
val popup =
PopupWindow(
view,
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
)
popup.isTouchable = false
popup.showAtLocation(currentActivity.window.decorView, Gravity.NO_GRAVITY, 0, topOffset)
devLoadingView = view
devLoadingPopup = popup
@@ -11,6 +11,8 @@ package com.facebook.react.devsupport.interfaces
public interface DevLoadingViewManager {
public fun showMessage(message: String)
public fun showMessage(message: String, color: Double?, backgroundColor: Double?)
public fun updateProgress(status: String?, done: Int?, total: Int?)
public fun hide()
@@ -821,6 +821,9 @@ public class SurfaceMountingManager {
@UnstableReactNativeAPI
public void experimental_prefetchResources(
int surfaceId, String componentName, MapBuffer params) {
if (isStopped()) {
return;
}
mViewManagerRegistry
.get(componentName)
.experimental_prefetchResources(
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<f089964c958dfcac00f83c3371ccbefc>>
* @generated SignedSource<<6b632ac7553ae149fa42a67efde5acfa>>
*/
/**
@@ -180,6 +180,12 @@ public object ReactNativeFeatureFlags {
@JvmStatic
public fun enableImagePrefetchingAndroid(): Boolean = accessor.enableImagePrefetchingAndroid()
/**
* When enabled, Android will build and initiate image prefetch requests on ImageShadowNode::layout and batch them together in a single JNI call
*/
@JvmStatic
public fun enableImagePrefetchingJNIBatchingAndroid(): Boolean = accessor.enableImagePrefetchingJNIBatchingAndroid()
/**
* When enabled, Android will initiate image prefetch requested on ImageShadowNode::layout on the UI thread
*/
@@ -192,6 +198,12 @@ public object ReactNativeFeatureFlags {
@JvmStatic
public fun enableImmediateUpdateModeForContentOffsetChanges(): Boolean = accessor.enableImmediateUpdateModeForContentOffsetChanges()
/**
* Enable ref.focus() and ref.blur() for all views, not just TextInput.
*/
@JvmStatic
public fun enableImperativeFocus(): Boolean = accessor.enableImperativeFocus()
/**
* This is to fix the issue with interop view manager where component descriptor lookup is causing ViewManager to preload.
*/
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<912dec895495052328e7e52b94a6738a>>
* @generated SignedSource<<c228bdbf6120b4715f49e03c04918a7c>>
*/
/**
@@ -45,8 +45,10 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
private var enableIOSTextBaselineOffsetPerLineCache: Boolean? = null
private var enableIOSViewClipToPaddingBoxCache: Boolean? = null
private var enableImagePrefetchingAndroidCache: Boolean? = null
private var enableImagePrefetchingJNIBatchingAndroidCache: Boolean? = null
private var enableImagePrefetchingOnUiThreadAndroidCache: Boolean? = null
private var enableImmediateUpdateModeForContentOffsetChangesCache: Boolean? = null
private var enableImperativeFocusCache: Boolean? = null
private var enableInteropViewManagerClassLookUpOptimizationIOSCache: Boolean? = null
private var enableLayoutAnimationsOnAndroidCache: Boolean? = null
private var enableLayoutAnimationsOnIOSCache: Boolean? = null
@@ -319,6 +321,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
return cached
}
override fun enableImagePrefetchingJNIBatchingAndroid(): Boolean {
var cached = enableImagePrefetchingJNIBatchingAndroidCache
if (cached == null) {
cached = ReactNativeFeatureFlagsCxxInterop.enableImagePrefetchingJNIBatchingAndroid()
enableImagePrefetchingJNIBatchingAndroidCache = cached
}
return cached
}
override fun enableImagePrefetchingOnUiThreadAndroid(): Boolean {
var cached = enableImagePrefetchingOnUiThreadAndroidCache
if (cached == null) {
@@ -337,6 +348,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
return cached
}
override fun enableImperativeFocus(): Boolean {
var cached = enableImperativeFocusCache
if (cached == null) {
cached = ReactNativeFeatureFlagsCxxInterop.enableImperativeFocus()
enableImperativeFocusCache = cached
}
return cached
}
override fun enableInteropViewManagerClassLookUpOptimizationIOS(): Boolean {
var cached = enableInteropViewManagerClassLookUpOptimizationIOSCache
if (cached == null) {
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<ba1e53d93b9fdaf298a034543bc44a57>>
* @generated SignedSource<<26dce1945df5641ab84cbca9eaf2b10f>>
*/
/**
@@ -78,10 +78,14 @@ public object ReactNativeFeatureFlagsCxxInterop {
@DoNotStrip @JvmStatic public external fun enableImagePrefetchingAndroid(): Boolean
@DoNotStrip @JvmStatic public external fun enableImagePrefetchingJNIBatchingAndroid(): Boolean
@DoNotStrip @JvmStatic public external fun enableImagePrefetchingOnUiThreadAndroid(): Boolean
@DoNotStrip @JvmStatic public external fun enableImmediateUpdateModeForContentOffsetChanges(): Boolean
@DoNotStrip @JvmStatic public external fun enableImperativeFocus(): Boolean
@DoNotStrip @JvmStatic public external fun enableInteropViewManagerClassLookUpOptimizationIOS(): Boolean
@DoNotStrip @JvmStatic public external fun enableLayoutAnimationsOnAndroid(): 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<<7601cbcde75ff19ef0fe67f6faef2549>>
* @generated SignedSource<<11051ece1b61fd4bf4ca003a3b7fc4f9>>
*/
/**
@@ -73,10 +73,14 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
override fun enableImagePrefetchingAndroid(): Boolean = false
override fun enableImagePrefetchingJNIBatchingAndroid(): Boolean = false
override fun enableImagePrefetchingOnUiThreadAndroid(): Boolean = false
override fun enableImmediateUpdateModeForContentOffsetChanges(): Boolean = false
override fun enableImperativeFocus(): Boolean = false
override fun enableInteropViewManagerClassLookUpOptimizationIOS(): Boolean = false
override fun enableLayoutAnimationsOnAndroid(): 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<<3a13f8e35423b634ed4ef46fbac3c1e9>>
* @generated SignedSource<<66fa583c37021750123a483ab0ccb030>>
*/
/**
@@ -49,8 +49,10 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
private var enableIOSTextBaselineOffsetPerLineCache: Boolean? = null
private var enableIOSViewClipToPaddingBoxCache: Boolean? = null
private var enableImagePrefetchingAndroidCache: Boolean? = null
private var enableImagePrefetchingJNIBatchingAndroidCache: Boolean? = null
private var enableImagePrefetchingOnUiThreadAndroidCache: Boolean? = null
private var enableImmediateUpdateModeForContentOffsetChangesCache: Boolean? = null
private var enableImperativeFocusCache: Boolean? = null
private var enableInteropViewManagerClassLookUpOptimizationIOSCache: Boolean? = null
private var enableLayoutAnimationsOnAndroidCache: Boolean? = null
private var enableLayoutAnimationsOnIOSCache: Boolean? = null
@@ -348,6 +350,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
return cached
}
override fun enableImagePrefetchingJNIBatchingAndroid(): Boolean {
var cached = enableImagePrefetchingJNIBatchingAndroidCache
if (cached == null) {
cached = currentProvider.enableImagePrefetchingJNIBatchingAndroid()
accessedFeatureFlags.add("enableImagePrefetchingJNIBatchingAndroid")
enableImagePrefetchingJNIBatchingAndroidCache = cached
}
return cached
}
override fun enableImagePrefetchingOnUiThreadAndroid(): Boolean {
var cached = enableImagePrefetchingOnUiThreadAndroidCache
if (cached == null) {
@@ -368,6 +380,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
return cached
}
override fun enableImperativeFocus(): Boolean {
var cached = enableImperativeFocusCache
if (cached == null) {
cached = currentProvider.enableImperativeFocus()
accessedFeatureFlags.add("enableImperativeFocus")
enableImperativeFocusCache = cached
}
return cached
}
override fun enableInteropViewManagerClassLookUpOptimizationIOS(): Boolean {
var cached = enableInteropViewManagerClassLookUpOptimizationIOSCache
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<<4feeb3c1789d8169dd93bee7ae1ff1ac>>
* @generated SignedSource<<dffc5db0f80501f6246f9d6087c6fb4a>>
*/
/**
@@ -25,5 +25,7 @@ public open class ReactNativeFeatureFlagsOverrides_RNOSS_Experimental_Android :
override fun enableAccessibilityOrder(): Boolean = true
override fun enableSwiftUIBasedFilters(): Boolean = true
override fun preventShadowTreeCommitExhaustion(): Boolean = true
}
@@ -7,16 +7,10 @@
package com.facebook.react.internal.featureflags
public class ReactNativeFeatureFlagsOverrides_RNOSS_Stable_Android(
private val fabricEnabled: Boolean,
private val bridgelessEnabled: Boolean,
private val turboModulesEnabled: Boolean,
) : ReactNativeNewArchitectureFeatureFlagsDefaults(bridgelessEnabled) {
override fun useFabricInterop(): Boolean = bridgelessEnabled || fabricEnabled
public class ReactNativeFeatureFlagsOverrides_RNOSS_Stable_Android() :
ReactNativeNewArchitectureFeatureFlagsDefaults() {
override fun enableFabricRenderer(): Boolean = bridgelessEnabled || fabricEnabled
override fun useTurboModules(): Boolean = bridgelessEnabled || turboModulesEnabled
override fun useFabricInterop(): Boolean = true
override fun useShadowNodeStateOnClone(): Boolean = true
}
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<143b568248e68033efaefc3f178ff6db>>
* @generated SignedSource<<f26998daf87c8b90c2ec822c8316b134>>
*/
/**
@@ -73,10 +73,14 @@ public interface ReactNativeFeatureFlagsProvider {
@DoNotStrip public fun enableImagePrefetchingAndroid(): Boolean
@DoNotStrip public fun enableImagePrefetchingJNIBatchingAndroid(): Boolean
@DoNotStrip public fun enableImagePrefetchingOnUiThreadAndroid(): Boolean
@DoNotStrip public fun enableImmediateUpdateModeForContentOffsetChanges(): Boolean
@DoNotStrip public fun enableImperativeFocus(): Boolean
@DoNotStrip public fun enableInteropViewManagerClassLookUpOptimizationIOS(): Boolean
@DoNotStrip public fun enableLayoutAnimationsOnAndroid(): Boolean
@@ -20,9 +20,11 @@ package com.facebook.react.internal.featureflags
* When the new architecture is enabled, we want to set the default values of the flags for Fabric,
* TurboModules and Bridgeless as enabled by default.
*/
public open class ReactNativeNewArchitectureFeatureFlagsDefaults(
private val newArchitectureEnabled: Boolean = true
) : ReactNativeFeatureFlagsDefaults() {
public open class ReactNativeNewArchitectureFeatureFlagsDefaults() :
ReactNativeFeatureFlagsDefaults() {
private val newArchitectureEnabled: Boolean = true
override fun enableBridgelessArchitecture(): Boolean = newArchitectureEnabled
override fun enableFabricRenderer(): Boolean = newArchitectureEnabled
@@ -31,7 +31,9 @@ internal class DevLoadingModule(reactContext: ReactApplicationContext) :
}
override fun showMessage(message: String, color: Double?, backgroundColor: Double?) {
UiThreadUtil.runOnUiThread { devLoadingViewManager?.showMessage(message) }
UiThreadUtil.runOnUiThread {
devLoadingViewManager?.showMessage(message, color, backgroundColor)
}
}
override fun hide() {
@@ -1,137 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.uimanager.layoutanimation
import android.view.View
import android.view.animation.AccelerateDecelerateInterpolator
import android.view.animation.AccelerateInterpolator
import android.view.animation.Animation
import android.view.animation.BaseInterpolator
import android.view.animation.DecelerateInterpolator
import android.view.animation.Interpolator
import android.view.animation.LinearInterpolator
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.common.annotations.VisibleForTesting
import com.facebook.react.common.annotations.internal.LegacyArchitecture
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger
import com.facebook.react.uimanager.IllegalViewOperationException
/**
* Class responsible for parsing and converting layout animation data into native [Animation] in
* order to animate layout when a valid configuration has been supplied by the application.
*/
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING,
)
internal abstract class AbstractLayoutAnimation {
var interpolator: Interpolator? = null
var delayMs: Int = 0
var animatedProperty: AnimatedPropertyType? = null
var durationMs: Int = 0
internal abstract fun isValid(): Boolean
/**
* Create an animation object for the current animation type, based on the view and final screen
* coordinates. If the application-supplied configuration does not specify an animation definition
* for this types, or if the animation definition is invalid, returns null.
*/
internal abstract fun createAnimationImpl(
view: View,
x: Int,
y: Int,
width: Int,
height: Int,
): Animation?
fun reset() {
animatedProperty = null
durationMs = 0
delayMs = 0
interpolator = null
}
fun initializeFromConfig(data: ReadableMap, globalDuration: Int) {
animatedProperty =
if (data.hasKey("property")) {
AnimatedPropertyType.fromString(data.getString("property").orEmpty())
} else {
null
}
durationMs = if (data.hasKey("duration")) data.getInt("duration") else globalDuration
delayMs = if (data.hasKey("delay")) data.getInt("delay") else 0
require(data.hasKey("type")) { "Missing interpolation type." }
interpolator =
getInterpolator(InterpolatorType.fromString(data.getString("type").orEmpty()), data)
if (!isValid()) {
throw IllegalViewOperationException("Invalid layout animation : $data")
}
}
/**
* Create an animation object to be used to animate the view, based on the animation config
* supplied at initialization time and the new view position and size.
*
* @param view the view to create the animation for
* @param x the new X position for the view
* @param y the new Y position for the view
* @param width the new width value for the view
* @param height the new height value for the view
*/
fun createAnimation(view: View, x: Int, y: Int, width: Int, height: Int): Animation? {
if (!isValid()) {
return null
}
return createAnimationImpl(view, x, y, width, height)?.apply {
val slowdownFactor = if (SLOWDOWN_ANIMATION_MODE) 10 else 1
duration = (durationMs * slowdownFactor).toLong()
startOffset = (delayMs * slowdownFactor).toLong()
interpolator = this@AbstractLayoutAnimation.interpolator
}
}
companion object {
init {
LegacyArchitectureLogger.assertLegacyArchitecture(
"AbstractLayoutAnimation",
LegacyArchitectureLogLevel.ERROR,
)
}
// Forces animation to be playing 10x slower, used for debug purposes.
private const val SLOWDOWN_ANIMATION_MODE = false
private val INTERPOLATOR: Map<InterpolatorType, BaseInterpolator> =
mapOf(
InterpolatorType.LINEAR to LinearInterpolator(),
InterpolatorType.EASE_IN to AccelerateInterpolator(),
InterpolatorType.EASE_OUT to DecelerateInterpolator(),
InterpolatorType.EASE_IN_EASE_OUT to AccelerateDecelerateInterpolator(),
)
@VisibleForTesting
fun getInterpolator(type: InterpolatorType, params: ReadableMap): Interpolator {
val interpolator =
if (type == InterpolatorType.SPRING) {
SimpleSpringInterpolator(SimpleSpringInterpolator.getSpringDamping(params))
} else {
INTERPOLATOR[type]
}
requireNotNull(interpolator) { "Missing interpolator for type : $type" }
return interpolator
}
}
}
@@ -1,42 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.uimanager.layoutanimation
import com.facebook.react.common.annotations.internal.LegacyArchitecture
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel
/**
* Enum representing the different view properties that can be used when animating layout for view
* creation.
*/
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING,
)
internal enum class AnimatedPropertyType {
OPACITY,
SCALE_X,
SCALE_Y,
SCALE_XY;
companion object {
@JvmStatic
fun fromString(name: String): AnimatedPropertyType {
return when (name) {
"opacity" -> OPACITY
"scaleX" -> SCALE_X
"scaleY" -> SCALE_Y
"scaleXY" -> SCALE_XY
else -> throw IllegalArgumentException("Unsupported animated property: $name")
}
}
}
}
@@ -1,96 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.uimanager.layoutanimation
import android.view.View
import android.view.animation.Animation
import android.view.animation.ScaleAnimation
import com.facebook.react.common.annotations.internal.LegacyArchitecture
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger
import com.facebook.react.uimanager.IllegalViewOperationException
/** Class responsible for default layout animation, i.e animation of view creation and deletion. */
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING,
)
internal abstract class BaseLayoutAnimation : AbstractLayoutAnimation() {
abstract fun isReverse(): Boolean
override fun isValid(): Boolean = durationMs > 0 && animatedProperty != null
override fun createAnimationImpl(view: View, x: Int, y: Int, width: Int, height: Int): Animation {
animatedProperty?.let {
return when (it) {
AnimatedPropertyType.OPACITY -> {
val fromValue = if (isReverse()) view.alpha else 0.0f
val toValue = if (isReverse()) 0.0f else view.alpha
OpacityAnimation(view, fromValue, toValue)
}
AnimatedPropertyType.SCALE_XY -> {
val fromValue = if (isReverse()) 1.0f else 0.0f
val toValue = if (isReverse()) 0.0f else 1.0f
ScaleAnimation(
fromValue,
toValue,
fromValue,
toValue,
Animation.RELATIVE_TO_SELF,
.5f,
Animation.RELATIVE_TO_SELF,
.5f,
)
}
AnimatedPropertyType.SCALE_X -> {
val fromValue = if (isReverse()) 1.0f else 0.0f
val toValue = if (isReverse()) 0.0f else 1.0f
ScaleAnimation(
fromValue,
toValue,
1f,
1f,
Animation.RELATIVE_TO_SELF,
.5f,
Animation.RELATIVE_TO_SELF,
0f,
)
}
AnimatedPropertyType.SCALE_Y -> {
val fromValue = if (isReverse()) 1.0f else 0.0f
val toValue = if (isReverse()) 0.0f else 1.0f
ScaleAnimation(
1f,
1f,
fromValue,
toValue,
Animation.RELATIVE_TO_SELF,
0f,
Animation.RELATIVE_TO_SELF,
.5f,
)
}
}
} ?: throw IllegalViewOperationException("Missing animated property from animation config")
}
private companion object {
init {
LegacyArchitectureLogger.assertLegacyArchitecture(
"BaseLayoutAnimation",
LegacyArchitectureLogLevel.ERROR,
)
}
}
}
@@ -1,43 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.uimanager.layoutanimation
import com.facebook.react.common.annotations.internal.LegacyArchitecture
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel
/**
* Enum representing the different interpolators that can be used in layout animation configuration.
*/
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING,
)
internal enum class InterpolatorType {
LINEAR,
EASE_IN,
EASE_OUT,
EASE_IN_EASE_OUT,
SPRING;
companion object {
@JvmStatic
fun fromString(name: String): InterpolatorType {
return when (name.lowercase()) {
"linear" -> LINEAR
"easein" -> EASE_IN
"easeout" -> EASE_OUT
"easeineaseout" -> EASE_IN_EASE_OUT
"spring" -> SPRING
else -> throw IllegalArgumentException("Unsupported interpolation type : $name")
}
}
}
}
@@ -9,19 +9,12 @@
package com.facebook.react.uimanager.layoutanimation
import android.util.SparseArray
import android.view.View
import android.view.ViewGroup
import android.view.animation.Animation
import android.view.animation.Animation.AnimationListener
import com.facebook.react.bridge.Callback
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.bridge.UiThreadUtil.assertOnUiThread
import com.facebook.react.bridge.UiThreadUtil.getUiThreadHandler
import com.facebook.react.common.annotations.internal.LegacyArchitecture
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger.assertLegacyArchitecture
import com.facebook.react.uimanager.layoutanimation.LayoutAnimationType.Companion.toString
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger
import javax.annotation.concurrent.NotThreadSafe
/**
@@ -36,75 +29,27 @@ import javax.annotation.concurrent.NotThreadSafe
level = DeprecationLevel.WARNING,
)
public open class LayoutAnimationController {
private val layoutCreateAnimation: AbstractLayoutAnimation = LayoutCreateAnimation()
private val layoutUpdateAnimation: AbstractLayoutAnimation = LayoutUpdateAnimation()
private val layoutDeleteAnimation: AbstractLayoutAnimation = LayoutDeleteAnimation()
private val layoutHandlers = SparseArray<LayoutHandlingAnimation?>(0)
private var shouldAnimateLayout = false
private var maxAnimationDuration: Long = -1
private var completionRunnable: Runnable? = null
public fun initializeFromConfig(config: ReadableMap?, completionCallback: Callback?) {
if (config == null) {
reset()
return
}
shouldAnimateLayout = false
val globalDuration = if (config.hasKey("duration")) config.getInt("duration") else 0
if (config.hasKey(toString(LayoutAnimationType.CREATE))) {
layoutCreateAnimation.initializeFromConfig(
config.getMap(toString(LayoutAnimationType.CREATE))!!,
globalDuration,
)
shouldAnimateLayout = true
}
if (config.hasKey(toString(LayoutAnimationType.UPDATE))) {
layoutUpdateAnimation.initializeFromConfig(
config.getMap(toString(LayoutAnimationType.UPDATE))!!,
globalDuration,
)
shouldAnimateLayout = true
}
if (config.hasKey(toString(LayoutAnimationType.DELETE))) {
layoutDeleteAnimation.initializeFromConfig(
config.getMap(toString(LayoutAnimationType.DELETE))!!,
globalDuration,
)
shouldAnimateLayout = true
}
if (shouldAnimateLayout && completionCallback != null) {
completionRunnable = Runnable { completionCallback.invoke(java.lang.Boolean.TRUE) }
}
LegacyArchitectureLogger.assertLegacyArchitecture(
"LayoutAnimationController",
LegacyArchitectureLogLevel.ERROR,
)
}
public open fun reset() {
layoutCreateAnimation.reset()
layoutUpdateAnimation.reset()
layoutDeleteAnimation.reset()
completionRunnable = null
shouldAnimateLayout = false
maxAnimationDuration = -1
for (i in layoutHandlers.size() - 1 downTo 0) {
val animation = layoutHandlers.valueAt(i)
if (!animation!!.isValid()) {
layoutHandlers.removeAt(i)
}
}
LegacyArchitectureLogger.assertLegacyArchitecture(
"LayoutAnimationController",
LegacyArchitectureLogLevel.ERROR,
)
}
public open fun shouldAnimateLayout(viewToAnimate: View?): Boolean {
// if view parent is null, skip animation: view have been clipped, we don't want animation to
// resume when view is re-attached to parent, which is the standard android animation behavior.
// If there's a layout handling animation going on, it should be animated nonetheless since the
// ongoing animation needs to be updated.
if (viewToAnimate == null) {
return false
}
return ((shouldAnimateLayout && viewToAnimate.parent != null) ||
layoutHandlers[viewToAnimate.id] != null)
LegacyArchitectureLogger.assertLegacyArchitecture(
"LayoutAnimationController",
LegacyArchitectureLogLevel.ERROR,
)
return false
}
/**
@@ -119,57 +64,10 @@ public open class LayoutAnimationController {
* @param height the new height value for the view
*/
public open fun applyLayoutUpdate(view: View, x: Int, y: Int, width: Int, height: Int) {
assertOnUiThread()
val reactTag = view.id
// Update an ongoing animation if possible, otherwise the layout update would be ignored as
// the existing animation would still animate to the old layout.
val existingAnimation = layoutHandlers[reactTag]
if (existingAnimation != null) {
if (!existingAnimation.isValid()) {
layoutHandlers.remove(reactTag)
} else {
existingAnimation.onLayoutUpdate(x, y, width, height)
return
}
}
// Determine which animation to use : if view is initially invisible, use create animation,
// otherwise use update animation. This approach is easier than maintaining a list of tags
// for recently created views.
val layoutAnimation =
if ((view.width == 0 || view.height == 0)) layoutCreateAnimation else layoutUpdateAnimation
val animation = layoutAnimation.createAnimation(view, x, y, width, height)
if (animation is LayoutHandlingAnimation) {
animation.setAnimationListener(
object : AnimationListener {
override fun onAnimationStart(animation: Animation) {
layoutHandlers.put(reactTag, animation as LayoutHandlingAnimation)
}
override fun onAnimationEnd(animation: Animation) {
layoutHandlers.remove(reactTag)
}
override fun onAnimationRepeat(animation: Animation) = Unit
}
)
} else {
view.layout(x, y, x + width, y + height)
}
if (animation != null) {
val animationDuration = animation.duration
if (animationDuration > maxAnimationDuration) {
maxAnimationDuration = animationDuration
scheduleCompletionCallback(animationDuration)
}
view.startAnimation(animation)
}
LegacyArchitectureLogger.assertLegacyArchitecture(
"LayoutAnimationController",
LegacyArchitectureLogLevel.ERROR,
)
}
/**
@@ -181,59 +79,9 @@ public open class LayoutAnimationController {
* view.
*/
public open fun deleteView(view: View, listener: LayoutAnimationListener) {
assertOnUiThread()
val animation =
layoutDeleteAnimation.createAnimation(view, view.left, view.top, view.width, view.height)
if (animation != null) {
disableUserInteractions(view)
animation.setAnimationListener(
object : AnimationListener {
override fun onAnimationStart(anim: Animation) = Unit
override fun onAnimationRepeat(anim: Animation) = Unit
override fun onAnimationEnd(anim: Animation) {
listener.onAnimationEnd()
}
}
)
val animationDuration = animation.duration
if (animationDuration > maxAnimationDuration) {
scheduleCompletionCallback(animationDuration)
maxAnimationDuration = animationDuration
}
view.startAnimation(animation)
} else {
listener.onAnimationEnd()
}
}
/** Disables user interactions for a view and all it's subviews. */
private fun disableUserInteractions(view: View) {
view.isClickable = false
if (view is ViewGroup) {
for (i in 0 until view.childCount) {
disableUserInteractions(view.getChildAt(i))
}
}
}
private fun scheduleCompletionCallback(delayMillis: Long) {
if (completionRunnable != null) {
val completionHandler = getUiThreadHandler()
completionHandler.removeCallbacks(completionRunnable!!)
completionHandler.postDelayed(completionRunnable!!, delayMillis)
}
}
private companion object {
init {
assertLegacyArchitecture("LayoutAnimationController", LegacyArchitectureLogLevel.ERROR)
}
LegacyArchitectureLogger.assertLegacyArchitecture(
"LayoutAnimationController",
LegacyArchitectureLogLevel.ERROR,
)
}
}
@@ -1,46 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.uimanager.layoutanimation
import com.facebook.react.common.annotations.internal.LegacyArchitecture
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger
/**
* Enum representing the different animation type that can be specified in layout animation config.
*/
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING,
)
internal enum class LayoutAnimationType {
CREATE,
UPDATE,
DELETE;
companion object {
init {
LegacyArchitectureLogger.assertLegacyArchitecture(
"LayoutAnimationType",
LegacyArchitectureLogLevel.ERROR,
)
}
@JvmStatic
fun toString(type: LayoutAnimationType): String {
return when (type) {
CREATE -> "create"
UPDATE -> "update"
DELETE -> "delete"
}
}
}
}
@@ -1,33 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.uimanager.layoutanimation
import com.facebook.react.common.annotations.internal.LegacyArchitecture
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger
/**
* Class responsible for handling layout view creation animation, applied to view whenever a valid
* config was supplied for the layout animation of CREATE type.
*/
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
internal class LayoutCreateAnimation : BaseLayoutAnimation() {
override fun isReverse(): Boolean = false
private companion object {
init {
LegacyArchitectureLogger.assertLegacyArchitecture(
"LayoutCreateAnimation",
LegacyArchitectureLogLevel.ERROR,
)
}
}
}
@@ -1,37 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.uimanager.layoutanimation
import com.facebook.react.common.annotations.internal.LegacyArchitecture
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger
/**
* Class responsible for handling layout view deletion animation, applied to view whenever a valid
* config was supplied for the layout animation of DELETE type.
*/
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING,
)
internal class LayoutDeleteAnimation : BaseLayoutAnimation() {
override fun isReverse(): Boolean = true
private companion object {
init {
LegacyArchitectureLogger.assertLegacyArchitecture(
"LayoutDeleteAnimation",
LegacyArchitectureLogLevel.ERROR,
)
}
}
}
@@ -1,42 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.uimanager.layoutanimation
import com.facebook.react.common.annotations.internal.LegacyArchitecture
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel
/** Interface for an animation type that takes care of updating the view layout. */
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING,
)
internal interface LayoutHandlingAnimation {
/**
* Notifies the animation of a layout update in case one occurs during the animation. This avoids
* animating the view to the old layout since it's no longer correct; instead the animation should
* update and do whatever it can so that the final layout is correct.
*
* @param x the new X position for the view
* @param y the new Y position for the view
* @param width the new width value for the view
* @param height the new height value for the view
*/
fun onLayoutUpdate(x: Int, y: Int, width: Int, height: Int)
/**
* Returns whether the animation is valid and should be used. Because layout animations generally
* hold {@link java.lang.ref.WeakReference<android.view.View>} objects, it's possible that the
* view has been garbage collected. In this case, the animation should not be used.
*
* @return true if the animation is valid and can be used, false otherwise
*/
fun isValid(): Boolean
}
@@ -1,66 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.uimanager.layoutanimation
import android.view.View
import android.view.animation.Animation
import android.view.animation.TranslateAnimation
import com.facebook.react.common.annotations.internal.LegacyArchitecture
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger
/**
* Class responsible for handling layout update animation, applied to view whenever a valid config
* was supplied for the layout animation of UPDATE type.
*/
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING,
)
internal class LayoutUpdateAnimation : AbstractLayoutAnimation() {
override fun isValid(): Boolean = durationMs > 0
override fun createAnimationImpl(
view: View,
x: Int,
y: Int,
width: Int,
height: Int,
): Animation? {
val animateLocation = view.x.toInt() != x || view.y.toInt() != y
val animateSize = view.width != width || view.height != height
return if (!animateLocation && !animateSize) {
null
} else if (animateLocation && !animateSize && USE_TRANSLATE_ANIMATION) {
// Use GPU-accelerated animation, however we loose the ability to resume interrupted
// animation where it was left off. We may be able to listen to animation interruption
// and set the layout manually in this case, so that next animation kicks off smoothly.
TranslateAnimation(view.x - x, 0f, view.y - y, 0f)
} else {
// Animation is sub-optimal for perf, but scale transformation can't be use in this case.
PositionAndSizeAnimation(view, x, y, width, height)
}
}
private companion object {
// We are currently not enabling translation GPU-accelerated animated, as it creates odd
// artifacts with native react scrollview. This needs to be investigated.
private const val USE_TRANSLATE_ANIMATION = false
init {
LegacyArchitectureLogger.assertLegacyArchitecture(
"LayoutUpdateAnimation",
LegacyArchitectureLogLevel.ERROR,
)
}
}
}
@@ -1,77 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.uimanager.layoutanimation
import android.view.View
import android.view.animation.Animation
import android.view.animation.Transformation
import com.facebook.react.common.annotations.VisibleForTesting
import com.facebook.react.common.annotations.internal.LegacyArchitecture
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger
import java.lang.ref.WeakReference
/**
* Animation responsible for updating opacity of a view. It should ideally use hardware texture to
* optimize rendering performances.
*/
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING,
)
internal class OpacityAnimation(view: View, private val startOpacity: Float, endOpacity: Float) :
Animation() {
private val viewRef = WeakReference(view)
private val deltaOpacity = endOpacity - startOpacity
init {
setAnimationListener(OpacityAnimationListener(view))
LegacyArchitectureLogger.assertLegacyArchitecture(
"OpacityAnimation",
LegacyArchitectureLogLevel.ERROR,
)
}
class OpacityAnimationListener(view: View) : Animation.AnimationListener {
private val viewRef = WeakReference(view)
private var layerTypeChanged = false
override fun onAnimationStart(animation: Animation) {
viewRef.get()?.let { view ->
if (view.hasOverlappingRendering() && view.layerType == View.LAYER_TYPE_NONE) {
layerTypeChanged = true
view.setLayerType(View.LAYER_TYPE_HARDWARE, null)
}
}
}
override fun onAnimationEnd(animation: Animation) {
viewRef.get()?.let { view ->
if (layerTypeChanged) {
view.setLayerType(View.LAYER_TYPE_NONE, null)
}
}
}
override fun onAnimationRepeat(animation: Animation) {
// do nothing
}
}
@VisibleForTesting
public override fun applyTransformation(interpolatedTime: Float, t: Transformation) {
viewRef.get()?.let { view -> view.alpha = startOpacity + deltaOpacity * interpolatedTime }
}
override fun willChangeBounds(): Boolean {
return false
}
}
@@ -1,98 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.uimanager.layoutanimation
import android.view.View
import android.view.animation.Animation
import android.view.animation.Transformation
import com.facebook.react.common.annotations.internal.LegacyArchitecture
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger
import java.lang.ref.WeakReference
/**
* Animation responsible for updating size and position of a view. We can't use scaling as view
* content may not necessarily stretch. As a result, this approach is inefficient because of layout
* passes occurring on every frame. What we might want to try to do instead is use a combined
* ScaleAnimation and TranslateAnimation.
*/
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING,
)
internal class PositionAndSizeAnimation(view: View, x: Int, y: Int, width: Int, height: Int) :
Animation(), LayoutHandlingAnimation {
private val viewRef = WeakReference(view)
private var startX = 0f
private var startY = 0f
private var deltaX = 0f
private var deltaY = 0f
private var startWidth = 0
private var startHeight = 0
private var deltaWidth = 0
private var deltaHeight = 0
init {
calculateAnimation(x, y, width, height)
}
override fun applyTransformation(interpolatedTime: Float, t: Transformation) {
viewRef.get()?.let { view ->
val newX = startX + deltaX * interpolatedTime
val newY = startY + deltaY * interpolatedTime
val newWidth = startWidth + deltaWidth * interpolatedTime
val newHeight = startHeight + deltaHeight * interpolatedTime
view.layout(
Math.round(newX),
Math.round(newY),
Math.round(newX + newWidth),
Math.round(newY + newHeight),
)
}
}
override fun onLayoutUpdate(x: Int, y: Int, width: Int, height: Int) {
// Layout changed during the animation, we should update our values so that the final layout
// is correct.
calculateAnimation(x, y, width, height)
}
override fun isValid(): Boolean {
return viewRef.get() != null
}
override fun willChangeBounds(): Boolean {
return true
}
private fun calculateAnimation(x: Int, y: Int, width: Int, height: Int) {
viewRef.get()?.let { view ->
startX = view.x - view.translationX
startY = view.y - view.translationY
startWidth = view.width
startHeight = view.height
deltaX = x - startX
deltaY = y - startY
deltaWidth = width - startWidth
deltaHeight = height - startHeight
}
}
private companion object {
init {
LegacyArchitectureLogger.assertLegacyArchitecture(
"PositionAndSizeAnimation",
LegacyArchitectureLogLevel.ERROR,
)
}
}
}
@@ -1,62 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.uimanager.layoutanimation
import android.view.animation.Interpolator
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.bridge.ReadableType
import com.facebook.react.common.annotations.internal.LegacyArchitecture
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger
import kotlin.math.pow
import kotlin.math.sin
/** Simple spring interpolator */
// TODO(7613736): Improve spring interpolator with friction and damping variable support
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING,
)
internal class SimpleSpringInterpolator @JvmOverloads constructor(springDamping: Float = FACTOR) :
Interpolator {
private val _springDamping: Float = springDamping
override fun getInterpolation(input: Float): Float =
// Using mSpringDamping in this equation is not really the exact mathematical springDamping,
// but a good approximation
// We need to replace this equation with the right Factor that accounts for damping and
// friction
(1 +
2.0.pow((-10 * input).toDouble()) *
sin((input - _springDamping / 4) * Math.PI * 2 / _springDamping))
.toFloat()
companion object {
init {
LegacyArchitectureLogger.assertLegacyArchitecture(
"SimpleSpringInterpolator",
LegacyArchitectureLogLevel.ERROR,
)
}
private const val FACTOR = 0.5f
const val PARAM_SPRING_DAMPING: String = "springDamping"
@JvmStatic
fun getSpringDamping(params: ReadableMap): Float =
if (params.getType(PARAM_SPRING_DAMPING) == ReadableType.Number) {
params.getDouble(PARAM_SPRING_DAMPING).toFloat()
} else {
FACTOR
}
}
}
@@ -158,7 +158,12 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
mOverflowInset = new Rect();
mActivelyScrolling = false;
mClippingRect = null;
mOverflow = Overflow.SCROLL;
// The default value for `overflow` is set to `Visible` in the Yoga style props.
mOverflow =
ReactNativeFeatureFlags.enablePropsUpdateReconciliationAndroid()
? Overflow.VISIBLE
: Overflow.SCROLL;
mDragging = false;
mPagingEnabled = false;
mPostTouchRunnable = null;
@@ -381,7 +386,12 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
mOverflow = Overflow.SCROLL;
} else {
@Nullable Overflow parsedOverflow = Overflow.fromString(overflow);
mOverflow = parsedOverflow == null ? Overflow.SCROLL : parsedOverflow;
mOverflow =
parsedOverflow == null
? (ReactNativeFeatureFlags.enablePropsUpdateReconciliationAndroid()
? Overflow.VISIBLE
: Overflow.SCROLL)
: parsedOverflow;
}
invalidate();
@@ -159,14 +159,19 @@ public class ReactScrollView extends ScrollView
mVirtualViewContainerState = null;
mActivelyScrolling = false;
mClippingRect = null;
mOverflow = Overflow.SCROLL;
// The default value for `overflow` is set to `Visible` in the Yoga style props.
mOverflow =
ReactNativeFeatureFlags.enablePropsUpdateReconciliationAndroid()
? Overflow.VISIBLE
: Overflow.SCROLL;
mDragging = false;
mPagingEnabled = false;
mPostTouchRunnable = null;
mRemoveClippedSubviews = false;
mScrollEnabled = true;
mSendMomentumEvents = false;
mFpsListener = null;
mScrollPerfTag = null;
mEndBackground = null;
mEndFillColor = Color.TRANSPARENT;
@@ -363,7 +368,12 @@ public class ReactScrollView extends ScrollView
mOverflow = Overflow.SCROLL;
} else {
@Nullable Overflow parsedOverflow = Overflow.fromString(overflow);
mOverflow = parsedOverflow == null ? Overflow.SCROLL : parsedOverflow;
mOverflow =
parsedOverflow == null
? (ReactNativeFeatureFlags.enablePropsUpdateReconciliationAndroid()
? Overflow.VISIBLE
: Overflow.SCROLL)
: parsedOverflow;
}
invalidate();
@@ -34,7 +34,6 @@ import com.facebook.react.views.text.ReactTypefaceUtils.parseFontStyle
import com.facebook.react.views.text.ReactTypefaceUtils.parseFontVariant
import com.facebook.react.views.text.ReactTypefaceUtils.parseFontWeight
import com.facebook.react.views.text.TextTransform.Companion.apply
import com.facebook.react.views.text.internal.ReactTextInlineImageShadowNode
import com.facebook.react.views.text.internal.span.CustomLetterSpacingSpan
import com.facebook.react.views.text.internal.span.CustomLineHeightSpan
import com.facebook.react.views.text.internal.span.CustomStyleSpan
@@ -523,6 +522,7 @@ public constructor(
while (i < length) {
val child: ReactShadowNode<*> = textShadowNode.getChildAt(i)
@Suppress("DEPRECATION")
if (child is ReactRawTextShadowNode) {
child.text?.let { sb.append(apply(it, textAttributes.textTransform)) }
} else if (child is ReactBaseTextShadowNode) {
@@ -535,7 +535,7 @@ public constructor(
inlineViews,
sb.length,
)
} else if (child is ReactTextInlineImageShadowNode) {
} else if (child is com.facebook.react.views.text.internal.ReactTextInlineImageShadowNode) {
// We make the image take up 1 character in the span and put a corresponding character
// into the text so that the image doesn't run over any following text.
sb.append(INLINE_VIEW_PLACEHOLDER)
@@ -5,6 +5,8 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.views.text.frescosupport
import android.content.Context
@@ -9,11 +9,18 @@
package com.facebook.react.views.text.internal
import com.facebook.react.common.annotations.internal.LegacyArchitecture
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel
import com.facebook.react.uimanager.LayoutShadowNode
import com.facebook.react.views.text.internal.span.TextInlineImageSpan
import com.facebook.yoga.YogaNode
/** Base class for [YogaNode]s that represent inline images. */
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING,
)
internal abstract class ReactTextInlineImageShadowNode : LayoutShadowNode() {
/**
* Build a [TextInlineImageSpan] from this node. This will be added to the TextView in place of
@@ -416,6 +416,14 @@ public open class ReactViewGroup public constructor(context: Context?) :
updateClippingToRect(clippingRect, excludedViews)
}
internal fun requestFocusFromJS() {
super.requestFocus(FOCUS_DOWN, null)
}
internal fun clearFocusFromJS() {
super.clearFocus()
}
override fun endViewTransition(view: View) {
super.endViewTransition(view)
childrenRemovedWhileTransitioning?.remove(view.id)
@@ -404,6 +404,8 @@ public open class ReactViewManager : ReactClippingViewManager<ReactViewGroup>()
when (commandId) {
HOTSPOT_UPDATE_KEY -> handleHotspotUpdate(root, args)
"setPressed" -> handleSetPressed(root, args)
"focus" -> handleFocus(root)
"blur" -> handleBlur(root)
else -> {}
}
}
@@ -428,4 +430,16 @@ public open class ReactViewManager : ReactClippingViewManager<ReactViewGroup>()
val y = args.getDouble(1).dpToPx()
root.drawableHotspotChanged(x, y)
}
private fun handleFocus(root: ReactViewGroup) {
if (ReactNativeFeatureFlags.enableImperativeFocus()) {
root.requestFocusFromJS()
}
}
private fun handleBlur(root: ReactViewGroup) {
if (ReactNativeFeatureFlags.enableImperativeFocus()) {
root.clearFocusFromJS()
}
}
}
@@ -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<<92c9aa29df580c6d12faa14e60b00e4f>>
* @generated SignedSource<<8e1821e9a153a4b725890cb4a7f262ee>>
*/
/**
@@ -189,6 +189,12 @@ class ReactNativeFeatureFlagsJavaProvider
return method(javaProvider_);
}
bool enableImagePrefetchingJNIBatchingAndroid() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableImagePrefetchingJNIBatchingAndroid");
return method(javaProvider_);
}
bool enableImagePrefetchingOnUiThreadAndroid() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableImagePrefetchingOnUiThreadAndroid");
@@ -201,6 +207,12 @@ class ReactNativeFeatureFlagsJavaProvider
return method(javaProvider_);
}
bool enableImperativeFocus() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableImperativeFocus");
return method(javaProvider_);
}
bool enableInteropViewManagerClassLookUpOptimizationIOS() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableInteropViewManagerClassLookUpOptimizationIOS");
@@ -606,6 +618,11 @@ bool JReactNativeFeatureFlagsCxxInterop::enableImagePrefetchingAndroid(
return ReactNativeFeatureFlags::enableImagePrefetchingAndroid();
}
bool JReactNativeFeatureFlagsCxxInterop::enableImagePrefetchingJNIBatchingAndroid(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::enableImagePrefetchingJNIBatchingAndroid();
}
bool JReactNativeFeatureFlagsCxxInterop::enableImagePrefetchingOnUiThreadAndroid(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::enableImagePrefetchingOnUiThreadAndroid();
@@ -616,6 +633,11 @@ bool JReactNativeFeatureFlagsCxxInterop::enableImmediateUpdateModeForContentOffs
return ReactNativeFeatureFlags::enableImmediateUpdateModeForContentOffsetChanges();
}
bool JReactNativeFeatureFlagsCxxInterop::enableImperativeFocus(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::enableImperativeFocus();
}
bool JReactNativeFeatureFlagsCxxInterop::enableInteropViewManagerClassLookUpOptimizationIOS(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::enableInteropViewManagerClassLookUpOptimizationIOS();
@@ -952,12 +974,18 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
makeNativeMethod(
"enableImagePrefetchingAndroid",
JReactNativeFeatureFlagsCxxInterop::enableImagePrefetchingAndroid),
makeNativeMethod(
"enableImagePrefetchingJNIBatchingAndroid",
JReactNativeFeatureFlagsCxxInterop::enableImagePrefetchingJNIBatchingAndroid),
makeNativeMethod(
"enableImagePrefetchingOnUiThreadAndroid",
JReactNativeFeatureFlagsCxxInterop::enableImagePrefetchingOnUiThreadAndroid),
makeNativeMethod(
"enableImmediateUpdateModeForContentOffsetChanges",
JReactNativeFeatureFlagsCxxInterop::enableImmediateUpdateModeForContentOffsetChanges),
makeNativeMethod(
"enableImperativeFocus",
JReactNativeFeatureFlagsCxxInterop::enableImperativeFocus),
makeNativeMethod(
"enableInteropViewManagerClassLookUpOptimizationIOS",
JReactNativeFeatureFlagsCxxInterop::enableInteropViewManagerClassLookUpOptimizationIOS),
@@ -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<<124d1378990fdd09a4d97f9103f81a6a>>
* @generated SignedSource<<5be2ec52bda638a1eac837c402149b9f>>
*/
/**
@@ -105,12 +105,18 @@ class JReactNativeFeatureFlagsCxxInterop
static bool enableImagePrefetchingAndroid(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static bool enableImagePrefetchingJNIBatchingAndroid(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static bool enableImagePrefetchingOnUiThreadAndroid(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static bool enableImmediateUpdateModeForContentOffsetChanges(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static bool enableImperativeFocus(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static bool enableInteropViewManagerClassLookUpOptimizationIOS(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
@@ -24,20 +24,18 @@ class JReactMarker : public facebook::jni::JavaClass<JReactMarker> {
private:
static void logMarker(const std::string& marker);
static void logMarker(const std::string& marker, const std::string& tag);
static void logMarker(
const std::string& marker,
const std::string& tag,
const int instanceKey);
static void
logMarker(const std::string& marker, const std::string& tag, int instanceKey);
static void logPerfMarker(
const ReactMarker::ReactMarkerId markerId,
ReactMarker::ReactMarkerId markerId,
const char* tag);
static void logPerfMarkerBridgeless(
const ReactMarker::ReactMarkerId markerId,
ReactMarker::ReactMarkerId markerId,
const char* tag);
static void logPerfMarkerWithInstanceKey(
const ReactMarker::ReactMarkerId markerId,
ReactMarker::ReactMarkerId markerId,
const char* tag,
const int instanceKey);
int instanceKey);
static void nativeLogMarker(
jni::alias_ref<jclass> /* unused */,
const std::string& markerNameStr,
@@ -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)"
)
}
}
@@ -1,157 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.uimanager.layoutanimation
import android.view.View
import android.view.animation.AccelerateDecelerateInterpolator
import android.view.animation.AccelerateInterpolator
import android.view.animation.Animation
import android.view.animation.DecelerateInterpolator
import android.view.animation.LinearInterpolator
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.uimanager.IllegalViewOperationException
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.assertThatThrownBy
import org.junit.After
import org.junit.Assert.assertThrows
import org.junit.Before
import org.junit.Test
import org.mockito.Mockito.mockConstruction
import org.mockito.kotlin.mock
import org.mockito.kotlin.whenever
class AbstractLayoutAnimationTest {
private lateinit var view: View
private lateinit var config: ReadableMap
private lateinit var animation: AbstractLayoutAnimation
private lateinit var mockedConstructors: List<AutoCloseable>
@Before
fun setUp() {
view = mock()
config = mock()
mockedConstructors =
listOf(
mockConstruction(LinearInterpolator::class.java),
mockConstruction(AccelerateInterpolator::class.java),
mockConstruction(DecelerateInterpolator::class.java),
mockConstruction(AccelerateDecelerateInterpolator::class.java),
)
animation =
object : AbstractLayoutAnimation() {
override fun isValid(): Boolean = true
override fun createAnimationImpl(
view: View,
x: Int,
y: Int,
width: Int,
height: Int,
): Animation = mock()
}
}
@After
fun tearDown() {
mockedConstructors.forEach { it.close() }
}
@Test
fun reset_clearsAnimationProperties() {
animation.reset()
assertThat(animation.animatedProperty).isNull()
assertThat(animation.durationMs).isEqualTo(0)
assertThat(animation.delayMs).isEqualTo(0)
assertThat(animation.interpolator).isNull()
}
@Test
fun createAnimation_returnsValidAnimation() {
val result = animation.createAnimation(view, 0, 0, 100, 100)
assertThat(result).isNotNull
}
@Test
fun initializeFromConfig_throwsIfTypeMissing() {
whenever(config.hasKey("type")).thenReturn(false)
val exception =
assertThrows(IllegalArgumentException::class.java) {
animation.initializeFromConfig(config, 300)
}
assertThat(exception.message).isEqualTo("Missing interpolation type.")
}
@Test
fun createAnimation_returnsNullWhenInvalid() {
val invalidAnimation =
object : AbstractLayoutAnimation() {
override fun isValid(): Boolean = false
override fun createAnimationImpl(
view: View,
x: Int,
y: Int,
width: Int,
height: Int,
): Animation = mock()
}
val result = invalidAnimation.createAnimation(view, 0, 0, 100, 100)
assertThat(result).isNull()
}
@Test
fun initializeFromConfig_throwsIfInvalidAnimation() {
whenever(config.hasKey("type")).thenReturn(true)
whenever(config.getString("type")).thenReturn("linear")
whenever(config.hasKey("duration")).thenReturn(true)
whenever(config.getInt("duration")).thenReturn(300)
val invalidAnimation =
object : AbstractLayoutAnimation() {
override fun isValid(): Boolean = false
override fun createAnimationImpl(
view: View,
x: Int,
y: Int,
width: Int,
height: Int,
): Animation = mock()
}
assertThatThrownBy { invalidAnimation.initializeFromConfig(config, 300) }
.isInstanceOf(IllegalViewOperationException::class.java)
.hasMessageContaining("Invalid layout animation")
}
@Test
fun getInterpolator_returnsSimpleSpringInterpolator() {
val type = InterpolatorType.SPRING
val params = mock<ReadableMap>()
whenever(params.hasKey("damping")).thenReturn(true)
whenever(params.getDouble("damping")).thenReturn(0.5)
val interpolator = AbstractLayoutAnimation.getInterpolator(type, params)
assertThat(interpolator).isInstanceOf(SimpleSpringInterpolator::class.java)
}
@Test
fun getInterpolator_returnsDefaultInterpolator() {
val type = InterpolatorType.LINEAR
val params = mock<ReadableMap>()
val interpolator = AbstractLayoutAnimation.getInterpolator(type, params)
assertThat(interpolator).isInstanceOf(LinearInterpolator::class.java)
}
}
@@ -1,47 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.uimanager.layoutanimation
import java.util.Locale
import org.assertj.core.api.Assertions.assertThat
import org.junit.Test
class InterpolatorTypeTest {
@Test
fun testCamelCase() {
assertThat(InterpolatorType.fromString("linear")).isEqualTo(InterpolatorType.LINEAR)
assertThat(InterpolatorType.fromString("easeIn")).isEqualTo(InterpolatorType.EASE_IN)
assertThat(InterpolatorType.fromString("easeOut")).isEqualTo(InterpolatorType.EASE_OUT)
assertThat(InterpolatorType.fromString("easeInEaseOut"))
.isEqualTo(InterpolatorType.EASE_IN_EASE_OUT)
assertThat(InterpolatorType.fromString("spring")).isEqualTo(InterpolatorType.SPRING)
}
@Test
fun testOtherCases() {
assertThat(InterpolatorType.fromString("EASEIN")).isEqualTo(InterpolatorType.EASE_IN)
assertThat(InterpolatorType.fromString("easeout")).isEqualTo(InterpolatorType.EASE_OUT)
assertThat(InterpolatorType.fromString("easeineaseout"))
.isEqualTo(InterpolatorType.EASE_IN_EASE_OUT)
}
@Test
fun testLocales() {
Locale.setDefault(Locale.forLanguageTag("tr-TR"))
assertThat(InterpolatorType.fromString("easeInEaseOut"))
.isEqualTo(InterpolatorType.EASE_IN_EASE_OUT)
}
@Test(expected = IllegalArgumentException::class)
@Throws(IllegalArgumentException::class)
fun testInvalidInterpolatorTypes() {
InterpolatorType.fromString("ease_in_ease_out")
}
}
@@ -1,105 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.uimanager.layoutanimation
import android.view.View
import android.view.animation.Transformation
import org.assertj.core.api.Assertions.assertThat
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.never
import org.mockito.kotlin.verify
import org.robolectric.RobolectricTestRunner
import org.robolectric.RuntimeEnvironment
@RunWith(RobolectricTestRunner::class)
class OpacityAnimationTest {
private lateinit var view: View
private lateinit var animation: OpacityAnimation
@Before
fun setUp() {
view = View(RuntimeEnvironment.getApplication())
}
@Test
fun applyTransformation_updatesAlphaCorrectly() {
val startOpacity = 0.5f
val endOpacity = 1.0f
animation = OpacityAnimation(view, startOpacity, endOpacity)
val transformation = Transformation()
animation.applyTransformation(0.0f, transformation)
assertThat(view.alpha).isEqualTo(0.5f)
animation.applyTransformation(0.5f, transformation)
assertThat(view.alpha).isEqualTo(0.75f)
animation.applyTransformation(1.0f, transformation)
assertThat(view.alpha).isEqualTo(1.0f)
}
@Test
fun willChangeBounds_returnsFalse() {
animation = OpacityAnimation(view, 0.5f, 1.0f)
assertThat(animation.willChangeBounds()).isFalse()
}
@Test
fun onAnimationStart_setsLayerTypeHardwareIfOverlappingRendering() {
val spyView: View = mock {
on { hasOverlappingRendering() } doReturn true
on { layerType } doReturn View.LAYER_TYPE_NONE
}
val listener = OpacityAnimation.OpacityAnimationListener(spyView)
listener.onAnimationStart(mock())
verify(spyView).setLayerType(View.LAYER_TYPE_HARDWARE, null)
}
@Test
fun onAnimationStart_doesNotChangeLayerTypeIfAlreadySet() {
val spyView: View = mock {
on { hasOverlappingRendering() } doReturn true
on { layerType } doReturn View.LAYER_TYPE_HARDWARE
}
val listener = OpacityAnimation.OpacityAnimationListener(spyView)
listener.onAnimationStart(mock())
verify(spyView, never()).setLayerType(View.LAYER_TYPE_HARDWARE, null)
}
@Test
fun onAnimationEnd_resetsLayerTypeIfChanged() {
val spyView: View = mock {
on { hasOverlappingRendering() } doReturn true
on { layerType } doReturn View.LAYER_TYPE_NONE
}
val listener = OpacityAnimation.OpacityAnimationListener(spyView)
listener.onAnimationStart(mock())
listener.onAnimationEnd(mock())
verify(spyView).setLayerType(View.LAYER_TYPE_NONE, null)
}
@Test
fun onAnimationRepeat_doesNothing() {
val listener = OpacityAnimation.OpacityAnimationListener(mock())
listener.onAnimationRepeat(mock())
// No assertions needed, just verifying it runs without errors
}
}
@@ -141,10 +141,10 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation {
}
std::string description() override {
return plain().description();
};
}
bool isInspectable() override {
return plain().isInspectable();
};
}
Instrumentation& instrumentation() override {
return *this;
}
@@ -160,45 +160,45 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation {
Runtime::PointerValue* cloneSymbol(const Runtime::PointerValue* pv) override {
return plain_.cloneSymbol(pv);
};
}
Runtime::PointerValue* cloneBigInt(const Runtime::PointerValue* pv) override {
return plain_.cloneBigInt(pv);
};
}
Runtime::PointerValue* cloneString(const Runtime::PointerValue* pv) override {
return plain_.cloneString(pv);
};
}
Runtime::PointerValue* cloneObject(const Runtime::PointerValue* pv) override {
return plain_.cloneObject(pv);
};
}
Runtime::PointerValue* clonePropNameID(
const Runtime::PointerValue* pv) override {
return plain_.clonePropNameID(pv);
};
}
PropNameID createPropNameIDFromAscii(const char* str, size_t length)
override {
return plain_.createPropNameIDFromAscii(str, length);
};
}
PropNameID createPropNameIDFromUtf8(const uint8_t* utf8, size_t length)
override {
return plain_.createPropNameIDFromUtf8(utf8, length);
};
}
PropNameID createPropNameIDFromString(const String& str) override {
return plain_.createPropNameIDFromString(str);
};
}
PropNameID createPropNameIDFromUtf16(const char16_t* utf16, size_t length)
override {
return plain_.createPropNameIDFromUtf16(utf16, length);
}
PropNameID createPropNameIDFromSymbol(const Symbol& sym) override {
return plain_.createPropNameIDFromSymbol(sym);
};
}
std::string utf8(const PropNameID& id) override {
return plain_.utf8(id);
};
}
bool compare(const PropNameID& a, const PropNameID& b) override {
return plain_.compare(a, b);
};
}
std::string symbolToString(const Symbol& sym) override {
return plain_.symbolToString(sym);
@@ -225,10 +225,10 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation {
String createStringFromAscii(const char* str, size_t length) override {
return plain_.createStringFromAscii(str, length);
};
}
String createStringFromUtf8(const uint8_t* utf8, size_t length) override {
return plain_.createStringFromUtf8(utf8, length);
};
}
String createStringFromUtf16(const char16_t* utf16, size_t length) override {
return plain_.createStringFromUtf16(utf16, length);
}
@@ -265,22 +265,22 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation {
Object createObject() override {
return plain_.createObject();
};
}
Object createObject(std::shared_ptr<HostObject> ho) override {
return plain_.createObject(
std::make_shared<DecoratedHostObject>(*this, std::move(ho)));
};
}
std::shared_ptr<HostObject> getHostObject(const jsi::Object& o) override {
std::shared_ptr<HostObject> dho = plain_.getHostObject(o);
return static_cast<DecoratedHostObject&>(*dho).plainHO_;
};
}
HostFunctionType& getHostFunction(const jsi::Function& f) override {
HostFunctionType& dhf = plain_.getHostFunction(f);
// This will fail if a cpp file including this header is not compiled
// with RTTI.
return dhf.target<DecoratedHostFunction>()->plainHF_;
};
}
bool hasNativeState(const Object& o) override {
return plain_.hasNativeState(o);
@@ -307,19 +307,19 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation {
Value getProperty(const Object& o, const PropNameID& name) override {
return plain_.getProperty(o, name);
};
}
Value getProperty(const Object& o, const String& name) override {
return plain_.getProperty(o, name);
};
}
Value getProperty(const Object& o, const Value& name) override {
return plain_.getProperty(o, name);
}
bool hasProperty(const Object& o, const PropNameID& name) override {
return plain_.hasProperty(o, name);
};
}
bool hasProperty(const Object& o, const String& name) override {
return plain_.hasProperty(o, name);
};
}
bool hasProperty(const Object& o, const Value& name) override {
return plain_.hasProperty(o, name);
}
@@ -328,11 +328,11 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation {
const PropNameID& name,
const Value& value) override {
plain_.setPropertyValue(o, name, value);
};
}
void setPropertyValue(const Object& o, const String& name, const Value& value)
override {
plain_.setPropertyValue(o, name, value);
};
}
void setPropertyValue(const Object& o, const Value& name, const Value& value)
override {
plain_.setPropertyValue(o, name, value);
@@ -352,53 +352,53 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation {
bool isArray(const Object& o) const override {
return plain_.isArray(o);
};
}
bool isArrayBuffer(const Object& o) const override {
return plain_.isArrayBuffer(o);
};
}
bool isFunction(const Object& o) const override {
return plain_.isFunction(o);
};
}
bool isHostObject(const jsi::Object& o) const override {
return plain_.isHostObject(o);
};
}
bool isHostFunction(const jsi::Function& f) const override {
return plain_.isHostFunction(f);
};
}
Array getPropertyNames(const Object& o) override {
return plain_.getPropertyNames(o);
};
}
WeakObject createWeakObject(const Object& o) override {
return plain_.createWeakObject(o);
};
}
Value lockWeakObject(const WeakObject& wo) override {
return plain_.lockWeakObject(wo);
};
}
Array createArray(size_t length) override {
return plain_.createArray(length);
};
}
ArrayBuffer createArrayBuffer(
std::shared_ptr<MutableBuffer> buffer) override {
return plain_.createArrayBuffer(std::move(buffer));
};
}
size_t size(const Array& a) override {
return plain_.size(a);
};
}
size_t size(const ArrayBuffer& ab) override {
return plain_.size(ab);
};
}
uint8_t* data(const ArrayBuffer& ab) override {
return plain_.data(ab);
};
}
Value getValueAtIndex(const Array& a, size_t i) override {
return plain_.getValueAtIndex(a, i);
};
}
void setValueAtIndexImpl(const Array& a, size_t i, const Value& value)
override {
plain_.setValueAtIndexImpl(a, i, value);
};
}
Function createFunctionFromHostFunction(
const PropNameID& name,
@@ -406,18 +406,18 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation {
HostFunctionType func) override {
return plain_.createFunctionFromHostFunction(
name, paramCount, DecoratedHostFunction(*this, std::move(func)));
};
}
Value call(
const Function& f,
const Value& jsThis,
const Value* args,
size_t count) override {
return plain_.call(f, jsThis, args, count);
};
}
Value callAsConstructor(const Function& f, const Value* args, size_t count)
override {
return plain_.callAsConstructor(f, args, count);
};
}
void setRuntimeDataImpl(
const UUID& uuid,
@@ -440,20 +440,20 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation {
bool strictEquals(const Symbol& a, const Symbol& b) const override {
return plain_.strictEquals(a, b);
};
}
bool strictEquals(const BigInt& a, const BigInt& b) const override {
return plain_.strictEquals(a, b);
};
}
bool strictEquals(const String& a, const String& b) const override {
return plain_.strictEquals(a, b);
};
}
bool strictEquals(const Object& a, const Object& b) const override {
return plain_.strictEquals(a, b);
};
}
bool instanceOf(const Object& o, const Function& f) override {
return plain_.instanceOf(o, f);
};
}
// jsi::Instrumentation methods
@@ -654,11 +654,11 @@ class WithRuntimeDecorator : public RuntimeDecorator<Plain, Base> {
std::string description() override {
Around around{with_};
return RD::description();
};
}
bool isInspectable() override {
Around around{with_};
return RD::isInspectable();
};
}
// The jsi:: prefix is necessary because MSVC compiler complains C2247:
// Instrumentation is not accessible because RuntimeDecorator uses private
@@ -673,35 +673,35 @@ class WithRuntimeDecorator : public RuntimeDecorator<Plain, Base> {
Runtime::PointerValue* cloneSymbol(const Runtime::PointerValue* pv) override {
Around around{with_};
return RD::cloneSymbol(pv);
};
}
Runtime::PointerValue* cloneBigInt(const Runtime::PointerValue* pv) override {
Around around{with_};
return RD::cloneBigInt(pv);
};
}
Runtime::PointerValue* cloneString(const Runtime::PointerValue* pv) override {
Around around{with_};
return RD::cloneString(pv);
};
}
Runtime::PointerValue* cloneObject(const Runtime::PointerValue* pv) override {
Around around{with_};
return RD::cloneObject(pv);
};
}
Runtime::PointerValue* clonePropNameID(
const Runtime::PointerValue* pv) override {
Around around{with_};
return RD::clonePropNameID(pv);
};
}
PropNameID createPropNameIDFromAscii(const char* str, size_t length)
override {
Around around{with_};
return RD::createPropNameIDFromAscii(str, length);
};
}
PropNameID createPropNameIDFromUtf8(const uint8_t* utf8, size_t length)
override {
Around around{with_};
return RD::createPropNameIDFromUtf8(utf8, length);
};
}
PropNameID createPropNameIDFromUtf16(const char16_t* utf16, size_t length)
override {
Around around{with_};
@@ -710,58 +710,58 @@ class WithRuntimeDecorator : public RuntimeDecorator<Plain, Base> {
PropNameID createPropNameIDFromString(const String& str) override {
Around around{with_};
return RD::createPropNameIDFromString(str);
};
}
PropNameID createPropNameIDFromSymbol(const Symbol& sym) override {
Around around{with_};
return RD::createPropNameIDFromSymbol(sym);
};
}
std::string utf8(const PropNameID& id) override {
Around around{with_};
return RD::utf8(id);
};
}
bool compare(const PropNameID& a, const PropNameID& b) override {
Around around{with_};
return RD::compare(a, b);
};
}
std::string symbolToString(const Symbol& sym) override {
Around around{with_};
return RD::symbolToString(sym);
};
}
BigInt createBigIntFromInt64(int64_t i) override {
Around around{with_};
return RD::createBigIntFromInt64(i);
};
}
BigInt createBigIntFromUint64(uint64_t i) override {
Around around{with_};
return RD::createBigIntFromUint64(i);
};
}
bool bigintIsInt64(const BigInt& bi) override {
Around around{with_};
return RD::bigintIsInt64(bi);
};
}
bool bigintIsUint64(const BigInt& bi) override {
Around around{with_};
return RD::bigintIsUint64(bi);
};
}
uint64_t truncate(const BigInt& bi) override {
Around around{with_};
return RD::truncate(bi);
};
}
String bigintToString(const BigInt& bi, int i) override {
Around around{with_};
return RD::bigintToString(bi, i);
};
}
String createStringFromAscii(const char* str, size_t length) override {
Around around{with_};
return RD::createStringFromAscii(str, length);
};
}
String createStringFromUtf8(const uint8_t* utf8, size_t length) override {
Around around{with_};
return RD::createStringFromUtf8(utf8, length);
};
}
String createStringFromUtf16(const char16_t* utf16, size_t length) override {
Around around{with_};
return RD::createStringFromUtf16(utf16, length);
@@ -801,7 +801,7 @@ class WithRuntimeDecorator : public RuntimeDecorator<Plain, Base> {
Value createValueFromJsonUtf8(const uint8_t* json, size_t length) override {
Around around{with_};
return RD::createValueFromJsonUtf8(json, length);
};
}
Object createObjectWithPrototype(const Value& prototype) override {
Around around{with_};
@@ -811,33 +811,33 @@ class WithRuntimeDecorator : public RuntimeDecorator<Plain, Base> {
Object createObject() override {
Around around{with_};
return RD::createObject();
};
}
Object createObject(std::shared_ptr<HostObject> ho) override {
Around around{with_};
return RD::createObject(std::move(ho));
};
}
std::shared_ptr<HostObject> getHostObject(const jsi::Object& o) override {
Around around{with_};
return RD::getHostObject(o);
};
}
HostFunctionType& getHostFunction(const jsi::Function& f) override {
Around around{with_};
return RD::getHostFunction(f);
};
}
bool hasNativeState(const Object& o) override {
Around around{with_};
return RD::hasNativeState(o);
};
}
std::shared_ptr<NativeState> getNativeState(const Object& o) override {
Around around{with_};
return RD::getNativeState(o);
};
}
void setNativeState(const Object& o, std::shared_ptr<NativeState> state)
override {
Around around{with_};
RD::setNativeState(o, state);
};
}
void setPrototypeOf(const Object& object, const Value& prototype) override {
Around around{with_};
@@ -852,11 +852,11 @@ class WithRuntimeDecorator : public RuntimeDecorator<Plain, Base> {
Value getProperty(const Object& o, const PropNameID& name) override {
Around around{with_};
return RD::getProperty(o, name);
};
}
Value getProperty(const Object& o, const String& name) override {
Around around{with_};
return RD::getProperty(o, name);
};
}
Value getProperty(const Object& o, const Value& name) override {
Around around{with_};
return RD::getProperty(o, name);
@@ -864,11 +864,11 @@ class WithRuntimeDecorator : public RuntimeDecorator<Plain, Base> {
bool hasProperty(const Object& o, const PropNameID& name) override {
Around around{with_};
return RD::hasProperty(o, name);
};
}
bool hasProperty(const Object& o, const String& name) override {
Around around{with_};
return RD::hasProperty(o, name);
};
}
bool hasProperty(const Object& o, const Value& name) override {
Around around{with_};
return RD::hasProperty(o, name);
@@ -879,12 +879,12 @@ class WithRuntimeDecorator : public RuntimeDecorator<Plain, Base> {
const Value& value) override {
Around around{with_};
RD::setPropertyValue(o, name, value);
};
}
void setPropertyValue(const Object& o, const String& name, const Value& value)
override {
Around around{with_};
RD::setPropertyValue(o, name, value);
};
}
void setPropertyValue(const Object& o, const Value& name, const Value& value)
override {
Around around{with_};
@@ -909,66 +909,66 @@ class WithRuntimeDecorator : public RuntimeDecorator<Plain, Base> {
bool isArray(const Object& o) const override {
Around around{with_};
return RD::isArray(o);
};
}
bool isArrayBuffer(const Object& o) const override {
Around around{with_};
return RD::isArrayBuffer(o);
};
}
bool isFunction(const Object& o) const override {
Around around{with_};
return RD::isFunction(o);
};
}
bool isHostObject(const jsi::Object& o) const override {
Around around{with_};
return RD::isHostObject(o);
};
}
bool isHostFunction(const jsi::Function& f) const override {
Around around{with_};
return RD::isHostFunction(f);
};
}
Array getPropertyNames(const Object& o) override {
Around around{with_};
return RD::getPropertyNames(o);
};
}
WeakObject createWeakObject(const Object& o) override {
Around around{with_};
return RD::createWeakObject(o);
};
}
Value lockWeakObject(const WeakObject& wo) override {
Around around{with_};
return RD::lockWeakObject(wo);
};
}
Array createArray(size_t length) override {
Around around{with_};
return RD::createArray(length);
};
}
ArrayBuffer createArrayBuffer(
std::shared_ptr<MutableBuffer> buffer) override {
return RD::createArrayBuffer(std::move(buffer));
};
}
size_t size(const Array& a) override {
Around around{with_};
return RD::size(a);
};
}
size_t size(const ArrayBuffer& ab) override {
Around around{with_};
return RD::size(ab);
};
}
uint8_t* data(const ArrayBuffer& ab) override {
Around around{with_};
return RD::data(ab);
};
}
Value getValueAtIndex(const Array& a, size_t i) override {
Around around{with_};
return RD::getValueAtIndex(a, i);
};
}
void setValueAtIndexImpl(const Array& a, size_t i, const Value& value)
override {
Around around{with_};
RD::setValueAtIndexImpl(a, i, value);
};
}
Function createFunctionFromHostFunction(
const PropNameID& name,
@@ -977,7 +977,7 @@ class WithRuntimeDecorator : public RuntimeDecorator<Plain, Base> {
Around around{with_};
return RD::createFunctionFromHostFunction(
name, paramCount, std::move(func));
};
}
Value call(
const Function& f,
const Value& jsThis,
@@ -985,12 +985,12 @@ class WithRuntimeDecorator : public RuntimeDecorator<Plain, Base> {
size_t count) override {
Around around{with_};
return RD::call(f, jsThis, args, count);
};
}
Value callAsConstructor(const Function& f, const Value* args, size_t count)
override {
Around around{with_};
return RD::callAsConstructor(f, args, count);
};
}
// Private data for managing scopes.
Runtime::ScopeState* pushScope() override {
@@ -1005,31 +1005,31 @@ class WithRuntimeDecorator : public RuntimeDecorator<Plain, Base> {
bool strictEquals(const Symbol& a, const Symbol& b) const override {
Around around{with_};
return RD::strictEquals(a, b);
};
}
bool strictEquals(const BigInt& a, const BigInt& b) const override {
Around around{with_};
return RD::strictEquals(a, b);
};
}
bool strictEquals(const String& a, const String& b) const override {
Around around{with_};
return RD::strictEquals(a, b);
};
}
bool strictEquals(const Object& a, const Object& b) const override {
Around around{with_};
return RD::strictEquals(a, b);
};
}
bool instanceOf(const Object& o, const Function& f) override {
Around around{with_};
return RD::instanceOf(o, f);
};
}
void setExternalMemoryPressure(const jsi::Object& obj, size_t amount)
override {
Around around{with_};
RD::setExternalMemoryPressure(obj, amount);
};
}
void setRuntimeDataImpl(
const UUID& uuid,
@@ -13,13 +13,11 @@ namespace facebook::react::jsinspector_modern::cdp::network {
namespace {
folly::dynamic headersToDynamic(const std::optional<Headers>& headers) {
folly::dynamic headersToDynamic(const Headers& headers) {
folly::dynamic result = folly::dynamic::object;
if (headers) {
for (const auto& [key, value] : *headers) {
result[key] = value;
}
for (const auto& [key, value] : headers) {
result[key] = value;
}
return result;
@@ -41,14 +39,14 @@ folly::dynamic Request::toDynamic() const {
/* static */ Response Response::fromInputParams(
const std::string& url,
uint16_t status,
const std::optional<Headers>& headers,
const Headers& headers,
int encodedDataLength) {
return {
.url = url,
.status = status,
.statusText = httpReasonPhrase(status),
.headers = headers,
.mimeType = mimeTypeFromHeaders(headers.value_or(Headers())),
.mimeType = mimeTypeFromHeaders(headers),
.encodedDataLength = encodedDataLength,
};
}
@@ -24,7 +24,7 @@ using Headers = std::map<std::string, std::string>;
struct Request {
std::string url;
std::string method;
std::optional<Headers> headers;
Headers headers;
std::optional<std::string> postData;
folly::dynamic toDynamic() const;
@@ -37,7 +37,7 @@ struct Response {
std::string url;
uint16_t status;
std::string statusText;
std::optional<Headers> headers;
Headers headers;
std::string mimeType;
int encodedDataLength;
@@ -48,7 +48,7 @@ struct Response {
static Response fromInputParams(
const std::string& url,
uint16_t status,
const std::optional<Headers>& headers,
const Headers& headers,
int encodedDataLength);
folly::dynamic toDynamic() const;
@@ -12,6 +12,8 @@
namespace facebook::react::jsinspector_modern {
using Headers = std::map<std::string, std::string>;
/**
* Get the HTTP reason phrase for a given status code (RFC 9110).
*/
@@ -21,7 +23,6 @@ std::string httpReasonPhrase(uint16_t status);
* Get the MIME type for a response based on the 'Content-Type' header. If
* the header is not present, returns 'application/octet-stream'.
*/
std::string mimeTypeFromHeaders(
const std::map<std::string, std::string>& headers);
std::string mimeTypeFromHeaders(const Headers& headers);
} // namespace facebook::react::jsinspector_modern
@@ -18,6 +18,7 @@ target_include_directories(jsinspector_tracing PUBLIC ${REACT_COMMON_DIR})
target_link_libraries(jsinspector_tracing
folly_runtime
jsinspector_network
oscompat
react_timing
)
@@ -9,6 +9,8 @@
#include "Timing.h"
#include "TraceEventSerializer.h"
#include <jsinspector-modern/network/CdpNetwork.h>
#include <jsinspector-modern/network/HttpUtils.h>
#include <oscompat/OSCompat.h>
#include <react/timing/primitives.h>
@@ -16,9 +18,12 @@
#include <mutex>
using namespace facebook::react;
namespace facebook::react::jsinspector_modern::tracing {
namespace {
/**
* Instead of validating that the indicated duration is positive, we can ensure
* the value is sensible (less than 1 seccond doesn't make much sense).
@@ -31,6 +36,7 @@ ThreadId getCurrentThreadId() {
oscompat::getCurrentThreadId();
return CURRENT_THREAD_ID;
}
} // namespace
PerformanceTracer& PerformanceTracer::getInstance() {
@@ -84,6 +90,7 @@ std::optional<std::vector<TraceEvent>> PerformanceTracer::stopTracing() {
tracingAtomic_ = false;
performanceMeasureCount_ = 0;
alreadyEmittedEntryForComponentsTrackOrdering_ = false;
events = collectEventsAndClearBuffers(currentTraceEndTime);
}
@@ -232,15 +239,12 @@ void PerformanceTracer::reportEventLoopMicrotasks(
});
}
void PerformanceTracer::reportResourceTiming(
const std::string& requestId,
void PerformanceTracer::reportResourceSendRequest(
const std::string& devtoolsRequestId,
HighResTimeStamp start,
const std::string& url,
HighResTimeStamp fetchStart,
HighResTimeStamp responseStart,
HighResTimeStamp responseEnd,
int statusCode,
const std::string& requestMethod,
const std::string& resourceType) {
const Headers& headers) {
if (!tracingAtomic_) {
return;
}
@@ -250,28 +254,67 @@ void PerformanceTracer::reportResourceTiming(
return;
}
enqueueEvent(PerformanceTracerResourceWillSendRequest{
.requestId = requestId,
.start = fetchStart,
.threadId = getCurrentThreadId(),
});
auto resourceType =
jsinspector_modern::cdp::network::resourceTypeFromMimeType(
jsinspector_modern::mimeTypeFromHeaders(headers));
enqueueEvent(PerformanceTracerResourceSendRequest{
.requestId = requestId,
.requestId = devtoolsRequestId,
.url = url,
.start = fetchStart,
.start = start,
.requestMethod = requestMethod,
.resourceType = resourceType,
.threadId = getCurrentThreadId(),
});
}
void PerformanceTracer::reportResourceReceiveResponse(
const std::string& devtoolsRequestId,
HighResTimeStamp start,
int statusCode,
const Headers& headers,
int encodedDataLength,
folly::dynamic timingData) {
if (!tracingAtomic_) {
return;
}
std::lock_guard<std::mutex> lock(mutex_);
if (!tracingAtomic_) {
return;
}
enqueueEvent(PerformanceTracerResourceReceiveResponse{
.requestId = requestId,
.start = responseStart,
.requestId = devtoolsRequestId,
.start = start,
.encodedDataLength = encodedDataLength,
.headers = headers,
.mimeType = jsinspector_modern::mimeTypeFromHeaders(headers),
.protocol = "h2",
.statusCode = statusCode,
.timing = std::move(timingData),
.threadId = getCurrentThreadId(),
});
}
void PerformanceTracer::reportResourceFinish(
const std::string& devtoolsRequestId,
HighResTimeStamp start,
int encodedDataLength,
int decodedBodyLength) {
if (!tracingAtomic_) {
return;
}
std::lock_guard<std::mutex> lock(mutex_);
if (!tracingAtomic_) {
return;
}
enqueueEvent(PerformanceTracerResourceFinish{
.requestId = requestId,
.start = responseEnd,
.requestId = devtoolsRequestId,
.start = start,
.encodedDataLength = encodedDataLength,
.decodedBodyLength = decodedBodyLength,
.threadId = getCurrentThreadId(),
});
}
@@ -508,11 +551,8 @@ void PerformanceTracer::enqueueTraceEventsFromPerformanceTracerEvent(
});
},
[&](PerformanceTracerEventTimeStamp&& event) {
// `name` takes precedence over `message` in Chrome DevTools
// Frontend, no need
// to record both.
folly::dynamic data =
folly::dynamic::object("name", std::move(event.name));
folly::dynamic data = folly::dynamic::object("name", event.name)(
"message", std::move(event.name));
if (event.start) {
if (std::holds_alternative<HighResTimeStamp>(*event.start)) {
data["start"] = highResTimeStampToTracingClockTimeStamp(
@@ -529,6 +569,34 @@ void PerformanceTracer::enqueueTraceEventsFromPerformanceTracerEvent(
data["end"] = std::move(std::get<std::string>(*event.end));
}
}
// We add a custom synthetic entry here to manually put Components
// track right under the Scheduler track. Will be removed once CDT
// Frontend preserves track ordering and we upgrade the fork.
if (!alreadyEmittedEntryForComponentsTrackOrdering_ &&
event.trackName && !event.trackGroup) {
if (*event.trackName == "Components \u269B") {
alreadyEmittedEntryForComponentsTrackOrdering_ = true;
// React is using 0.003 for Scheduler sub-tracks.
auto timestamp = highResTimeStampToTracingClockTimeStamp(
HighResTimeStamp::fromDOMHighResTimeStamp(0.004));
events.emplace_back(TraceEvent{
.name = "TimeStamp",
.cat = "devtools.timeline",
.ph = 'I',
.ts = event.createdAt,
.pid = processId_,
.tid = event.threadId,
.args = folly::dynamic::object(
"data",
folly::dynamic::object(
"name", "ReactNative-ComponentsTrack")(
"start", timestamp)("end", timestamp)(
"track", *event.trackName)),
});
}
}
if (event.trackName) {
data["track"] = std::move(*event.trackName);
}
@@ -549,25 +617,10 @@ void PerformanceTracer::enqueueTraceEventsFromPerformanceTracerEvent(
.args = folly::dynamic::object("data", std::move(data)),
});
},
[&](PerformanceTracerResourceWillSendRequest&& event) {
folly::dynamic data =
folly::dynamic::object("requestId", std::move(event.requestId));
events.emplace_back(TraceEvent{
.name = "ResourceWillSendRequest",
.cat = "devtools.timeline",
.ph = 'I',
.ts = event.start,
.pid = processId_,
.s = 't',
.tid = event.threadId,
.args = folly::dynamic::object("data", std::move(data)),
});
},
[&](PerformanceTracerResourceSendRequest&& event) {
folly::dynamic data =
folly::dynamic::object("initiator", folly::dynamic::object())(
"renderBlocking", "non_blocking")(
"priority", "VeryHigh")("renderBlocking", "non_blocking")(
"requestId", std::move(event.requestId))(
"requestMethod", std::move(event.requestMethod))(
"resourceType", std::move(event.resourceType))(
@@ -585,10 +638,18 @@ void PerformanceTracer::enqueueTraceEventsFromPerformanceTracerEvent(
});
},
[&](PerformanceTracerResourceReceiveResponse&& event) {
folly::dynamic data = folly::dynamic::object("protocol", "h2")(
folly::dynamic headersEntries = folly::dynamic::array;
for (const auto& [key, value] : event.headers) {
headersEntries.push_back(
folly::dynamic::object("name", key)("value", value));
}
folly::dynamic data = folly::dynamic::object(
"encodedDataLength", event.encodedDataLength)(
"headers", headersEntries)("mimeType", event.mimeType)(
"protocol", event.protocol)(
"requestId", std::move(event.requestId))(
"statusCode", event.statusCode)(
"timing", folly::dynamic::object());
"timing", std::move(event.timing));
events.emplace_back(TraceEvent{
.name = "ResourceReceiveResponse",
@@ -602,7 +663,9 @@ void PerformanceTracer::enqueueTraceEventsFromPerformanceTracerEvent(
});
},
[&](PerformanceTracerResourceFinish&& event) {
folly::dynamic data = folly::dynamic::object("didFail", false)(
folly::dynamic data = folly::dynamic::object(
"decodedBodyLength", event.decodedBodyLength)("didFail", false)(
"encodedDataLength", event.encodedDataLength)(
"requestId", std::move(event.requestId));
events.emplace_back(TraceEvent{
@@ -15,6 +15,7 @@
#include <folly/dynamic.h>
#include <atomic>
#include <map>
#include <mutex>
#include <optional>
#include <vector>
@@ -24,6 +25,8 @@ namespace facebook::react::jsinspector_modern::tracing {
// TODO: Review how this API is integrated into jsinspector_modern (singleton
// design is copied from earlier FuseboxTracer prototype).
using Headers = std::map<std::string, std::string>;
/**
* [Experimental] An interface for logging performance trace events to the
* modern debugger server.
@@ -109,19 +112,56 @@ class PerformanceTracer {
void reportEventLoopMicrotasks(HighResTimeStamp start, HighResTimeStamp end);
/**
* Record a "ResourceSendRequest"/"ResourceFinish" event pair - a labelled
* duration in the Performance timeline Network track. If not currently
* tracing, this is a no-op.
* Record a "ResourceWillSendRequest" event. Paired with other "Resource*"
* events, renders a network request timeline in the Performance panel Network
* track.
*
* If not currently tracing, this is a no-op.
*/
void reportResourceTiming(
const std::string& requestId,
void reportResourceWillSendRequest(
const std::string& devtoolsRequestId,
HighResTimeStamp start);
/**
* Record a "ResourceSendRequest" event. Paired with other "Resource*"
* events, renders a network request timeline in the Performance panel Network
* track.
*
* If not currently tracing, this is a no-op.
*/
void reportResourceSendRequest(
const std::string& devtoolsRequestId,
HighResTimeStamp start,
const std::string& url,
HighResTimeStamp fetchStart,
HighResTimeStamp responseStart,
HighResTimeStamp responseEnd,
int statusCode,
const std::string& requestMethod,
const std::string& resourceType);
const Headers& headers);
/**
* Record a "ResourceReceiveResponse" event. Paired with other "Resource*"
* events, renders a network request timeline in the Performance panel Network
* track.
*
* If not currently tracing, this is a no-op.
*/
void reportResourceReceiveResponse(
const std::string& devtoolsRequestId,
HighResTimeStamp start,
int statusCode,
const Headers& headers,
int encodedDataLength,
folly::dynamic timingData);
/**
* Record a "ResourceFinish" event. Paired with other "Resource*" events,
* renders a network request timeline in the Performance panel Network track.
*
* If not currently tracing, this is a no-op.
*/
void reportResourceFinish(
const std::string& devtoolsRequestId,
HighResTimeStamp start,
int encodedDataLength,
int decodedBodyLength);
/**
* Creates "Profile" Trace Event.
@@ -196,13 +236,6 @@ class PerformanceTracer {
HighResTimeStamp createdAt = HighResTimeStamp::now();
};
struct PerformanceTracerResourceWillSendRequest {
std::string requestId;
HighResTimeStamp start;
ThreadId threadId;
HighResTimeStamp createdAt = HighResTimeStamp::now();
};
struct PerformanceTracerResourceSendRequest {
std::string requestId;
std::string url;
@@ -216,6 +249,8 @@ class PerformanceTracer {
struct PerformanceTracerResourceFinish {
std::string requestId;
HighResTimeStamp start;
int encodedDataLength;
int decodedBodyLength;
ThreadId threadId;
HighResTimeStamp createdAt = HighResTimeStamp::now();
};
@@ -223,7 +258,12 @@ class PerformanceTracer {
struct PerformanceTracerResourceReceiveResponse {
std::string requestId;
HighResTimeStamp start;
int encodedDataLength;
Headers headers;
std::string mimeType;
std::string protocol;
int statusCode;
folly::dynamic timing;
ThreadId threadId;
HighResTimeStamp createdAt = HighResTimeStamp::now();
};
@@ -234,7 +274,6 @@ class PerformanceTracer {
PerformanceTracerEventEventLoopMicrotask,
PerformanceTracerEventMark,
PerformanceTracerEventMeasure,
PerformanceTracerResourceWillSendRequest,
PerformanceTracerResourceSendRequest,
PerformanceTracerResourceReceiveResponse,
PerformanceTracerResourceFinish>;
@@ -271,6 +310,10 @@ class PerformanceTracer {
std::vector<PerformanceTracerEvent>* previousBuffer_{};
HighResTimeStamp currentBufferStartTime_;
// A flag that is used to ensure we only emit one auxiliary entry for the
// ordering of Scheduler / Component tracks.
bool alreadyEmittedEntryForComponentsTrackOrdering_ = false;
/**
* Protects data members of this class for concurrent access, including
* the tracingAtomic_, in order to eliminate potential "logic" races.
@@ -43,6 +43,7 @@ Pod::Spec.new do |s|
resolve_use_frameworks(s, header_mappings_dir: "../..", module_name: module_name)
add_dependency(s, "React-jsinspectornetwork", :framework_name => 'jsinspector_modernnetwork')
s.dependency "React-oscompat"
s.dependency "React-timing"
@@ -9,13 +9,13 @@
#ifdef __cplusplus
#include <ReactCommon/RuntimeExecutor.h>
#include <cxxreact/MessageQueueThread.h>
#include <jsi/jsi.h>
#include <jsinspector-modern/ReactCdp.h>
namespace facebook::react {
class MessageQueueThread;
/**
* An interface that represents an instance of a JS VM
*/

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