Compare commits

...
Author SHA1 Message Date
Devmate BotandFacebook GitHub Bot 53d8c9d2d7 xplat/js/react-native-github/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tests/TaskTestUtils.kt
Reviewed By: rshest

Differential Revision: D80931289
2025-08-26 03:56:36 -07:00
Christian FalchandFacebook GitHub Bot 939a75b5ce add SWIFT_ENABLE_EXPLICIT_MODULES to xcode 26 (#53457)
Summary:
XCode 26 introduces building explicit swift modules turned on (SWIFT_ENABLE_EXPLICIT_MODULES). This breaks building with precompiled binaries.

This commit fixes this by adding a step when not building from source where we explicitly set the `SWIFT_ENABLE_EXPLICIT_MODULES` flag to `NO`.

## Changelog:

[IOS] [FIXED] - Added setting SWIFT_ENABLE_EXPLICIT_MODULES=NO when using precompiled to support Xcode 26

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

Test Plan:
```bash
npx react-native-community/cli init MyApp --version nightly --skip-install
cd MyApp
yarn
cd ios
bundle install
RCT_USE_RN_DEP=1 RCT_USE_PREBUILT_RNCORE=1 bundle exec pod install
```

Build above app with Xcode 26 and verify that it no longer fails

Reviewed By: motiz88

Differential Revision: D81025367

Pulled By: cipolleschi

fbshipit-source-id: 1db7c4d7de07d62f43b355aa784d7d9de478023c
2025-08-26 03:39:49 -07:00
generatedunixname537391475639613andFacebook GitHub Bot ec1ee19cda xplat/js/react-native-github/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/internal/PrepareBoostTaskTest.kt (#53358)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/53358

Reviewed By: cortinico, cipolleschi

Differential Revision: D80605883

fbshipit-source-id: cf576ee6e6c941eaef25ebf835c771e9bb3d5669
2025-08-25 18:37:02 -07:00
Luna WeiandFacebook GitHub Bot 792e450aff Introduce hysteresis window (#53345)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53345

Changelog: [Internal] - Introduce hysteresis window that is nested between the prerender and hidden window sizes. Currently set to enlargening the prerender window by hysteresis ratio

When a VirtualView intersects with the hysteresis window, it mode remains unchanged.

This prevents us dispatch mode changes for things like overscroll.

I put the hysteresis between prerender and hidden because we already avoid dispatching mode changes from visible -> prerender. For prerender -> visible, we use renderState

Reviewed By: yungsters

Differential Revision: D80511627

fbshipit-source-id: cd14256abc898e7120705e277147d52a06c865a9
2025-08-25 12:58:22 -07:00
Pieter De BaetsandFacebook GitHub Bot 870836ff84 Namespace Perfetto usage (#53424)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53424

Use the namespaced version of these macros to avoid symbol conflicts when multiple instances of `PERFETTO_DEFINE_CATEGORIES` are in the same binary.

The current macro is effectively deprecated: https://github.com/a6f/perfetto_protos/blob/master/CHANGELOG#L691-L696

Changelog: [Internal]

Reviewed By: rshest

Differential Revision: D80697205

fbshipit-source-id: 713fec4d41137ddd2f025c7e7130dc44c5a3a656
2025-08-25 11:16:51 -07:00
Andrew DatsenkoandFacebook GitHub Bot 42b94fc709 Add babel-plugin-istanbul for code covearage (#53413)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53413

Changelog: [Internal]
Add dependency on istanbul plugin so we can collect code coverage.

Reviewed By: christophpurrer

Differential Revision: D80723825

fbshipit-source-id: bf0ac0e49e12ea1b01f72c11362019ef68e09ff9
2025-08-25 10:45:16 -07:00
Pieter De BaetsandFacebook GitHub Bot 8881faa7ec Rollout useRawPropsJsiValue (#53426)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53426

Experiment review for this was completed internally, and we can now change the default behaviour to no longer allocate an intermediate folly::dynamic when parsing props.

RawValue will continue supporting a folly::dynamic constructor as some paths go through code path (eg animations)

There should be no user-visible difference in parsing behaviour.

Changelog: [Internal]

Reviewed By: rshest

Differential Revision: D80799833

fbshipit-source-id: 8eeae656157757eb38f69a2af14409da23b510c8
2025-08-25 07:09:34 -07:00
Phil PluckthunandFacebook GitHub Bot b054540092 Mark @react-native/metro-config as optional peer to fix warning (#53314)
Summary:
The `react-native/metro-config` peer was added in https://github.com/facebook/react-native/commit/fe2bcbf4ba7ce983fac0cd09727c165517b6337f / https://github.com/facebook/react-native/issues/51836 by robhogan

Side-note: It's pulled in via `react-native/community-cli-plugin` which is a direct dependency of `react-native` for the `scripts/bundle.js` script. While, for expo, we'd love to find a way to make this an optional dependency (to avoid excessive deps that `expo` replaces otherwise), for now, it's a direct dependency.

The problem here is that this isn't optional, which means:
- with auto-installing peer dependencies it is directly fulfilled (while `react-native-community/cli` is already marked as optional and skipped)
- with legacy/non-auto peer-dependencies it is flagged as missing, but in an Expo project it wouldn't make sense to install directly

This causes a **package manager regression in the form of either a peer dependency warning**, that shouldn't be fulfilled in an Expo project, or (in the best case scenario) pulls in dependencies [that a user does not need](https://npmgraph.js.org/?q=%40react-native%2Fmetro-config#zoom=w&select=exact%3A%40react-native%2Fmetro-config%400.81.0).

An error message is already in place to inform the user of this being missing when it's not installed, so marking it as optional seems appropriate.

## Changelog:

[INTERNAL] [FIXED] Mark added `react-native/metro-config` peer dependency as optional

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

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

Test Plan:
Warnings like the following won't occur in fresh Expo (54/preview/`next`) projects
```
warning "workspace-aggregator-484d9ec3-587b-43cb-97de-4dcce3876578 > microfoam-mobile > react-native > react-native/community-cli-plugin@0.81.0" has unmet peer dependency "react-native/metro-config@*".
```

Reviewed By: cortinico

Differential Revision: D80450287

Pulled By: robhogan

fbshipit-source-id: c622fd4c24025676c0ec74de826f863f1e291669
2025-08-24 14:18:42 -07:00
Tim YungandFacebook GitHub Bot bf12e30cb7 VirtualView: Remove Unnecessary ?. in updateClippingRect() (#53442)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53442

Refactors `VirtualView` to remove this unnecessary `?.` in `updateClippingRect()`.

Changelog:
[Internal]

Reviewed By: lunaleaps

Differential Revision: D80600713

fbshipit-source-id: 1a11b302f069e3b35db70831fd4f7a9bd7471cc6
2025-08-22 17:49:05 -07:00
Ruslan ShestopalyukandFacebook GitHub Bot ec1e97342a View recycling for ScrollView native component on Android (#53395)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53395

# Changelog
[Internal] -

This enables view recycling for both ScrollView and HorizontalScrollView on Android.

The feature is gated by the corresponding RN feature flag, `enableViewRecyclingForScrollView` (which is false by default for now, will be enabled in an experiment).

Reviewed By: lenaic

Differential Revision: D80611087

fbshipit-source-id: b3026affc0ea61bc7739126d6529c83f2a653183
2025-08-22 13:54:51 -07:00
Nicola CortiandFacebook GitHub Bot cf528526cc Remove dead Inspector.kt/JInspector.h/.cpp code (#53403)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53403

This code is Legacy and totally unused. It should be safe to remove it altogether.
This class is public but no one is using it in OSS + no one should be using it, so I don't think we'll need the full deprecation cycle for it.

Changelog:
[Android] [Removed] - Removed unused `Inspector` public class from React Android

Reviewed By: cipolleschi

Differential Revision: D80711515

fbshipit-source-id: 83134851877fcbccd50f7a5b75b2ab8906b3416a
2025-08-22 11:13:31 -07:00
Sam ZhouandFacebook GitHub Bot 0530ea3349 Migrate to suppression with error code in xplat: 1/n (#53439)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53439

Changelog: [Internal]

Reviewed By: panagosg7

Differential Revision: D80809220

fbshipit-source-id: 6f432d8302934b9fee9780ac1d6ba6c87c0b3899
2025-08-22 10:35:39 -07:00
generatedunixname89002005287564andFacebook GitHub Bot 56ab2e72b2 Fix CQS signal modernize-use-designated-initializers in xplat/js/react-native-github/packages [B] [A] [A] (#53401)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/53401

Reviewed By: cipolleschi

Differential Revision: D80713611

fbshipit-source-id: 73dc034d966eea5b388a51ab84da2416531c7376
2025-08-22 07:02:13 -07:00
generatedunixname89002005287564andFacebook GitHub Bot e60ddf0adb Fix CQS signal modernize-use-designated-initializers in xplat/js/react-native-github/packages [B] [B] (#53425)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/53425

Reviewed By: javache

Differential Revision: D80619000

fbshipit-source-id: d012c170ed366904b39ef335fea5241b604461ec
2025-08-22 05:52:14 -07:00
Ruslan LesiutinandFacebook GitHub Bot 4b34be445d Release PerfMetricsBinding to avoid memory leak (#53420)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53420

# Changelog: [Internal]

HostRuntimeBinding owns a connection, which is stored as a session on HostTarget, so we need to release it first in order to satifsy the assertion in the destructor.

Reviewed By: huntie

Differential Revision: D80778273

fbshipit-source-id: be7bf085fadd8808fd5e5c621c3990a5e7e0186d
2025-08-22 05:07:02 -07:00
Ruslan LesiutinandFacebook GitHub Bot 8d8245123e Create endpoints for tracing and stashing on Bridgeless Android ReactHost (#53416)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53416

# Changelog: [Internal]

Creates methods on Bridgeless Android Host for starting / stopping tracing and implements logic for storing the recording that will be transferred to `jsinspector-modern` stack via HostTargetDelegate when CDP session is created.

Reviewed By: sbuggay

Differential Revision: D79725161

fbshipit-source-id: f3e3b39f6d94a6548cf227394f7328f6913c33e4
2025-08-22 04:12:22 -07:00
Ruslan LesiutinandFacebook GitHub Bot 80f340e81c Send custom CDP Event to Frontend to prepare for displaying a trace (#53079)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53079

# Changelog: [Internal]

We need this to notify Frontend, so it updates the local state before receiving `Tracing.dataCollected` events.

Corresponding change in CDT fork - https://github.com/facebook/react-native-devtools-frontend/pull/199.

Reviewed By: sbuggay

Differential Revision: D79672598

fbshipit-source-id: b2928cb3942e34a1f4723516ecdf5062d4331591
2025-08-22 04:12:22 -07:00
Ruslan LesiutinandFacebook GitHub Bot e1b76ab2d5 Add a mechanism for emitting stashed trace recording (#53078)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53078

# Changelog: [Internal]

When CDP session is created via `HostTarget::connect`, it will ask `HostTargetDelegate` is there is a previously recorded trace that Host wants to display in the Frontend.

`TracingAgent` will serialize and send the recording at the initialization time in constructor.

Reviewed By: huntie

Differential Revision: D79672597

fbshipit-source-id: 241c9d367ab65ef1e95c62d5025b3bc14bf42608
2025-08-22 04:12:22 -07:00
generatedunixname537391475639613andFacebook GitHub Bot 5848252ee2 xplat/js/react-native-github/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/internal/PreparePrefabHeadersTaskTest.kt (#53423)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/53423

Reviewed By: rshest

Differential Revision: D80786149

fbshipit-source-id: 81df8592b142df2f9d9178c13a9480a7186c2604
2025-08-22 04:12:06 -07:00
Moti ZilbermanandFacebook GitHub Bot 33be0606c1 Always reload the frontend when launching, even in an existing window (#53407)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53407

Changelog: [Internal]

## Context

Upon receiving a launch command, the RNDT shell either:

1. Creates a new window and navigates to the requested frontend URL.
2. Brings an existing window to the foreground *with no further navigation*.

In the happy path, (2) is a pretty nice experience: it preserves all prior UI state in the frontend and leaves the user with an instantly responsive debugger - this can be quite a bit faster than (1) because of the overhead of loading and parsing source maps for example. However, this breaks down if the frontend is not in a usable state to begin with. This is, sadly, a frequent-enough occurrence that we must account for it: the CDP connection may have been lost, the frontend app itself might have failed to load the last time, etc.

Preserving everything that's nice about (2) while also making it fully reliable - incrementally bringing the frontend to the state specified by a new URL - would require delicate engineering across the shell and frontend codebases, which is an amount of complexity I would like to sidestep for now.

NOTE: The more complex solution **is 100% worth implementing in the long term,** as it has tangible benefits for the user, and matches Chrome best.

## This diff

Here we take a much cheaper approach than the one described above: the shell will *always* initiate navigation to the new frontend URL, regardless of whether it does so in a new window or a previously opened one. This will consistently bring the user to a state where the frontend is open and working (although it will reset any ephemeral UI state in the process, and typically take a noticeable amount of time to load).

Even with this simplified approach, the standalone shell still offers a better experience than launching in a browser (if only because it is zero-install and avoids the "dead tab spam" problem).

Reviewed By: huntie

Differential Revision: D80711185

fbshipit-source-id: 8f376ccf1717c48a1742c798da3171ac6d2f8af0
2025-08-22 04:03:08 -07:00
Christian FalchandFacebook GitHub Bot a843119ff1 Fix copy symbol files in RNDeps precompile (#53353)
Summary:
Symbol files wasn't copied correctly when building - as with bundles we did overwrite the files and ended up with only the last symbol file.

This commit fixes this by mapping the framework build folder architecture type to the xcframework slices creating the correct file structure under the Symbols folder.

- Each slice gets a folder with the architecture name under Symbols containing the dSym folder for that slice
- Refactored getting correct architecture folder into a separate function.
- Refactored target folder lookup in copyBundles
- Removed unused async modifier on function

## Changelog:

[IOS] [FIXED] - Fixed how we copy and build the Symbols folder when precompiling ReactNativeDependencies

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

Test Plan: Run nightlies and verify that ReactNativeDependencies.framework.dSym files contains symbol files for all architectures.

Reviewed By: cortinico

Differential Revision: D80692019

Pulled By: cipolleschi

fbshipit-source-id: 77983bc29d1965edf3bc0fcbd9cb3177071991d3
2025-08-22 03:26:54 -07:00
Christian FalchandFacebook GitHub Bot 8c444f773a aligned symbol folders with RNdeps (#53354)
Summary:
After fixing an isssue with ReactnativeDependencies and how it built symbols (https://github.com/facebook/react-native/issues/53353) this commit will align the output of the Symbols folder for the two frameworks.

Previously we had an output in the Symbols folder that looked like this (from a local build on my machine)

- catalyst
- iphone
- iphonesimulator

After this we now have the more correct arcitecture names on these folders:

- ios-arm64
- ios-arm64_x86_64-simulator
- ios-arm64_x86_64-maccatalyst

This is in line with how the ReactNativeDependencies Symbol folder is set up.

## Changelog:

[IOS] [FIXED] - Aligned Symbols folder in React.xcframework symbols with ReactNativeDependencies.xcframework symbols.

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

Test Plan: Nightlies

Reviewed By: cortinico

Differential Revision: D80692098

Pulled By: cipolleschi

fbshipit-source-id: e952b087d5dbdeb929b45d9e6d3d7e077c9d05cc
2025-08-22 03:23:24 -07:00
Alex HuntandFacebook GitHub Bot 3292cb1dc9 Fix incorrectly hardcoded landingView for open debugger action (#53400)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53400

In D79329081, we accidentally hardcoded the `landingView` parameter in the default Dev Menu handler to open React Native DevTools. Reset this.

Changelog: [Internal]

Reviewed By: hoxyq

Differential Revision: D80710487

fbshipit-source-id: 9066ffafcb17a6ff46650f7081d9a662f186d995
2025-08-22 03:09:50 -07:00
Ruslan ShestopalyukandFacebook GitHub Bot d0744f7e59 Use Map as recyclable views container (#53394)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53394

# Changelog:
[Internal] -

This just fixes a linter warning I noticed when working on related code.

Reviewed By: cortinico

Differential Revision: D80702545

fbshipit-source-id: fecfed9e9946b971864706306b03b57cd3111aee
2025-08-22 01:35:18 -07:00
Chi TsaiandFacebook GitHub Bot 646945c2f2 Add deleteProperty API (#52911)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/52911

Add a new `deleteProperty` API to JSI. As the name implies, allows users
to delete properties from Objects through JSI.

The default implementation uses `Reflect.deleteProperty.` For the
`PropNameID` overload, convert the propNameID to a String and pass into
the `deleteProperty` function.

Changelog: [Internal]

Reviewed By: dannysu

Differential Revision: D79120814

fbshipit-source-id: e30f383247d94bb5971e4909f004c75e8165adda
2025-08-21 17:35:55 -07:00
Marco WangandFacebook GitHub Bot da9136f587 Turn on null strict comparison check for xplat js (#53379)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53379

X-link: https://github.com/facebook/react/pull/34240

Changelog: [Internal]

Reviewed By: SamChou19815

Differential Revision: D80648362

fbshipit-source-id: cc47ae207f29a3ddb68bc0e029b8773f89503c52
2025-08-21 16:46:23 -07:00
Nikita LutsenkoandFacebook GitHub Bot ffe52b75a3 xplat/js/react-native-github/packages/react-native/ReactCommon/react/renderer/mounting/Differentiator.cpp (#53412)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53412

Changelog:
[General][Internal] - Encapsulated internal class into anonymous namespace to ensure no collisions with public symbols.

Differential Revision: D80689084

fbshipit-source-id: 53ebd8a16a3c217efead0bfe91f66bd50bb6dd2f
2025-08-21 14:59:24 -07:00
Ruslan LesiutinandFacebook GitHub Bot a2a73739d8 fix: use ThreadId when event is captured, not when transformed (#53411)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53411

# Changelog: [Internal]

This regressed after D80263154, when we introduced a local struct for PerforamanceTracerEvent.

We should use id of the thread where event was captured (registered), not where the transform to TraceEvent happened.

This makes sure that events like Event Loop tick or Microtasks phase tick are correctly point to JavaScript thread, not the thread where the transform could've taken place.

Reviewed By: sbuggay

Differential Revision: D80728931

fbshipit-source-id: d3af16e68adece9ebc37368fec2b8a17c1293b4b
2025-08-21 14:18:27 -07:00
Nicola CortiandFacebook GitHub Bot 046ff8e58b Make OnBatchCompleteListener interface internal (#53409)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53409

This interface is public and is part of Legacy Architecture.

Having this interface as `public` was a mistake, as users can't really do much with it.
There is only one old library that is going to be affected by this change:
https://github.com/spoke-ph/react-native-threads
The library appears unmaintained since RN 0.69 + no NewArch support so I won't consider this a breaking change
given this will land in 0.82.

I'm making it internal so we can remove it more easily later.

Changelog:
[Android] [Changed] - Make OnBatchCompleteListener interface internal

Differential Revision: D80715625

fbshipit-source-id: 94fe80eeba95222deab7ca89c5fcafca8fcee0b7
2025-08-21 14:05:47 -07:00
Nicola CortiandFacebook GitHub Bot fb114da8a4 Remove unused internal UIManagerModuleListener (#53404)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53404

This interface is part of Legacy Architecture. No one is using it either internally or externally,
so it's safe to remove now. Interface was also `internal` so this is not a breaking change.

Changelog:
[Internal] [Changed] -

Reviewed By: mdvacca

Differential Revision: D80714721

fbshipit-source-id: 82cc6152af7d7980119d2eda704ae50d8e81fd2b
2025-08-21 12:25:38 -07:00
Umar MohammadandFacebook GitHub Bot 191ddc1ec7 Fix React Native Commands Export Validation in Coverage Mode (#53381)
Summary:
Changelog: [GENERAL] [FIXED] - Fixed babel plugin validation error when coverage instrumentation is enabled

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

### Problem

[Workplace post](https://fb.workplace.com/groups/235694244595999/permalink/1278937163605030/)

React Native tests were failing **only when coverage collection was enabled** with the error:

`'Commands' is a reserved export and may only be used to export the result of codegenNativeCommands.`

### Root Cause

The React Native Babel plugin's `codegenNativeCommands` validation logic only handled direct `CallExpression` AST nodes. When coverage instrumentation was enabled, it transformed:

**Normal code:**

`export const Commands = codegenNativeCommands<NativeCommands>({...})`

**With coverage:**

`export const Commands = (cov_xxx().s[0]++, codegenNativeCommands<NativeCommands>({...}))`

The plugin failed to recognize the valid `codegenNativeCommands` call wrapped in a `SequenceExpression` by coverage instrumentation.

### **Solution**

Added `isCodegenNativeCommandsDeclaration` function to handle:

1.  **Coverage instrumentation**: `SequenceExpression` nodes containing the function call
2.  **Flow type casts**: `TypeCastExpression` and `AsExpression`
3.  **TypeScript assertions**: `TSAsExpression`
4.  **Direct calls**: Original `CallExpression` (backward compatibility)

Reviewed By: andrewdacenko

Differential Revision: D80572666

fbshipit-source-id: 465f4312a0229d8a92e495c685f46b607ce326e4
2025-08-21 11:33:52 -07:00
Nicola CortiandFacebook GitHub Bot aaa7ba4ab3 HelloWorld should not use ReactNativeHost (#53399)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53399

We currently create application template that are still using `ReactNativeHost`.
As this is a legacy arch class, we should remove it from the template ASAP so that
users can organically migrate away from it.

I will also update https://github.com/react-native-community/template with
the same changes I'm applying here.

Changelog:
[Internal] [Changed] -

Reviewed By: mdvacca

Differential Revision: D80708461

fbshipit-source-id: e0d4a1f817e6fdddd93405decf77fd115956ec51
2025-08-21 11:16:20 -07:00
Nicola CortiandFacebook GitHub Bot 2689d4d372 RNTester should not use ReactNativeHost (#53398)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53398

ReactNativeHost is a legacy architecture class.
This migrates the app away from it and converts it to use DefaultReactHost instead.

Changelog:
[Internal] [Changed] -

Reviewed By: mdvacca

Differential Revision: D80708460

fbshipit-source-id: 7d88c440414c979a2968fc9c910e828f5851195c
2025-08-21 11:16:20 -07:00
Nicola CortiandFacebook GitHub Bot d35ddb5e59 Delete unused DefaultReactHost.getDefaultReactHost() overload (#53396)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53396

This overload for `getDefaultReactHost` is missing the last 2 parameters
and provides the same default as the full method.

In OSS is unused as we used the one with `ReactNativeHost`.
I'm removing it as it's causing an overload resolution failure internally.

This won't be a breaking change for Kotlin users are the signatures are compatibles,
but it will be breaking for Java users. I've verified that there are no OSS users.

Developers should use Kotlin default parameters + the method `getDefaultReactHost()`
with all the params + defaults for ease of use of this API.

Changelog:
[Android] [Removed] - Delete unused `DefaultReactHost.getDefaultReactHost()` overload

Reviewed By: mdvacca

Differential Revision: D80704987

fbshipit-source-id: 0b3a61aad3f18cde77bac78e3ba413d7f9166ede
2025-08-21 11:16:20 -07:00
Nicola CortiandFacebook GitHub Bot 8e514a8a10 Annotate ReactNativeJNISoLoader as InteropLegacyArchitecture (#53406)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53406

The `ReactNativeJNISoLoader` class (previously called BridgeSoLoader)
is actually a Legacy Architecture class.
However is used by `CxxModuleWrapperBase` which is needed by interop, so we need to keep it around.
I'm adding the annotation so we won't forget about it.

Changelog:
[Internal] [Changed] -

Reviewed By: cipolleschi

Differential Revision: D80710951

fbshipit-source-id: ed353e2b14c742b25962f0b81beba6dc90157709
2025-08-21 10:52:56 -07:00
Nicola CortiandFacebook GitHub Bot e28784d4b6 Remove unnecessary NativeArgumentsParseException (#53408)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53408

This class is internal + legacy arch so can safely be removed now.
I've replaced the throw/catch site with the superclass of this exception.

Changelog:
[Internal] [Changed] -

Reviewed By: mdvacca

Differential Revision: D80710950

fbshipit-source-id: 96615835588ce409de40d31ee83b82c88d3a07a0
2025-08-21 10:52:56 -07:00
Riccardo CipolleschiandFacebook GitHub Bot 28275a0f7b Fix Crash when rendering Switch component (#53393)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53393

When implementing the changes for the Switch component for iOS 26, I didn't realize that the code in [`RCTIntance.mm`](https://www.internalfb.com/code/fbsource/[a54514baccf4e1f828ef46af8180555754c405d8]/xplat/js/react-native-github/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm?lines=344-375) was running behind a feature flag.
This means that all the users not in the experiment where the feature flag is turned on will experience a crash as soon as they navigate to a React Native screen that contains a Switch.

This change fixes the problem by adding a jump to the right queue and it also fixes a measurement issue with the Switch.

## Changelog:
[iOS][Fixed] - Fixed a crash when rendering the Switch component

bypass-github-export-checks

Reviewed By: GijsWeterings

Differential Revision: D80702245

fbshipit-source-id: 480ea061233d35e31679b4b30758dbc133ff0a77
2025-08-21 10:13:22 -07:00
Ruslan ShestopalyukandFacebook GitHub Bot bcf76e8bb0 Add RN feature flag for ScrollView view recycling (#53373)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53373

# Changelog:
[Internal] -

Creates a RN feature flag for enabling/disabling view recycling for ScrollView native component on Android.

Reviewed By: lenaic

Differential Revision: D80625656

fbshipit-source-id: 23eae07512e0ba2ea014404e7afa19db900f7c47
2025-08-21 09:47:23 -07:00
Lauren TanandFacebook GitHub Bot c2d96d3a5b Add flow suppression for Constant Condition rollout (#34243)
Summary: DiffTrain build for [83c7379b9601f25463826449256f0cd3d283702d](https://github.com/facebook/react/commit/83c7379b9601f25463826449256f0cd3d283702d)

Reviewed By: marcoww6

Differential Revision: D80661139

fbshipit-source-id: 8ccf2dccba9a07ffd38f50da2c1ded8ebfa78c89
2025-08-21 09:35:19 -07:00
Nicola CortiandFacebook GitHub Bot c557311ed8 Ship useNativeEqualsInNativeReadableArrayAndroid and useNativeTransformHelperAndroid to stable (#53372)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53372

We verified that those feature flags are not regressing the experience + we got confirmation from Software Mansion that the fix
is effectively mitigating the regression on Android mounting.

Hence we can ship this to production.

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

Changelog:
[Android] [Fixed] - Fix mounting is very slow on Android by shipping native transform optimizations

Reviewed By: javache

Differential Revision: D80624739

fbshipit-source-id: 2e185434f08b5ea0339d59a6ea006017e5abeff2
2025-08-21 09:32:21 -07:00
Nicola CortiandFacebook GitHub Bot 3f74a87027 Reland: Remove deprecated DefaultReactHost.getDefaultReactHost() overload - part 1 & 2
Summary:
This is a reland of D80622058 + D80623826 + fixes for all the apps.

This method was deprecated in React Native 0.79. We should be able to remove it without impact in 0.82.
I also verified that there are no users of this API in OSS.

There is also a 1:1 replacement for this API which is the other non-deprecated `getDefaultReactHost()` method.

bypass-github-export-checks

Changelog:
[Internal] - Skipping changelog as main already contains a changelog entry

Reviewed By: javache

Differential Revision: D80704320

fbshipit-source-id: c9aa26b83dbd9f4bf97d0a9e9c6dcaa6eb0afdca
2025-08-21 09:31:30 -07:00
129 changed files with 1822 additions and 1097 deletions
@@ -179,8 +179,9 @@ jobs:
- name: Compress and Rename dSYM
if: steps.restore-xcframework.outputs.cache-hit != 'true'
run: |
tar -cz -f packages/react-native/third-party/Symbols/ReactNativeDependencies${{ matrix.flavor }}.framework.dSYM.tar.gz \
packages/react-native/third-party/Symbols/ReactNativeDependencies.framework.dSYM
cd packages/react-native/third-party/Symbols/
tar -cz -f ../ReactNativeDependencies${{ matrix.flavor }}.framework.dSYM.tar.gz .
mv ../ReactNativeDependencies${{ matrix.flavor }}.framework.dSYM.tar.gz ./ReactNativeDependencies${{ matrix.flavor }}.framework.dSYM.tar.gz
- name: Upload XCFramework Artifact
uses: actions/upload-artifact@v4
with:
@@ -81,10 +81,147 @@ export {Commands};
export default (codegenNativeComponent<ModuleProps>('Module'): NativeType);
`;
const COMMANDS_WITH_COVERAGE_INVALID = `
// @flow
const codegenNativeComponent = require('codegenNativeComponent');
import type {NativeComponentType} from 'codegenNativeComponent';
import type {ViewProps} from 'ViewPropTypes';
type ModuleProps = $ReadOnly<{|
...ViewProps,
|}>;
type NativeType = NativeComponentType<ModuleProps>;
// Coverage instrumentation of invalid Commands export - should still fail
export const Commands = (cov_1234567890().s[0]++, {
hotspotUpdate: () => {},
scrollTo: () => {},
});
export default (codegenNativeComponent<ModuleProps>('Module'): NativeType);
`;
const COMMANDS_WITH_COVERAGE_WRONG_FUNCTION = `
// @flow
const codegenNativeComponent = require('codegenNativeComponent');
import type {NativeComponentType} from 'codegenNativeComponent';
import type {ViewProps} from 'ViewPropTypes';
type ModuleProps = $ReadOnly<{|
...ViewProps,
|}>;
type NativeType = NativeComponentType<ModuleProps>;
// Coverage instrumentation of wrong function call - should fail
export const Commands = (cov_abcdef123().s[0]++, someOtherFunction({
supportedCommands: ['pause', 'play'],
}));
export default (codegenNativeComponent<ModuleProps>('Module'): NativeType);
`;
const COMMANDS_WITH_COMPLEX_COVERAGE_INVALID = `
// @flow
const codegenNativeComponent = require('codegenNativeComponent');
import type {NativeComponentType} from 'codegenNativeComponent';
import type {ViewProps} from 'ViewPropTypes';
type ModuleProps = $ReadOnly<{|
...ViewProps,
|}>;
type NativeType = NativeComponentType<ModuleProps>;
// Complex coverage instrumentation with invalid nested structure - should fail
export const Commands = (
cov_xyz789().f[1]++,
cov_xyz789().s[2]++,
{
pause: (ref) => {},
play: (ref) => {},
}
);
export default (codegenNativeComponent<ModuleProps>('Module'): NativeType);
`;
const COMMANDS_WITH_COVERAGE_WRONG_NAME = `
// @flow
const codegenNativeCommands = require('codegenNativeCommands');
const codegenNativeComponent = require('codegenNativeComponent');
import type {NativeComponentType} from 'codegenNativeComponent';
import type {ViewProps} from 'ViewPropTypes';
type ModuleProps = $ReadOnly<{|
...ViewProps,
|}>;
type NativeType = NativeComponentType<ModuleProps>;
interface NativeCommands {
+pause: (viewRef: React.ElementRef<NativeType>) => void;
+play: (viewRef: React.ElementRef<NativeType>) => void;
}
// Coverage instrumentation with correct function but wrong export name - should fail
export const WrongName = (cov_wrong123().s[0]++, codegenNativeCommands<NativeCommands>({
supportedCommands: ['pause', 'play'],
}));
export default (codegenNativeComponent<ModuleProps>('Module'): NativeType);
`;
const COMMANDS_WITH_COVERAGE_TYPE_CAST_INVALID = `
// @flow
const codegenNativeComponent = require('codegenNativeComponent');
import type {NativeComponentType} from 'codegenNativeComponent';
import type {ViewProps} from 'ViewPropTypes';
type ModuleProps = $ReadOnly<{|
...ViewProps,
|}>;
type NativeType = NativeComponentType<ModuleProps>;
interface NativeCommands {
+pause: (viewRef: React.ElementRef<NativeType>) => void;
+play: (viewRef: React.ElementRef<NativeType>) => void;
}
// Coverage instrumentation with type cast but wrong function - should fail
export const Commands: NativeCommands = (cov_cast123().s[0]++, invalidFunction({
supportedCommands: ['pause', 'play'],
}));
export default (codegenNativeComponent<ModuleProps>('Module'): NativeType);
`;
module.exports = {
'CommandsExportedWithDifferentNameNativeComponent.js':
COMMANDS_EXPORTED_WITH_DIFFERENT_NAME,
'CommandsExportedWithShorthandNativeComponent.js':
COMMANDS_EXPORTED_WITH_SHORTHAND,
'OtherCommandsExportNativeComponent.js': OTHER_COMMANDS_EXPORT,
'CommandsWithCoverageInvalidNativeComponent.js':
COMMANDS_WITH_COVERAGE_INVALID,
'CommandsWithCoverageWrongFunctionNativeComponent.js':
COMMANDS_WITH_COVERAGE_WRONG_FUNCTION,
'CommandsWithComplexCoverageInvalidNativeComponent.js':
COMMANDS_WITH_COMPLEX_COVERAGE_INVALID,
'CommandsWithCoverageWrongNameNativeComponent.js':
COMMANDS_WITH_COVERAGE_WRONG_NAME,
'CommandsWithCoverageTypeCastInvalidNativeComponent.js':
COMMANDS_WITH_COVERAGE_TYPE_CAST_INVALID,
};
@@ -59,6 +59,92 @@ export default codegenNativeComponent<ModuleProps>('Module', {
});
`;
// Coverage instrumentation test cases - should be recognized as valid
const COMMANDS_WITH_SIMPLE_COVERAGE = `
// @flow
const codegenNativeCommands = require('codegenNativeCommands');
const codegenNativeComponent = require('codegenNativeComponent');
import type {ViewProps} from 'ViewPropTypes';
import type {NativeComponentType} from 'codegenNativeComponent';
type ModuleProps = $ReadOnly<{|
...ViewProps,
|}>;
type NativeType = NativeComponentType<ModuleProps>;
interface NativeCommands {
+pause: (viewRef: React.ElementRef<NativeType>) => void;
+play: (viewRef: React.ElementRef<NativeType>) => void;
}
export const Commands = (cov_1234567890.s[0]++, codegenNativeCommands<NativeCommands>({
supportedCommands: ['pause', 'play'],
}));
export default codegenNativeComponent<ModuleProps>('Module');
`;
const COMMANDS_WITH_COMPLEX_COVERAGE = `
// @flow
const codegenNativeCommands = require('codegenNativeCommands');
const codegenNativeComponent = require('codegenNativeComponent');
import type {ViewProps} from 'ViewPropTypes';
import type {NativeComponentType} from 'codegenNativeComponent';
type ModuleProps = $ReadOnly<{|
...ViewProps,
|}>;
type NativeType = NativeComponentType<ModuleProps>;
interface NativeCommands {
+seek: (viewRef: React.ElementRef<NativeType>, position: number) => void;
+stop: (viewRef: React.ElementRef<NativeType>) => void;
}
export const Commands = (
cov_abcdef123().f[2]++,
cov_abcdef123().s[5]++,
codegenNativeCommands<NativeCommands>({
supportedCommands: ['seek', 'stop'],
})
);
export default codegenNativeComponent<ModuleProps>('Module');
`;
const COMMANDS_WITH_TYPE_CAST_COVERAGE = `
// @flow
const codegenNativeCommands = require('codegenNativeCommands');
const codegenNativeComponent = require('codegenNativeComponent');
import type {ViewProps} from 'ViewPropTypes';
import type {NativeComponentType} from 'codegenNativeComponent';
type ModuleProps = $ReadOnly<{|
...ViewProps,
|}>;
type NativeType = NativeComponentType<ModuleProps>;
interface NativeCommands {
+mute: (viewRef: React.ElementRef<NativeType>) => void;
+unmute: (viewRef: React.ElementRef<NativeType>) => void;
}
export const Commands: NativeCommands = (cov_xyz789().s[1]++, codegenNativeCommands<NativeCommands>({
supportedCommands: ['mute', 'unmute'],
}));
export default codegenNativeComponent<ModuleProps>('Module');
`;
const FULL_NATIVE_COMPONENT_WITH_TYPE_EXPORT = `
// @flow
@@ -107,4 +193,9 @@ module.exports = {
'NotANativeComponent.js': NOT_A_NATIVE_COMPONENT,
'FullNativeComponent.js': FULL_NATIVE_COMPONENT,
'FullTypedNativeComponent.js': FULL_NATIVE_COMPONENT_WITH_TYPE_EXPORT,
'CommandsWithSimpleCoverageNativeComponent.js': COMMANDS_WITH_SIMPLE_COVERAGE,
'CommandsWithComplexCoverageNativeComponent.js':
COMMANDS_WITH_COMPLEX_COVERAGE,
'CommandsWithTypeCastCoverageNativeComponent.js':
COMMANDS_WITH_TYPE_CAST_COVERAGE,
};
@@ -1,5 +1,77 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Babel plugin inline view configs can inline config for CommandsWithComplexCoverageNativeComponent.js 1`] = `
"// @flow
const codegenNativeCommands = require('codegenNativeCommands');
const codegenNativeComponent = require('codegenNativeComponent');
import type { ViewProps } from 'ViewPropTypes';
import type { NativeComponentType } from 'codegenNativeComponent';
type ModuleProps = $ReadOnly<{|
...ViewProps
|}>;
type NativeType = NativeComponentType<ModuleProps>;
interface NativeCommands {
+seek: (viewRef: React.ElementRef<NativeType>, position: number) => void,
+stop: (viewRef: React.ElementRef<NativeType>) => void,
}
const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry');
let nativeComponentName = 'Module';
export const __INTERNAL_VIEW_CONFIG = {
uiViewClassName: \\"Module\\",
validAttributes: {}
};
export default NativeComponentRegistry.get(nativeComponentName, () => __INTERNAL_VIEW_CONFIG);"
`;
exports[`Babel plugin inline view configs can inline config for CommandsWithSimpleCoverageNativeComponent.js 1`] = `
"// @flow
const codegenNativeCommands = require('codegenNativeCommands');
const codegenNativeComponent = require('codegenNativeComponent');
import type { ViewProps } from 'ViewPropTypes';
import type { NativeComponentType } from 'codegenNativeComponent';
type ModuleProps = $ReadOnly<{|
...ViewProps
|}>;
type NativeType = NativeComponentType<ModuleProps>;
interface NativeCommands {
+pause: (viewRef: React.ElementRef<NativeType>) => void,
+play: (viewRef: React.ElementRef<NativeType>) => void,
}
const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry');
let nativeComponentName = 'Module';
export const __INTERNAL_VIEW_CONFIG = {
uiViewClassName: \\"Module\\",
validAttributes: {}
};
export default NativeComponentRegistry.get(nativeComponentName, () => __INTERNAL_VIEW_CONFIG);"
`;
exports[`Babel plugin inline view configs can inline config for CommandsWithTypeCastCoverageNativeComponent.js 1`] = `
"// @flow
const codegenNativeCommands = require('codegenNativeCommands');
const codegenNativeComponent = require('codegenNativeComponent');
import type { ViewProps } from 'ViewPropTypes';
import type { NativeComponentType } from 'codegenNativeComponent';
type ModuleProps = $ReadOnly<{|
...ViewProps
|}>;
type NativeType = NativeComponentType<ModuleProps>;
interface NativeCommands {
+mute: (viewRef: React.ElementRef<NativeType>) => void,
+unmute: (viewRef: React.ElementRef<NativeType>) => void,
}
const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry');
let nativeComponentName = 'Module';
export const __INTERNAL_VIEW_CONFIG = {
uiViewClassName: \\"Module\\",
validAttributes: {}
};
export default NativeComponentRegistry.get(nativeComponentName, () => __INTERNAL_VIEW_CONFIG);"
`;
exports[`Babel plugin inline view configs can inline config for FullNativeComponent.js 1`] = `
"// @flow
@@ -153,6 +225,61 @@ exports[`Babel plugin inline view configs fails on inline config for CommandsExp
24 |"
`;
exports[`Babel plugin inline view configs fails on inline config for CommandsWithComplexCoverageInvalidNativeComponent.js 1`] = `
"/CommandsWithComplexCoverageInvalidNativeComponent.js: 'Commands' is a reserved export and may only be used to export the result of codegenNativeCommands.
14 |
15 | // Complex coverage instrumentation with invalid nested structure - should fail
> 16 | export const Commands = (
| ^
17 | cov_xyz789().f[1]++,
18 | cov_xyz789().s[2]++,
19 | {"
`;
exports[`Babel plugin inline view configs fails on inline config for CommandsWithCoverageInvalidNativeComponent.js 1`] = `
"/CommandsWithCoverageInvalidNativeComponent.js: 'Commands' is a reserved export and may only be used to export the result of codegenNativeCommands.
14 |
15 | // Coverage instrumentation of invalid Commands export - should still fail
> 16 | export const Commands = (cov_1234567890().s[0]++, {
| ^
17 | hotspotUpdate: () => {},
18 | scrollTo: () => {},
19 | });"
`;
exports[`Babel plugin inline view configs fails on inline config for CommandsWithCoverageTypeCastInvalidNativeComponent.js 1`] = `
"/CommandsWithCoverageTypeCastInvalidNativeComponent.js: 'Commands' is a reserved export and may only be used to export the result of codegenNativeCommands.
19 |
20 | // Coverage instrumentation with type cast but wrong function - should fail
> 21 | export const Commands: NativeCommands = (cov_cast123().s[0]++, invalidFunction({
| ^
22 | supportedCommands: ['pause', 'play'],
23 | }));
24 |"
`;
exports[`Babel plugin inline view configs fails on inline config for CommandsWithCoverageWrongFunctionNativeComponent.js 1`] = `
"/CommandsWithCoverageWrongFunctionNativeComponent.js: 'Commands' is a reserved export and may only be used to export the result of codegenNativeCommands.
14 |
15 | // Coverage instrumentation of wrong function call - should fail
> 16 | export const Commands = (cov_abcdef123().s[0]++, someOtherFunction({
| ^
17 | supportedCommands: ['pause', 'play'],
18 | }));
19 |"
`;
exports[`Babel plugin inline view configs fails on inline config for CommandsWithCoverageWrongNameNativeComponent.js 1`] = `
"/CommandsWithCoverageWrongNameNativeComponent.js: Native commands must be exported with the name 'Commands'
20 |
21 | // Coverage instrumentation with correct function but wrong export name - should fail
> 22 | export const WrongName = (cov_wrong123().s[0]++, codegenNativeCommands<NativeCommands>({
| ^
23 | supportedCommands: ['pause', 'play'],
24 | }));
25 |"
`;
exports[`Babel plugin inline view configs fails on inline config for OtherCommandsExportNativeComponent.js 1`] = `
"/OtherCommandsExportNativeComponent.js: 'Commands' is a reserved export and may only be used to export the result of codegenNativeCommands.
17 | }
+58 -6
View File
@@ -102,6 +102,58 @@ function isCodegenDeclaration(declaration) {
return false;
}
function isCodegenNativeCommandsDeclaration(declaration) {
if (!declaration) {
return false;
}
// Handle direct calls: codegenNativeCommands()
if (
declaration.type === 'CallExpression' &&
declaration.callee &&
declaration.callee.type === 'Identifier' &&
declaration.callee.name === 'codegenNativeCommands'
) {
return true;
}
// Handle coverage instrumentation: (cov_xxx().s[0]++, codegenNativeCommands())
if (declaration.type === 'SequenceExpression' && declaration.expressions) {
// Get the last expression in the sequence (the actual function call)
const lastExpression =
declaration.expressions[declaration.expressions.length - 1];
// Recursively check if the last expression is a valid codegenNativeCommands call
return isCodegenNativeCommandsDeclaration(lastExpression);
}
// Handle Flow type casts: (codegenNativeCommands(): NativeCommands)
if (
(declaration.type === 'TypeCastExpression' ||
declaration.type === 'AsExpression') &&
declaration.expression &&
declaration.expression.type === 'CallExpression' &&
declaration.expression.callee &&
declaration.expression.callee.type === 'Identifier' &&
declaration.expression.callee.name === 'codegenNativeCommands'
) {
return true;
}
// Handle TypeScript assertions: codegenNativeCommands() as NativeCommands
if (
declaration.type === 'TSAsExpression' &&
declaration.expression &&
declaration.expression.type === 'CallExpression' &&
declaration.expression.callee &&
declaration.expression.callee.type === 'Identifier' &&
declaration.expression.callee.name === 'codegenNativeCommands'
) {
return true;
}
return false;
}
module.exports = function ({parse, types: t}) {
return {
pre(state) {
@@ -125,12 +177,12 @@ module.exports = function ({parse, types: t}) {
const firstDeclaration = path.node.declaration.declarations[0];
if (firstDeclaration.type === 'VariableDeclarator') {
if (
firstDeclaration.init &&
firstDeclaration.init.type === 'CallExpression' &&
firstDeclaration.init.callee.type === 'Identifier' &&
firstDeclaration.init.callee.name === 'codegenNativeCommands'
) {
// Check if this is a valid codegenNativeCommands call, handling type annotations
const isValidCommandsExport = isCodegenNativeCommandsDeclaration(
firstDeclaration.init,
);
if (isValidCommandsExport) {
if (
firstDeclaration.id.type === 'Identifier' &&
firstDeclaration.id.name !== 'Commands'
@@ -40,6 +40,9 @@
"peerDependenciesMeta": {
"@react-native-community/cli": {
"optional": true
},
"@react-native/metro-config": {
"optional": true
}
},
"engines": {
@@ -31,9 +31,9 @@ type MiddlewareReturn = {
...
};
// $FlowFixMe
// $FlowFixMe[incompatible-type]
const unusedStubWSServer: ws$WebSocketServer = {};
// $FlowFixMe
// $FlowFixMe[incompatible-type]
const unusedMiddlewareStub: Server = {};
const communityMiddlewareFallback = {
@@ -36,7 +36,7 @@ function handleLaunchArgs(argv: string[]) {
});
// Find an existing window for this app and launch configuration.
const existingWindow = BrowserWindow.getAllWindows().find(window => {
let frontendWindow = BrowserWindow.getAllWindows().find(window => {
const metadata = windowMetadata.get(window);
if (!metadata) {
return false;
@@ -44,41 +44,37 @@ function handleLaunchArgs(argv: string[]) {
return metadata.windowKey === windowKey;
});
if (existingWindow) {
if (frontendWindow) {
// If the window is already visible, flash it.
if (existingWindow.isVisible()) {
existingWindow.flashFrame(true);
if (frontendWindow.isVisible()) {
frontendWindow.flashFrame(true);
setTimeout(() => {
existingWindow.flashFrame(false);
frontendWindow.flashFrame(false);
}, 1000);
}
if (process.platform === 'darwin') {
app.focus({
steal: true,
});
}
existingWindow.focus();
return;
} else {
// Create the browser window.
frontendWindow = new BrowserWindow({
width: 1200,
height: 600,
webPreferences: {
partition: 'persist:react-native-devtools',
preload: require.resolve('./preload.js'),
},
// Icon for Linux
icon: path.join(__dirname, 'resources', 'icon.png'),
});
}
// Create the browser window.
const frontendWindow = new BrowserWindow({
width: 1200,
height: 600,
webPreferences: {
partition: 'persist:react-native-devtools',
preload: require.resolve('./preload.js'),
},
// Icon for Linux
icon: path.join(__dirname, 'resources', 'icon.png'),
});
// Open links in the default browser instead of in new Electron windows.
frontendWindow.webContents.setWindowOpenHandler(({url}) => {
shell.openExternal(url);
return {action: 'deny'};
});
// TODO: If the window contains a live, working frontend instance with a valid connection to the backend,
// we should avoid this reload and instead send the frontend a message to handle the launch arguments
// dynamically (e.g. update the launch ID for telemetry purposes, handle deeplinking to a specific CDT panel, etc).
frontendWindow.loadURL(frontendUrl);
windowMetadata.set(frontendWindow, {
@@ -90,6 +86,7 @@ function handleLaunchArgs(argv: string[]) {
steal: true,
});
}
frontendWindow.focus();
}
app.whenReady().then(() => {
@@ -58,11 +58,11 @@ class PrepareBoostTaskTest {
val boostThirdPartyJniPath = tempFolder.newFolder("boostpath/jni")
val output = tempFolder.newFolder("output")
val task =
createTestTask<PrepareBoostTask> {
it.boostPath.setFrom(boostpath)
it.boostThirdPartyJniPath.set(boostThirdPartyJniPath)
it.boostVersion.set("1.0.0")
it.outputDir.set(output)
createTestTask<PrepareBoostTask> { task ->
task.boostPath.setFrom(boostpath)
task.boostThirdPartyJniPath.set(boostThirdPartyJniPath)
task.boostVersion.set("1.0.0")
task.outputDir.set(output)
}
File(boostpath, "asm/asm.S").apply {
parentFile.mkdirs()
@@ -79,11 +79,11 @@ class PrepareBoostTaskTest {
val boostThirdPartyJniPath = tempFolder.newFolder("boostpath/jni")
val output = tempFolder.newFolder("output")
val task =
createTestTask<PrepareBoostTask> {
it.boostPath.setFrom(boostpath)
it.boostThirdPartyJniPath.set(boostThirdPartyJniPath)
it.boostVersion.set("1.0.0")
it.outputDir.set(output)
createTestTask<PrepareBoostTask> { task ->
task.boostPath.setFrom(boostpath)
task.boostThirdPartyJniPath.set(boostThirdPartyJniPath)
task.boostVersion.set("1.0.0")
task.outputDir.set(output)
}
File(boostpath, "boost_1.0.0/boost/config.hpp").apply {
parentFile.mkdirs()
@@ -100,11 +100,11 @@ class PrepareBoostTaskTest {
val boostThirdPartyJniPath = tempFolder.newFolder("boostpath/jni")
val output = tempFolder.newFolder("output")
val task =
createTestTask<PrepareBoostTask> {
it.boostPath.setFrom(boostpath)
it.boostThirdPartyJniPath.set(boostThirdPartyJniPath)
it.boostVersion.set("1.0.0")
it.outputDir.set(output)
createTestTask<PrepareBoostTask> { task ->
task.boostPath.setFrom(boostpath)
task.boostThirdPartyJniPath.set(boostThirdPartyJniPath)
task.boostVersion.set("1.0.0")
task.outputDir.set(output)
}
File(boostpath, "boost/boost/config.hpp").apply {
parentFile.mkdirs()
@@ -186,9 +186,9 @@ class PreparePrefabHeadersTaskTest {
val project = createProject(projectDir = tempFolder.root)
val task =
createTestTask<PreparePrefabHeadersTask>(project = project) {
it.outputDir.set(outputDir)
it.input.set(listOf(PrefabPreprocessingEntry("sample_library", "boost/" to "")))
createTestTask<PreparePrefabHeadersTask>(project = project) { task ->
task.outputDir.set(outputDir)
task.input.set(listOf(PrefabPreprocessingEntry("sample_library", "boost/" to "")))
}
task.taskAction()
@@ -59,8 +59,8 @@ internal fun createZip(dest: File, paths: List<String>) {
val uri = URI.create("jar:file:$dest")
FileSystems.newFileSystem(uri, env).use { zipfs ->
paths.forEach {
val zipEntryPath = zipfs.getPath(it)
paths.forEach { path ->
val zipEntryPath = zipfs.getPath(path)
val zipEntryFolder = zipEntryPath.subpath(0, zipEntryPath.nameCount - 1)
Files.createDirectories(zipEntryFolder)
Files.createFile(zipEntryPath)
@@ -47,7 +47,7 @@ it('refuses non-spec compliant colors', () => {
expect(normalizeColor('rgb (0, 1, 2)')).toBe(null);
expect(normalizeColor('rgba(0 0 0 0.0)')).toBe(null);
expect(normalizeColor('hsv(0, 1, 2)')).toBe(null);
// $FlowExpectedError - Intentionally malformed argument.
// $FlowExpectedError[incompatible-type] - Intentionally malformed argument.
expect(normalizeColor({r: 10, g: 10, b: 10})).toBe(null);
expect(normalizeColor('hsl(1%, 2, 3)')).toBe(null);
expect(normalizeColor('rgb(1%, 2%, 3%)')).toBe(null);
+1 -1
View File
@@ -218,7 +218,7 @@ const transform /*: BabelTransformer['transform'] */ = ({
// The result from `transformFromAstSync` can be null (if the file is ignored)
if (!result) {
/* $FlowFixMe BabelTransformer specifies that the `ast` can never be null but
/* $FlowFixMe[incompatible-type] BabelTransformer specifies that the `ast` can never be null but
* the function returns here. Discovered when typing `BabelNode`. */
return {ast: null};
}
@@ -350,6 +350,8 @@ function setDefaultValue(
common.default = ((defaultValue ? defaultValue : 0): number);
break;
case 'FloatTypeAnnotation':
/* $FlowFixMe[invalid-compare] Error discovered during Constant Condition
* roll out. See https://fburl.com/workplace/5whu3i34. */
common.default = ((defaultValue === null
? null
: defaultValue
@@ -357,6 +359,8 @@ function setDefaultValue(
: 0): number | null);
break;
case 'BooleanTypeAnnotation':
/* $FlowFixMe[invalid-compare] Error discovered during Constant Condition
* roll out. See https://fburl.com/workplace/5whu3i34. */
common.default = defaultValue === null ? null : !!defaultValue;
break;
case 'StringTypeAnnotation':
@@ -275,7 +275,7 @@ export function formatNativeSpecErrorStore(
export function formatDiffSet(summary: DiffSummary): FormattedDiffSummary {
const summaryStatus = summary.status;
if (summaryStatus === 'ok' || summaryStatus === 'patchable') {
// $FlowFixMe I don't think we can ever get in this branch
// $FlowFixMe[incompatible-type] I don't think we can ever get in this branch
return summary;
}
const hasteModules = Object.keys(summary.incompatibilityReport);
@@ -77,6 +77,8 @@ const ActionSheetIOS = {
callback: (buttonIndex: number) => void,
) {
invariant(
/* $FlowFixMe[invalid-compare] Error discovered during Constant Condition
* roll out. See https://fburl.com/workplace/5whu3i34. */
typeof options === 'object' && options !== null,
'Options must be a valid object',
);
@@ -162,6 +164,8 @@ const ActionSheetIOS = {
successCallback: Function | ((success: boolean, method: ?string) => void),
) {
invariant(
/* $FlowFixMe[invalid-compare] Error discovered during Constant Condition
* roll out. See https://fburl.com/workplace/5whu3i34. */
typeof options === 'object' && options !== null,
'Options must be a valid object',
);
@@ -54,7 +54,8 @@ const AnimatedScrollView: AnimatedComponentType<
props.style != null
) {
return (
// $FlowFixMe - It should return an Animated ScrollView but it returns a ScrollView with Animated props applied.
// $FlowFixMe[incompatible-type] - It should return an Animated ScrollView but it returns a ScrollView with Animated props applied.
// $FlowFixMe[incompatible-variance]
<AnimatedScrollViewWithInvertedRefreshControl
scrollEventThrottle={0.0001}
{...props}
@@ -14,7 +14,7 @@ import SectionList, {type SectionListProps} from '../../Lists/SectionList';
import createAnimatedComponent from '../createAnimatedComponent';
import * as React from 'react';
// $FlowFixMe
// $FlowFixMe[incompatible-type]
export default (createAnimatedComponent(SectionList): component<
// $FlowExpectedError[unclear-type]
ItemT = any,
@@ -18,6 +18,8 @@ export class URLSearchParams {
}
constructor(params?: Record<string, string> | string | [string, string][]) {
/* $FlowFixMe[invalid-compare] Error discovered during Constant Condition
* roll out. See https://fburl.com/workplace/5whu3i34. */
if (params === null) {
return;
}
@@ -1503,7 +1503,7 @@ class ScrollView extends React.Component<ScrollViewProps, ScrollViewState> {
keyboardNeverPersistTaps &&
this._keyboardIsDismissible() &&
e.target != null &&
// $FlowFixMe Error supressed during the migration of HostInstance to ReactNativeElement
// $FlowFixMe[incompatible-type] Error supressed during the migration of HostInstance to ReactNativeElement
!TextInputState.isTextInput(e.target)
) {
return true;
@@ -88,7 +88,7 @@ function focusTextInput(textField: ?HostInstance) {
if (textField != null) {
const fieldCanBeFocused =
currentlyFocusedInputRef !== textField &&
// $FlowFixMe - `currentProps` is missing in `NativeMethods`
// $FlowFixMe[prop-missing] - `currentProps` is missing in `NativeMethods`
textField.currentProps?.editable !== false;
if (!fieldCanBeFocused) {
@@ -123,7 +123,7 @@ jest.unmock('../TextInput');
throw new Error('Expected `textInputElement` to be non-null');
}
// $FlowFixMe
// $FlowFixMe[prop-missing]
textInputElement.currentProps = textInputElement.props;
expect(textInputElement.isFocused()).toBe(false);
@@ -387,7 +387,7 @@ if (ReactNativeFeatureFlags.reduceDefaultPropsInImage()) {
// in order to have a better alignment between platforms in the future.
src: sources,
source: sources,
/* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found
/* $FlowFixMe[prop-missing](>=0.78.0 site=react_native_android_fb) This issue was found
* when making Flow check .android.js files. */
headers: (source?.[0]?.headers || source?.headers: ?{[string]: string}),
defaultSource: defaultSource ? defaultSource.uri : null,
@@ -36,7 +36,7 @@ export function testBadDataWithTypicalItem(): React.Node {
key: 1,
},
];
// $FlowExpectedError - bad title type 6, should be string
// $FlowExpectedError[incompatible-type] - bad title type 6, should be string
return <FlatList renderItem={renderMyListItem} data={data} />;
}
@@ -46,7 +46,7 @@ export function testMissingFieldWithTypicalItem(): React.Node {
key: 1,
},
];
// $FlowExpectedError - missing title
// $FlowExpectedError[incompatible-type] - missing title
return <FlatList renderItem={renderMyListItem} data={data} />;
}
@@ -62,7 +62,7 @@ export function testGoodDataWithBadCustomRenderItemFunction(): React.Node {
renderItem={info => (
<span>
{
// $FlowExpectedError - bad widgetCount type 6, should be Object
// $FlowExpectedError[prop-missing] - bad widgetCount type 6, should be Object
info.item.widget.missingProp
}
</span>
@@ -80,22 +80,26 @@ export function testBadRenderItemFunction(): $ReadOnlyArray<React.Node> {
},
];
return [
// $FlowExpectedError - title should be inside `item`
// $FlowExpectedError[incompatible-type] - title should be inside `item`
// $FlowExpectedError[incompatible-exact]
<FlatList renderItem={(info: {title: string}) => <span />} data={data} />,
<FlatList
// $FlowExpectedError - bad index type string, should be number
// $FlowExpectedError[incompatible-type] - bad index type string, should be number
// $FlowExpectedError[incompatible-exact]
// $FlowExpectedError[unclear-type]
renderItem={(info: {item: any, index: string}) => <span />}
data={data}
/>,
<FlatList
// $FlowExpectedError - bad title type number, should be string
// $FlowExpectedError[incompatible-type] - bad index type string, should be number
// $FlowExpectedError[incompatible-exact]
renderItem={(info: {item: {title: number}}) => <span />}
// $FlowExpectedError - bad title type number, should be string
// $FlowExpectedError[incompatible-type] - bad title type number, should be string
data={data}
/>,
// EverythingIsFine
<FlatList
// $FlowExpectedError - bad title type number, should be string
// $FlowExpectedError[incompatible-type] - bad title type number, should be string
renderItem={(info: {item: {title: string, ...}, ...}) => <span />}
data={data}
/>,
@@ -104,11 +108,11 @@ export function testBadRenderItemFunction(): $ReadOnlyArray<React.Node> {
export function testOtherBadProps(): $ReadOnlyArray<React.Node> {
return [
// $FlowExpectedError - bad numColumns type "lots"
// $FlowExpectedError[incompatible-type] - bad numColumns type "lots"
<FlatList renderItem={renderMyListItem} data={[]} numColumns="lots" />,
// $FlowExpectedError - bad windowSize type "big"
// $FlowExpectedError[incompatible-type] - bad windowSize type "big"
<FlatList renderItem={renderMyListItem} data={[]} windowSize="big" />,
// $FlowExpectedError - missing `data` prop
// $FlowExpectedError[incompatible-type] - missing `data` prop
<FlatList renderItem={renderMyListItem} />,
];
}
@@ -55,12 +55,13 @@ export function testBadRenderItemFunction(): $ReadOnlyArray<React.Node> {
];
return [
<SectionList
// $FlowExpectedError - title should be inside `item`
// $FlowExpectedError[incompatible-type] - title should be inside `item`
renderItem={(info: {title: string, ...}) => <span />}
sections={sections}
/>,
<SectionList
// $FlowExpectedError - bad index type string, should be number
// $FlowExpectedError[incompatible-type] - bad index type string, should be number
// $FlowExpectedError[incompatible-exact]
renderItem={(info: {index: string}) => <span />}
sections={sections}
/>,
@@ -78,14 +79,14 @@ export function testBadInheritedDefaultProp(): React.MixedElement {
<SectionList
renderItem={renderMyListItem}
sections={sections}
// $FlowExpectedError - bad windowSize type "big"
// $FlowExpectedError[incompatible-type] - bad windowSize type "big"
windowSize="big"
/>
);
}
export function testMissingData(): React.MixedElement {
// $FlowExpectedError - missing `sections` prop
// $FlowExpectedError[incompatible-type] - missing `sections` prop
return <SectionList renderItem={renderMyListItem} />;
}
@@ -122,7 +123,7 @@ export function testBadSectionsMetadata(): React.MixedElement {
<SectionList
renderSectionHeader={renderMyHeader}
renderItem={renderMyListItem}
/* $FlowExpectedError - section has bad meta data `fooNumber` field of
/* $FlowExpectedError[incompatible-type] - section has bad meta data `fooNumber` field of
* type string */
sections={sections}
/>
@@ -58,12 +58,12 @@ export default class ReactFabricHostComponent implements NativeMethods {
}
blur() {
// $FlowFixMe - Error supressed during the migration of HostInstance to ReactNativeElement
// $FlowFixMe[incompatible-type] - Error supressed during the migration of HostInstance to ReactNativeElement
TextInputState.blurTextInput(this);
}
focus() {
// $FlowFixMe - Error supressed during the migration of HostInstance to ReactNativeElement
// $FlowFixMe[incompatible-type] - Error supressed during the migration of HostInstance to ReactNativeElement
TextInputState.focusTextInput(this);
}
@@ -47,14 +47,14 @@ const getMethod: (<MethodName: $Keys<ReactFabricType>>(
) => ReactNativeType[MethodName]) = (getRenderer, methodName) => {
let cachedImpl;
// $FlowExpectedError
// $FlowExpectedError[incompatible-type]
return function (arg1, arg2, arg3, arg4, arg5, arg6) {
if (cachedImpl == null) {
// $FlowExpectedError
// $FlowExpectedError[prop-missing]
cachedImpl = getRenderer()[methodName];
}
// $FlowExpectedError
// $FlowExpectedError[extra-arg]
return cachedImpl(arg1, arg2, arg3, arg4, arg5);
};
};
@@ -7,7 +7,7 @@
* @noformat
* @nolint
* @flow strict-local
* @generated SignedSource<<83073425aa3f71ced2c8c51f25a25938>>
* @generated SignedSource<<1f7876c0dc0b05685a730513dc410236>>
*/
'use strict';
@@ -82,6 +82,8 @@ export function register(name: string, callback: () => ViewConfig): string {
typeof callback === 'function',
'View config getter callback for component `%s` must be a function (received `%s`)',
name,
/* $FlowFixMe[invalid-compare] Error discovered during Constant Condition
* roll out. See https://fburl.com/workplace/5whu3i34. */
callback === null ? 'null' : typeof callback,
);
viewConfigCallbacks.set(name, callback);
+4
View File
@@ -83,6 +83,8 @@ class Share {
options?: ShareOptions = {},
): Promise<{action: string, activityType: ?string}> {
invariant(
/* $FlowFixMe[invalid-compare] Error discovered during Constant Condition
* roll out. See https://fburl.com/workplace/5whu3i34. */
typeof content === 'object' && content !== null,
'Content to share must be a valid object',
);
@@ -91,6 +93,8 @@ class Share {
'At least one of URL or message is required',
);
invariant(
/* $FlowFixMe[invalid-compare] Error discovered during Constant Condition
* roll out. See https://fburl.com/workplace/5whu3i34. */
typeof options === 'object' && options !== null,
'Options must be a valid object',
);
@@ -37,17 +37,17 @@ export function testGoodCompose() {
}
export function testBadCompose() {
// $FlowExpectedError - Incompatible type.
// $FlowExpectedError[incompatible-type] - Incompatible type.
(StyleSheet.compose(textStyle, textStyle): ImageStyleProp);
// $FlowExpectedError - Incompatible type.
// $FlowExpectedError[incompatible-type] - Incompatible type.
(StyleSheet.compose(
// $FlowExpectedError - Incompatible type.
[textStyle],
null,
): ImageStyleProp);
// $FlowExpectedError - Incompatible type.
// $FlowExpectedError[incompatible-type] - Incompatible type.
(StyleSheet.compose(
Math.random() < 0.5 ? textStyle : null,
null,
@@ -69,9 +69,9 @@ export default function processFilter(
if (amount != null) {
const filterFunction = {};
// $FlowFixMe The key will be the correct one but flow can't see that.
// $FlowFixMe[prop-missing] The key will be the correct one but flow can't see that.
filterFunction[camelizedName] = amount;
// $FlowFixMe The key will be the correct one but flow can't see that.
// $FlowFixMe[incompatible-type] The key will be the correct one but flow can't see that.
result.push(filterFunction);
} else {
// If any primitive is invalid then apply none of the filters. This is how
@@ -85,7 +85,7 @@ export default function processFilter(
for (const filterFunction of filter) {
const [filterName, filterValue] = Object.entries(filterFunction)[0];
if (filterName === 'dropShadow') {
// $FlowFixMe
// $FlowFixMe[incompatible-type]
const dropShadow = parseDropShadow(filterValue);
if (dropShadow == null) {
return [];
@@ -96,9 +96,9 @@ export default function processFilter(
if (amount != null) {
const resultObject = {};
// $FlowFixMe
// $FlowFixMe[prop-missing]
resultObject[filterName] = amount;
// $FlowFixMe
// $FlowFixMe[incompatible-type]
result.push(resultObject);
} else {
// If any primitive is invalid then apply none of the filters. This is how
@@ -165,6 +165,8 @@ const HMRClient: HMRClientNativeInterface = {
// Moving to top gives errors due to NativeModules not being initialized
const DevLoadingView = require('./DevLoadingView').default;
/* $FlowFixMe[invalid-compare] Error discovered during Constant Condition
* roll out. See https://fburl.com/workplace/5whu3i34. */
const serverHost = port !== null && port !== '' ? `${host}:${port}` : host;
const serverScheme = scheme;
@@ -33,6 +33,8 @@ function deepFreezeAndThrowOnMutationInDev<T: {...} | Array<mixed>>(
if (__DEV__) {
if (
typeof object !== 'object' ||
/* $FlowFixMe[invalid-compare] Error discovered during Constant Condition
* roll out. See https://fburl.com/workplace/5whu3i34. */
object === null ||
Object.isFrozen(object) ||
Object.isSealed(object)
@@ -232,6 +232,8 @@ const WebSocketInterceptor = {
_arrayBufferToString(data: string): ArrayBuffer | string {
const value = base64.toByteArray(data).buffer;
/* $FlowFixMe[invalid-compare] Error discovered during Constant Condition
* roll out. See https://fburl.com/workplace/5whu3i34. */
if (value === undefined || value === null) {
return '(no value)';
}
@@ -106,27 +106,27 @@ describe('listeners', () => {
}).not.toThrow();
expect(() => {
// $FlowExpectedError
// $FlowExpectedError[incompatible-type]
emitter.addListener('A', null);
}).toThrow();
expect(() => {
// $FlowExpectedError
// $FlowExpectedError[incompatible-type]
emitter.addListener('A', undefined);
}).toThrow();
expect(() => {
// $FlowExpectedError
// $FlowExpectedError[incompatible-type]
emitter.addListener('A', 'abc');
}).toThrow();
expect(() => {
// $FlowExpectedError
// $FlowExpectedError[incompatible-type]
emitter.addListener('A', 123);
}).toThrow();
expect(() => {
// $FlowExpectedError
// $FlowExpectedError[incompatible-type]
emitter.addListener('A', 123);
}).toThrow();
});
+3 -1
View File
@@ -415,7 +415,9 @@ CGSize RCTSwitchSize(void)
static CGSize rctSwitchSize;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
rctSwitchSize = [UISwitch new].intrinsicContentSize;
RCTUnsafeExecuteOnMainQueueSync(^{
rctSwitchSize = [UISwitch new].intrinsicContentSize;
});
});
return rctSwitchSize;
}
@@ -230,21 +230,34 @@ static BOOL sIsAccessibilityUsed = NO;
scrollView.contentOffset.y,
scrollView.frame.size.width,
scrollView.frame.size.height);
const CGFloat visibleWidth = thresholdRect.size.width;
const CGFloat visibleHeight = thresholdRect.size.height;
if (CGRectOverlaps(targetRect, thresholdRect)) {
newMode = RCTVirtualViewModeVisible;
} else {
auto prerender = false;
const CGFloat prerenderRatio = ReactNativeFeatureFlags::virtualViewPrerenderRatio();
if (prerenderRatio > 0) {
thresholdRect = CGRectInset(
thresholdRect, -thresholdRect.size.width * prerenderRatio, -thresholdRect.size.height * prerenderRatio);
thresholdRect = CGRectInset(thresholdRect, -visibleWidth * prerenderRatio, -visibleHeight * prerenderRatio);
prerender = CGRectOverlaps(targetRect, thresholdRect);
}
if (prerender) {
newMode = RCTVirtualViewModePrerender;
} else {
newMode = RCTVirtualViewModeHidden;
thresholdRect = CGRectZero;
const CGFloat hysteresisRatio = ReactNativeFeatureFlags::virtualViewHysteresisRatio();
if (_mode.has_value() && hysteresisRatio > 0) {
thresholdRect = CGRectInset(thresholdRect, -visibleWidth * hysteresisRatio, -visibleHeight * hysteresisRatio);
if (CGRectOverlaps(targetRect, thresholdRect)) {
newMode = _mode.value();
} else {
newMode = RCTVirtualViewModeHidden;
thresholdRect = CGRectZero;
}
} else {
newMode = RCTVirtualViewModeHidden;
thresholdRect = CGRectZero;
}
}
}
@@ -744,34 +744,6 @@ public abstract class com/facebook/react/bridge/GuardedRunnable : java/lang/Runn
public abstract fun runGuarded ()V
}
public final class com/facebook/react/bridge/Inspector {
public static final field Companion Lcom/facebook/react/bridge/Inspector$Companion;
public static final fun connect (ILcom/facebook/react/bridge/Inspector$RemoteConnection;)Lcom/facebook/react/bridge/Inspector$LocalConnection;
public static final fun getPages ()Ljava/util/List;
}
public final class com/facebook/react/bridge/Inspector$Companion {
public final fun connect (ILcom/facebook/react/bridge/Inspector$RemoteConnection;)Lcom/facebook/react/bridge/Inspector$LocalConnection;
public final fun getPages ()Ljava/util/List;
}
public final class com/facebook/react/bridge/Inspector$LocalConnection {
public final fun disconnect ()V
public final fun sendMessage (Ljava/lang/String;)V
}
public final class com/facebook/react/bridge/Inspector$Page {
public final fun getId ()I
public final fun getTitle ()Ljava/lang/String;
public final fun getVM ()Ljava/lang/String;
public fun toString ()Ljava/lang/String;
}
public abstract interface class com/facebook/react/bridge/Inspector$RemoteConnection {
public abstract fun onDisconnect ()V
public abstract fun onMessage (Ljava/lang/String;)V
}
public class com/facebook/react/bridge/JSApplicationCausedNativeException : java/lang/RuntimeException {
public fun <init> (Ljava/lang/String;)V
public fun <init> (Ljava/lang/String;Ljava/lang/Throwable;)V
@@ -1018,10 +990,6 @@ public abstract interface class com/facebook/react/bridge/NotThreadSafeBridgeIdl
public abstract fun onTransitionToBridgeIdle ()V
}
public abstract interface class com/facebook/react/bridge/OnBatchCompleteListener {
public abstract fun onBatchComplete ()V
}
public abstract interface class com/facebook/react/bridge/PerformanceCounter {
public abstract fun getPerformanceCounters ()Ljava/util/Map;
public abstract fun profileNextBatch ()V
@@ -1863,15 +1831,9 @@ public class com/facebook/react/defaults/DefaultReactActivityDelegate : com/face
public final class com/facebook/react/defaults/DefaultReactHost {
public static final field INSTANCE Lcom/facebook/react/defaults/DefaultReactHost;
public static final fun getDefaultReactHost (Landroid/content/Context;Lcom/facebook/react/ReactNativeHost;Lcom/facebook/react/runtime/JSRuntimeFactory;)Lcom/facebook/react/ReactHost;
public static final fun getDefaultReactHost (Landroid/content/Context;Ljava/util/List;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/facebook/react/runtime/JSRuntimeFactory;ZLjava/util/List;)Lcom/facebook/react/ReactHost;
public static final fun getDefaultReactHost (Landroid/content/Context;Ljava/util/List;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/facebook/react/runtime/JSRuntimeFactory;ZLjava/util/List;Lkotlin/jvm/functions/Function1;Lcom/facebook/react/runtime/BindingsInstaller;)Lcom/facebook/react/ReactHost;
public static final fun getDefaultReactHost (Landroid/content/Context;Ljava/util/List;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZLjava/util/List;)Lcom/facebook/react/ReactHost;
public static final fun getDefaultReactHost (Landroid/content/Context;Ljava/util/List;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZLjava/util/List;Lkotlin/jvm/functions/Function1;Lcom/facebook/react/runtime/BindingsInstaller;)Lcom/facebook/react/ReactHost;
public static synthetic fun getDefaultReactHost$default (Landroid/content/Context;Lcom/facebook/react/ReactNativeHost;Lcom/facebook/react/runtime/JSRuntimeFactory;ILjava/lang/Object;)Lcom/facebook/react/ReactHost;
public static synthetic fun getDefaultReactHost$default (Landroid/content/Context;Ljava/util/List;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/facebook/react/runtime/JSRuntimeFactory;ZLjava/util/List;ILjava/lang/Object;)Lcom/facebook/react/ReactHost;
public static synthetic fun getDefaultReactHost$default (Landroid/content/Context;Ljava/util/List;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/facebook/react/runtime/JSRuntimeFactory;ZLjava/util/List;Lkotlin/jvm/functions/Function1;Lcom/facebook/react/runtime/BindingsInstaller;ILjava/lang/Object;)Lcom/facebook/react/ReactHost;
public static synthetic fun getDefaultReactHost$default (Landroid/content/Context;Ljava/util/List;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZLjava/util/List;ILjava/lang/Object;)Lcom/facebook/react/ReactHost;
public static synthetic fun getDefaultReactHost$default (Landroid/content/Context;Ljava/util/List;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZLjava/util/List;Lkotlin/jvm/functions/Function1;Lcom/facebook/react/runtime/BindingsInstaller;ILjava/lang/Object;)Lcom/facebook/react/ReactHost;
}
public abstract class com/facebook/react/defaults/DefaultReactNativeHost : com/facebook/react/ReactNativeHost {
@@ -4368,7 +4330,6 @@ public class com/facebook/react/uimanager/UIManagerModule : com/facebook/react/b
public fun addRootView (Landroid/view/View;Lcom/facebook/react/bridge/WritableMap;)I
public fun addUIBlock (Lcom/facebook/react/uimanager/UIBlock;)V
public fun addUIManagerEventListener (Lcom/facebook/react/bridge/UIManagerListener;)V
public fun addUIManagerListener (Lcom/facebook/react/uimanager/UIManagerModuleListener;)V
public fun clearJSResponder ()V
public fun configureNextLayoutAnimation (Lcom/facebook/react/bridge/ReadableMap;Lcom/facebook/react/bridge/Callback;Lcom/facebook/react/bridge/Callback;)V
public static fun createConstants (Ljava/util/List;Ljava/util/Map;Ljava/util/Map;)Ljava/util/Map;
@@ -4405,7 +4366,6 @@ public class com/facebook/react/uimanager/UIManagerModule : com/facebook/react/b
public fun receiveEvent (ILjava/lang/String;Lcom/facebook/react/bridge/WritableMap;)V
public fun removeRootView (I)V
public fun removeUIManagerEventListener (Lcom/facebook/react/bridge/UIManagerListener;)V
public fun removeUIManagerListener (Lcom/facebook/react/uimanager/UIManagerModuleListener;)V
public fun resolveCustomDirectEventName (Ljava/lang/String;)Ljava/lang/String;
public fun resolveRootTagFromReactTag (I)I
public fun resolveView (I)Landroid/view/View;
@@ -5687,6 +5647,8 @@ public class com/facebook/react/views/scroll/ReactHorizontalScrollViewManager :
public fun flashScrollIndicators (Lcom/facebook/react/views/scroll/ReactHorizontalScrollView;)V
public synthetic fun flashScrollIndicators (Ljava/lang/Object;)V
public fun getName ()Ljava/lang/String;
public synthetic fun prepareToRecycleView (Lcom/facebook/react/uimanager/ThemedReactContext;Landroid/view/View;)Landroid/view/View;
protected fun prepareToRecycleView (Lcom/facebook/react/uimanager/ThemedReactContext;Lcom/facebook/react/views/scroll/ReactHorizontalScrollView;)Lcom/facebook/react/views/scroll/ReactHorizontalScrollView;
public synthetic fun receiveCommand (Landroid/view/View;ILcom/facebook/react/bridge/ReadableArray;)V
public synthetic fun receiveCommand (Landroid/view/View;Ljava/lang/String;Lcom/facebook/react/bridge/ReadableArray;)V
public fun receiveCommand (Lcom/facebook/react/views/scroll/ReactHorizontalScrollView;ILcom/facebook/react/bridge/ReadableArray;)V
@@ -5950,6 +5912,8 @@ public class com/facebook/react/views/scroll/ReactScrollViewManager : com/facebo
public fun getCommandsMap ()Ljava/util/Map;
public fun getExportedCustomDirectEventTypeConstants ()Ljava/util/Map;
public fun getName ()Ljava/lang/String;
public synthetic fun prepareToRecycleView (Lcom/facebook/react/uimanager/ThemedReactContext;Landroid/view/View;)Landroid/view/View;
protected fun prepareToRecycleView (Lcom/facebook/react/uimanager/ThemedReactContext;Lcom/facebook/react/views/scroll/ReactScrollView;)Lcom/facebook/react/views/scroll/ReactScrollView;
public synthetic fun receiveCommand (Landroid/view/View;ILcom/facebook/react/bridge/ReadableArray;)V
public synthetic fun receiveCommand (Landroid/view/View;Ljava/lang/String;Lcom/facebook/react/bridge/ReadableArray;)V
public fun receiveCommand (Lcom/facebook/react/views/scroll/ReactScrollView;ILcom/facebook/react/bridge/ReadableArray;)V
@@ -1,78 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.react.bridge
import com.facebook.common.logging.FLog
import com.facebook.jni.HybridData
import com.facebook.proguard.annotations.DoNotStrip
import com.facebook.react.common.ReactConstants
@DoNotStrip
public class Inspector
private constructor(@Suppress("NoHungarianNotation") private val mHybridData: HybridData) {
private external fun getPagesNative(): Array<Page>
private external fun connectNative(pageId: Int, remote: RemoteConnection): LocalConnection?
@DoNotStrip
public class Page
private constructor(private val id: Int, private val title: String, private val vm: String) {
public fun getId(): Int = id
public fun getTitle(): String = title
public fun getVM(): String = vm
override fun toString(): String = "Page{id=$id, title='$title'}"
}
@DoNotStrip
public interface RemoteConnection {
@DoNotStrip public fun onMessage(message: String)
@DoNotStrip public fun onDisconnect()
}
@DoNotStrip
public class LocalConnection
private constructor(@Suppress("NoHungarianNotation") private val mHybridData: HybridData) {
public external fun sendMessage(message: String)
public external fun disconnect()
}
public companion object {
init {
ReactNativeJNISoLoader.staticInit()
}
@JvmStatic
public fun getPages(): List<Page> {
return try {
instance().getPagesNative().toList()
} catch (e: UnsatisfiedLinkError) {
FLog.e(ReactConstants.TAG, "Inspector doesn't work in open source yet", e)
emptyList()
}
}
@JvmStatic
public fun connect(pageId: Int, remote: RemoteConnection): LocalConnection {
return try {
instance().connectNative(pageId, remote)
?: throw IllegalStateException("Can't open failed connection")
} catch (e: UnsatisfiedLinkError) {
FLog.e(ReactConstants.TAG, "Inspector doesn't work in open source yet", e)
throw RuntimeException(e)
}
}
@JvmStatic private external fun instance(): Inspector
}
}
@@ -189,7 +189,7 @@ internal class JavaMethodWrapper(
}
if (jsArgumentsNeeded != parameters.size()) {
throw NativeArgumentsParseException(
throw JSApplicationCausedNativeException(
"$traceName got ${parameters.size()} arguments, expected $jsArgumentsNeeded"
)
}
@@ -208,7 +208,7 @@ internal class JavaMethodWrapper(
i++
}
} catch (e: UnexpectedNativeTypeException) {
throw NativeArgumentsParseException(
throw JSApplicationCausedNativeException(
"${e.message} (constructing arguments for $traceName at argument index ${
getAffectedRange(
jsArgumentsConsumed,
@@ -218,7 +218,7 @@ internal class JavaMethodWrapper(
e,
)
} catch (e: NullPointerException) {
throw NativeArgumentsParseException(
throw JSApplicationCausedNativeException(
"${e.message} (constructing arguments for $traceName at argument index ${
getAffectedRange(
jsArgumentsConsumed,
@@ -1,34 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.react.bridge
import com.facebook.react.common.annotations.internal.LegacyArchitecture
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger
/** Exception thrown when a native module method call receives unexpected arguments from JS. */
@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 NativeArgumentsParseException : JSApplicationCausedNativeException {
constructor(detailMessage: String) : super(detailMessage)
constructor(detailMessage: String, throwable: Throwable?) : super(detailMessage, throwable)
private companion object {
init {
LegacyArchitectureLogger.assertLegacyArchitecture(
"NativeArgumentsParseException",
logLevel = LegacyArchitectureLogLevel.ERROR,
)
}
}
}
@@ -16,6 +16,6 @@ import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING,
)
public fun interface OnBatchCompleteListener {
public fun onBatchComplete()
internal fun interface OnBatchCompleteListener {
fun onBatchComplete()
}
@@ -7,8 +7,10 @@
package com.facebook.react.bridge
import com.facebook.react.common.annotations.internal.InteropLegacyArchitecture
import com.facebook.soloader.SoLoader
@InteropLegacyArchitecture
internal object ReactNativeJNISoLoader {
@JvmStatic
@@ -35,50 +35,6 @@ import java.lang.Exception
public object DefaultReactHost {
private var reactHost: ReactHost? = null
/**
* Util function to create a default [ReactHost] to be used in your application. This method is
* used by the New App template.
*
* @param context the Android [Context] to use for creating the [ReactHost]
* @param packageList the list of [ReactPackage]s to use for creating the [ReactHost]
* @param jsMainModulePath the path to your app's main module on Metro. Usually `index` or
* `index.<platform>`
* @param jsBundleAssetPath the path to the JS bundle relative to the assets directory. Will be
* composed in a `asset://...` URL
* @param jsBundleFilePath the path to the JS bundle on the filesystem. Will be composed in a
* `file://...` URL
* @param jsRuntimeFactory the JS engine to use for executing [ReactHost], default to Hermes.
* @param useDevSupport whether to enable dev support, default to ReactBuildConfig.DEBUG.
* @param cxxReactPackageProviders a list of cxxreactpackage providers (to register c++ turbo
* modules)
*
* TODO(T186951312): Should this be @UnstableReactNativeAPI?
*/
@OptIn(UnstableReactNativeAPI::class)
@JvmStatic
public fun getDefaultReactHost(
context: Context,
packageList: List<ReactPackage>,
jsMainModulePath: String = "index",
jsBundleAssetPath: String = "index",
jsBundleFilePath: String? = null,
jsRuntimeFactory: JSRuntimeFactory? = null,
useDevSupport: Boolean = ReactBuildConfig.DEBUG,
cxxReactPackageProviders: List<(ReactContext) -> CxxReactPackage> = emptyList(),
): ReactHost =
getDefaultReactHost(
context,
packageList,
jsMainModulePath,
jsBundleAssetPath,
jsBundleFilePath,
jsRuntimeFactory,
useDevSupport,
cxxReactPackageProviders,
{ throw it },
null,
)
/**
* Util function to create a default [ReactHost] to be used in your application. This method is
* used by the New App template.
@@ -154,129 +110,6 @@ public object DefaultReactHost {
return reactHost as ReactHost
}
/**
* Util function to create a default [ReactHost] to be used in your application. This method is
* used by the New App template.
*
* @param context the Android [Context] to use for creating the [ReactHost]
* @param packageList the list of [ReactPackage]s to use for creating the [ReactHost]
* @param jsMainModulePath the path to your app's main module on Metro. Usually `index` or
* `index.<platform>`
* @param jsBundleAssetPath the path to the JS bundle relative to the assets directory. Will be
* composed in a `asset://...` URL
* @param jsBundleFilePath the path to the JS bundle on the filesystem. Will be composed in a
* `file://...` URL
* @param isHermesEnabled whether to use Hermes as the JS engine, default to true.
* @param useDevSupport whether to enable dev support, default to ReactBuildConfig.DEBUG.
* @param cxxReactPackageProviders a list of cxxreactpackage providers (to register c++ turbo
* modules)
* @param exceptionHandler Callback that can be used by React Native host applications to react to
* exceptions thrown by the internals of React Native.
* @param bindingsInstaller that can be used for installing bindings.
*/
@Deprecated(
message = "Use `getDefaultReactHost` with `jsRuntimeFactory` instead",
replaceWith =
ReplaceWith(
"""
fun getDefaultReactHost(
context: Context,
packageList: List<ReactPackage>,
jsMainModulePath: String,
jsBundleAssetPath: String,
jsBundleFilePath: String?,
jsRuntimeFactory: JSRuntimeFactory?,
useDevSupport: Boolean,
cxxReactPackageProviders: List<(ReactContext) -> CxxReactPackage>,
exceptionHandler: (Exception) -> Unit,
bindingsInstaller: BindingsInstaller?,
): ReactHost
"""
),
)
@JvmStatic
public fun getDefaultReactHost(
context: Context,
packageList: List<ReactPackage>,
jsMainModulePath: String = "index",
jsBundleAssetPath: String = "index",
jsBundleFilePath: String? = null,
isHermesEnabled: Boolean = true,
useDevSupport: Boolean = ReactBuildConfig.DEBUG,
cxxReactPackageProviders: List<(ReactContext) -> CxxReactPackage> = emptyList(),
exceptionHandler: (Exception) -> Unit = { throw it },
bindingsInstaller: BindingsInstaller? = null,
): ReactHost =
getDefaultReactHost(
context,
packageList,
jsMainModulePath,
jsBundleAssetPath,
jsBundleFilePath,
HermesInstance(),
useDevSupport,
cxxReactPackageProviders,
exceptionHandler,
bindingsInstaller,
)
/**
* Util function to create a default [ReactHost] to be used in your application. This method is
* used by the New App template.
*
* @param context the Android [Context] to use for creating the [ReactHost]
* @param packageList the list of [ReactPackage]s to use for creating the [ReactHost]
* @param jsMainModulePath the path to your app's main module on Metro. Usually `index` or
* `index.<platform>`
* @param jsBundleAssetPath the path to the JS bundle relative to the assets directory. Will be
* composed in a `asset://...` URL
* @param jsBundleFilePath the path to the JS bundle on the filesystem. Will be composed in a
* `file://...` URL
* @param isHermesEnabled whether to use Hermes as the JS engine, default to true.
* @param useDevSupport whether to enable dev support, default to ReactBuildConfig.DEBUG.
* @param cxxReactPackageProviders a list of cxxreactpackage providers (to register c++ turbo
* modules)
*/
@Deprecated(
message = "Use `getDefaultReactHost` with `jsRuntimeFactory` instead",
replaceWith =
ReplaceWith(
"""
fun getDefaultReactHost(
context: Context,
packageList: List<ReactPackage>,
jsMainModulePath: String,
jsBundleAssetPath: String,
jsBundleFilePath: String?,
jsRuntimeFactory: JSRuntimeFactory?,
useDevSupport: Boolean,
cxxReactPackageProviders: List<(ReactContext) -> CxxReactPackage>,
): ReactHost
"""
),
)
@JvmStatic
public fun getDefaultReactHost(
context: Context,
packageList: List<ReactPackage>,
jsMainModulePath: String = "index",
jsBundleAssetPath: String = "index",
jsBundleFilePath: String? = null,
isHermesEnabled: Boolean = true,
useDevSupport: Boolean = ReactBuildConfig.DEBUG,
cxxReactPackageProviders: List<(ReactContext) -> CxxReactPackage> = emptyList(),
): ReactHost =
getDefaultReactHost(
context,
packageList,
jsMainModulePath,
jsBundleAssetPath,
jsBundleFilePath,
HermesInstance(),
useDevSupport,
cxxReactPackageProviders,
)
/**
* Util function to create a default [ReactHost] to be used in your application. This method is
* used by the New App template.
@@ -927,7 +927,7 @@ public abstract class DevSupportManagerBase(
devServerHelper.openDebugger(
currentReactContext,
applicationContext.getString(R.string.catalyst_open_debugger_error),
ChromeDevToolsViewKeys.Performance.value,
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<<f162c19a6742ecadd171500ccb918f4b>>
* @generated SignedSource<<34c12f5a31aab5bfb874953f1beefef1>>
*/
/**
@@ -258,6 +258,12 @@ public object ReactNativeFeatureFlags {
@JvmStatic
public fun enableViewRecycling(): Boolean = accessor.enableViewRecycling()
/**
* Enables View Recycling for <ScrollView> via ReactViewGroup/ReactViewManager.
*/
@JvmStatic
public fun enableViewRecyclingForScrollView(): Boolean = accessor.enableViewRecyclingForScrollView()
/**
* Enables View Recycling for <Text> via ReactTextView/ReactTextViewManager.
*/
@@ -426,6 +432,12 @@ public object ReactNativeFeatureFlags {
@JvmStatic
public fun useTurboModules(): Boolean = accessor.useTurboModules()
/**
* Sets a hysteresis window for transition between prerender and hidden modes.
*/
@JvmStatic
public fun virtualViewHysteresisRatio(): Double = accessor.virtualViewHysteresisRatio()
/**
* Initial prerender ratio for VirtualView.
*/
@@ -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<<51bb91fd70ba266c01bf46b3ca237ad5>>
* @generated SignedSource<<392da016e0bf4193b72c44a508811e10>>
*/
/**
@@ -58,6 +58,7 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
private var enableResourceTimingAPICache: Boolean? = null
private var enableViewCullingCache: Boolean? = null
private var enableViewRecyclingCache: Boolean? = null
private var enableViewRecyclingForScrollViewCache: Boolean? = null
private var enableViewRecyclingForTextCache: Boolean? = null
private var enableViewRecyclingForViewCache: Boolean? = null
private var enableVirtualViewDebugFeaturesCache: Boolean? = null
@@ -86,6 +87,7 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
private var useShadowNodeStateOnCloneCache: Boolean? = null
private var useTurboModuleInteropCache: Boolean? = null
private var useTurboModulesCache: Boolean? = null
private var virtualViewHysteresisRatioCache: Double? = null
private var virtualViewPrerenderRatioCache: Double? = null
override fun commonTestFlag(): Boolean {
@@ -430,6 +432,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
return cached
}
override fun enableViewRecyclingForScrollView(): Boolean {
var cached = enableViewRecyclingForScrollViewCache
if (cached == null) {
cached = ReactNativeFeatureFlagsCxxInterop.enableViewRecyclingForScrollView()
enableViewRecyclingForScrollViewCache = cached
}
return cached
}
override fun enableViewRecyclingForText(): Boolean {
var cached = enableViewRecyclingForTextCache
if (cached == null) {
@@ -682,6 +693,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
return cached
}
override fun virtualViewHysteresisRatio(): Double {
var cached = virtualViewHysteresisRatioCache
if (cached == null) {
cached = ReactNativeFeatureFlagsCxxInterop.virtualViewHysteresisRatio()
virtualViewHysteresisRatioCache = cached
}
return cached
}
override fun virtualViewPrerenderRatio(): Double {
var cached = virtualViewPrerenderRatioCache
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<<d4a1d4510264580e2f1436b05f1c2f0e>>
* @generated SignedSource<<a0453230524ebca2bfb8fad656a6f54a>>
*/
/**
@@ -104,6 +104,8 @@ public object ReactNativeFeatureFlagsCxxInterop {
@DoNotStrip @JvmStatic public external fun enableViewRecycling(): Boolean
@DoNotStrip @JvmStatic public external fun enableViewRecyclingForScrollView(): Boolean
@DoNotStrip @JvmStatic public external fun enableViewRecyclingForText(): Boolean
@DoNotStrip @JvmStatic public external fun enableViewRecyclingForView(): Boolean
@@ -160,6 +162,8 @@ public object ReactNativeFeatureFlagsCxxInterop {
@DoNotStrip @JvmStatic public external fun useTurboModules(): Boolean
@DoNotStrip @JvmStatic public external fun virtualViewHysteresisRatio(): Double
@DoNotStrip @JvmStatic public external fun virtualViewPrerenderRatio(): Double
@DoNotStrip @JvmStatic public external fun override(provider: Any)
@@ -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<<4cc61b5f71805589fa91abbdefb5eade>>
* @generated SignedSource<<719706a983a073b6c286c49d993f7f80>>
*/
/**
@@ -99,6 +99,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
override fun enableViewRecycling(): Boolean = false
override fun enableViewRecyclingForScrollView(): Boolean = false
override fun enableViewRecyclingForText(): Boolean = true
override fun enableViewRecyclingForView(): Boolean = true
@@ -139,15 +141,15 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
override fun useFabricInterop(): Boolean = true
override fun useNativeEqualsInNativeReadableArrayAndroid(): Boolean = false
override fun useNativeEqualsInNativeReadableArrayAndroid(): Boolean = true
override fun useNativeTransformHelperAndroid(): Boolean = false
override fun useNativeTransformHelperAndroid(): Boolean = true
override fun useNativeViewConfigsInBridgelessMode(): Boolean = false
override fun useOptimizedEventBatchingOnAndroid(): Boolean = false
override fun useRawPropsJsiValue(): Boolean = false
override fun useRawPropsJsiValue(): Boolean = true
override fun useShadowNodeStateOnClone(): Boolean = false
@@ -155,5 +157,7 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
override fun useTurboModules(): Boolean = false
override fun virtualViewHysteresisRatio(): Double = 0.0
override fun virtualViewPrerenderRatio(): Double = 5.0
}
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<78c9ee8f53273560de6b75719e317273>>
* @generated SignedSource<<594815ba6a984c460ab8bddd91c5cae2>>
*/
/**
@@ -62,6 +62,7 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
private var enableResourceTimingAPICache: Boolean? = null
private var enableViewCullingCache: Boolean? = null
private var enableViewRecyclingCache: Boolean? = null
private var enableViewRecyclingForScrollViewCache: Boolean? = null
private var enableViewRecyclingForTextCache: Boolean? = null
private var enableViewRecyclingForViewCache: Boolean? = null
private var enableVirtualViewDebugFeaturesCache: Boolean? = null
@@ -90,6 +91,7 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
private var useShadowNodeStateOnCloneCache: Boolean? = null
private var useTurboModuleInteropCache: Boolean? = null
private var useTurboModulesCache: Boolean? = null
private var virtualViewHysteresisRatioCache: Double? = null
private var virtualViewPrerenderRatioCache: Double? = null
override fun commonTestFlag(): Boolean {
@@ -472,6 +474,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
return cached
}
override fun enableViewRecyclingForScrollView(): Boolean {
var cached = enableViewRecyclingForScrollViewCache
if (cached == null) {
cached = currentProvider.enableViewRecyclingForScrollView()
accessedFeatureFlags.add("enableViewRecyclingForScrollView")
enableViewRecyclingForScrollViewCache = cached
}
return cached
}
override fun enableViewRecyclingForText(): Boolean {
var cached = enableViewRecyclingForTextCache
if (cached == null) {
@@ -752,6 +764,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
return cached
}
override fun virtualViewHysteresisRatio(): Double {
var cached = virtualViewHysteresisRatioCache
if (cached == null) {
cached = currentProvider.virtualViewHysteresisRatio()
accessedFeatureFlags.add("virtualViewHysteresisRatio")
virtualViewHysteresisRatioCache = cached
}
return cached
}
override fun virtualViewPrerenderRatio(): Double {
var cached = virtualViewPrerenderRatioCache
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<<1f89971ab4d5b2ee27ace3a3c8da78cf>>
* @generated SignedSource<<4feeb3c1789d8169dd93bee7ae1ff1ac>>
*/
/**
@@ -26,8 +26,4 @@ public open class ReactNativeFeatureFlagsOverrides_RNOSS_Experimental_Android :
override fun enableAccessibilityOrder(): Boolean = true
override fun preventShadowTreeCommitExhaustion(): Boolean = true
override fun useNativeEqualsInNativeReadableArrayAndroid(): Boolean = true
override fun useNativeTransformHelperAndroid(): Boolean = true
}
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<3db9f160e7221eb9c7660a3e93da0f40>>
* @generated SignedSource<<dfbd5e84392f1fda0e68324582c328b2>>
*/
/**
@@ -99,6 +99,8 @@ public interface ReactNativeFeatureFlagsProvider {
@DoNotStrip public fun enableViewRecycling(): Boolean
@DoNotStrip public fun enableViewRecyclingForScrollView(): Boolean
@DoNotStrip public fun enableViewRecyclingForText(): Boolean
@DoNotStrip public fun enableViewRecyclingForView(): Boolean
@@ -155,5 +157,7 @@ public interface ReactNativeFeatureFlagsProvider {
@DoNotStrip public fun useTurboModules(): Boolean
@DoNotStrip public fun virtualViewHysteresisRatio(): Double
@DoNotStrip public fun virtualViewPrerenderRatio(): Double
}
@@ -34,6 +34,12 @@ internal class ReactHostInspectorTarget(reactHostImpl: ReactHostImpl) :
external fun sendDebuggerResumeCommand()
external fun startBackgroundTrace(): Boolean
external fun stopAndStashBackgroundTrace()
external fun stopAndDiscardBackgroundTrace()
override fun addPerfMonitorListener(listener: PerfMonitorUpdateListener) {
perfMonitorListeners.add(listener)
}
@@ -52,7 +52,6 @@ import com.facebook.react.uimanager.events.RCTEventEmitter;
import com.facebook.react.uimanager.internal.LegacyArchitectureShadowNodeLogger;
import com.facebook.systrace.Systrace;
import com.facebook.systrace.SystraceMessage;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -117,7 +116,6 @@ public class UIManagerModule extends ReactContextBaseJavaModule
private final ViewManagerRegistry mViewManagerRegistry;
private final UIImplementation mUIImplementation;
private final MemoryTrimCallback mMemoryTrimCallback = new MemoryTrimCallback();
private final List<UIManagerModuleListener> mListeners = new ArrayList<>();
private final CopyOnWriteArrayList<UIManagerListener> mUIManagerListeners =
new CopyOnWriteArrayList<>();
@@ -687,9 +685,6 @@ public class UIManagerModule extends ReactContextBaseJavaModule
SystraceMessage.beginSection(Systrace.TRACE_TAG_REACT, "onBatchCompleteUI")
.arg("BatchId", batchId)
.flush();
for (UIManagerModuleListener listener : mListeners) {
listener.willDispatchViewUpdates(this);
}
for (UIManagerListener listener : mUIManagerListeners) {
listener.willDispatchViewUpdates(this);
}
@@ -757,16 +752,6 @@ public class UIManagerModule extends ReactContextBaseJavaModule
mUIImplementation.prependUIBlock(block);
}
@Deprecated
public void addUIManagerListener(UIManagerModuleListener listener) {
mListeners.add(listener);
}
@Deprecated
public void removeUIManagerListener(UIManagerModuleListener listener) {
mListeners.remove(listener);
}
public void addUIManagerEventListener(UIManagerListener listener) {
mUIManagerListeners.add(listener);
}
@@ -1,24 +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
import com.facebook.react.common.annotations.internal.LegacyArchitecture
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel
/** Listener used to hook into the UIManager update process. */
@Deprecated("Use UIManagerListener instead. This will be deleted in some future release.")
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
internal interface UIManagerModuleListener {
/**
* Called right before view updates are dispatched at the end of a batch. This is useful if a
* module needs to add UIBlocks to the queue before it is flushed.
*/
fun willDispatchViewUpdates(uiManager: UIManagerModule)
}
@@ -54,7 +54,7 @@ public abstract class ViewManager<T extends View, C extends ReactShadowNode>
* null signals that View Recycling is disabled. `enableViewRecycling` must be explicitly called
* in a concrete constructor to enable View Recycling per ViewManager.
*/
@Nullable private HashMap<Integer, Stack<T>> mRecyclableViews = null;
@Nullable private Map<Integer, Stack<T>> mRecyclableViews = null;
public ViewManager() {
super(null);
@@ -96,8 +96,10 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
private final OnScrollDispatchHelper mOnScrollDispatchHelper = new OnScrollDispatchHelper();
private final @Nullable OverScroller mScroller;
private final VelocityHelper mVelocityHelper = new VelocityHelper();
private final Rect mOverflowInset = new Rect();
private final Rect mTempRect = new Rect();
private final ValueAnimator DEFAULT_FLING_ANIMATOR = ObjectAnimator.ofInt(this, "scrollX", 0, 0);
private Rect mOverflowInset = new Rect();
private boolean mActivelyScrolling;
private @Nullable Rect mClippingRect;
private Overflow mOverflow = Overflow.SCROLL;
@@ -118,11 +120,10 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
private boolean mSnapToEnd = true;
private int mSnapToAlignment = SNAP_ALIGNMENT_DISABLED;
private boolean mPagedArrowScrolling = false;
private int pendingContentOffsetX = UNSET_CONTENT_OFFSET;
private int pendingContentOffsetY = UNSET_CONTENT_OFFSET;
private int mPendingContentOffsetX = UNSET_CONTENT_OFFSET;
private int mPendingContentOffsetY = UNSET_CONTENT_OFFSET;
private @Nullable StateWrapper mStateWrapper = null;
private final ReactScrollViewScrollState mReactScrollViewScrollState;
private final ValueAnimator DEFAULT_FLING_ANIMATOR = ObjectAnimator.ofInt(this, "scrollX", 0, 0);
private ReactScrollViewScrollState mReactScrollViewScrollState;
private PointerEvents mPointerEvents = PointerEvents.AUTO;
private long mLastScrollDispatchTime = 0;
private int mScrollEventThrottle = 0;
@@ -131,8 +132,6 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
private int mFadingEdgeLengthStart = 0;
private int mFadingEdgeLengthEnd = 0;
private final Rect mTempRect = new Rect();
public ReactHorizontalScrollView(Context context) {
this(context, null);
}
@@ -144,12 +143,67 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
ViewCompat.setAccessibilityDelegate(this, new ReactScrollViewAccessibilityDelegate());
mScroller = getOverScrollerFromParent();
mReactScrollViewScrollState = new ReactScrollViewScrollState();
setOnHierarchyChangeListener(this);
setClipChildren(false);
initView();
}
/**
* Set all default values here as opposed to in the constructor or field defaults. It is important
* that these properties are set during the constructor, but also on-demand whenever an existing
* ReactTextView is recycled.
*/
private void initView() {
mOverflowInset = new Rect();
mActivelyScrolling = false;
mClippingRect = null;
mOverflow = Overflow.SCROLL;
mDragging = false;
mPagingEnabled = false;
mPostTouchRunnable = null;
mRemoveClippedSubviews = false;
mScrollEnabled = true;
mSendMomentumEvents = false;
mFpsListener = null;
mScrollPerfTag = null;
mEndBackground = null;
mEndFillColor = Color.TRANSPARENT;
mDisableIntervalMomentum = false;
mSnapInterval = 0;
mSnapOffsets = null;
mSnapToStart = true;
mSnapToEnd = true;
mSnapToAlignment = SNAP_ALIGNMENT_DISABLED;
mPagedArrowScrolling = false;
mPendingContentOffsetX = UNSET_CONTENT_OFFSET;
mPendingContentOffsetY = UNSET_CONTENT_OFFSET;
mStateWrapper = null;
mReactScrollViewScrollState = new ReactScrollViewScrollState();
mPointerEvents = PointerEvents.AUTO;
mLastScrollDispatchTime = 0;
mScrollEventThrottle = 0;
mContentView = null;
mMaintainVisibleContentPositionHelper = null;
mFadingEdgeLengthStart = 0;
mFadingEdgeLengthEnd = 0;
}
/* package */ void recycleView() {
// Set default field values
initView();
// If the view is still attached to a parent, we need to remove it from the parent
// before we can recycle it.
if (getParent() != null) {
((ViewGroup) getParent()).removeView(this);
}
updateView();
}
private void updateView() {}
@Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
@@ -441,9 +495,9 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
// If a "pending" content offset value has been set, we restore that value.
// Upon call to scrollTo, the "pending" values will be re-set.
int scrollToX =
pendingContentOffsetX != UNSET_CONTENT_OFFSET ? pendingContentOffsetX : getScrollX();
mPendingContentOffsetX != UNSET_CONTENT_OFFSET ? mPendingContentOffsetX : getScrollX();
int scrollToY =
pendingContentOffsetY != UNSET_CONTENT_OFFSET ? pendingContentOffsetY : getScrollY();
mPendingContentOffsetY != UNSET_CONTENT_OFFSET ? mPendingContentOffsetY : getScrollY();
scrollTo(scrollToX, scrollToY);
}
@@ -1459,11 +1513,11 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
}
if (isContentReady()) {
pendingContentOffsetX = UNSET_CONTENT_OFFSET;
pendingContentOffsetY = UNSET_CONTENT_OFFSET;
mPendingContentOffsetX = UNSET_CONTENT_OFFSET;
mPendingContentOffsetY = UNSET_CONTENT_OFFSET;
} else {
pendingContentOffsetX = x;
pendingContentOffsetY = y;
mPendingContentOffsetX = x;
mPendingContentOffsetY = y;
}
}
@@ -14,6 +14,7 @@ import com.facebook.react.bridge.ReadableArray
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.bridge.ReadableType
import com.facebook.react.bridge.RetryableMountingLayerException
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags
import com.facebook.react.module.annotations.ReactModule
import com.facebook.react.uimanager.BackgroundStyleApplicator.setBorderColor
import com.facebook.react.uimanager.BackgroundStyleApplicator.setBorderRadius
@@ -55,6 +56,23 @@ public open class ReactHorizontalScrollViewManager
@JvmOverloads
constructor(private val fpsListener: FpsListener? = null) :
ViewGroupManager<ReactHorizontalScrollView>(), ScrollCommandHandler<ReactHorizontalScrollView> {
init {
if (ReactNativeFeatureFlags.enableViewRecyclingForScrollView()) {
setupViewRecycling()
}
}
override fun prepareToRecycleView(
reactContext: ThemedReactContext,
view: ReactHorizontalScrollView,
): ReactHorizontalScrollView? {
// BaseViewManager
val preparedView = super.prepareToRecycleView(reactContext, view)
if (preparedView != null) {
preparedView.recycleView()
}
return preparedView
}
override fun getName(): String = REACT_CLASS
@@ -96,43 +96,41 @@ public class ReactScrollView extends ScrollView
private final @Nullable OverScroller mScroller;
private final VelocityHelper mVelocityHelper = new VelocityHelper();
private final Rect mTempRect = new Rect();
private final Rect mOverflowInset = new Rect();
private final ValueAnimator DEFAULT_FLING_ANIMATOR = ObjectAnimator.ofInt(this, "scrollY", 0, 0);
private Rect mOverflowInset;
private @Nullable VirtualViewContainerState mVirtualViewContainerState;
private boolean mActivelyScrolling;
private @Nullable Rect mClippingRect;
private Overflow mOverflow = Overflow.SCROLL;
private Overflow mOverflow;
private boolean mDragging;
private boolean mPagingEnabled = false;
private boolean mPagingEnabled;
private @Nullable Runnable mPostTouchRunnable;
private boolean mRemoveClippedSubviews;
private boolean mScrollEnabled = true;
private boolean mScrollEnabled;
private boolean mSendMomentumEvents;
private @Nullable FpsListener mFpsListener = null;
private @Nullable FpsListener mFpsListener;
private @Nullable String mScrollPerfTag;
private @Nullable Drawable mEndBackground;
private int mEndFillColor = Color.TRANSPARENT;
private boolean mDisableIntervalMomentum = false;
private int mSnapInterval = 0;
private int mEndFillColor;
private boolean mDisableIntervalMomentum;
private int mSnapInterval;
private @Nullable List<Integer> mSnapOffsets;
private boolean mSnapToStart = true;
private boolean mSnapToEnd = true;
private int mSnapToAlignment = SNAP_ALIGNMENT_DISABLED;
private boolean mSnapToStart;
private boolean mSnapToEnd;
private int mSnapToAlignment;
private @Nullable View mContentView;
private @Nullable ReadableMap mCurrentContentOffset = null;
private int pendingContentOffsetX = UNSET_CONTENT_OFFSET;
private int pendingContentOffsetY = UNSET_CONTENT_OFFSET;
private @Nullable StateWrapper mStateWrapper = null;
private final ReactScrollViewScrollState mReactScrollViewScrollState =
new ReactScrollViewScrollState();
private final ValueAnimator DEFAULT_FLING_ANIMATOR = ObjectAnimator.ofInt(this, "scrollY", 0, 0);
private PointerEvents mPointerEvents = PointerEvents.AUTO;
private long mLastScrollDispatchTime = 0;
private int mScrollEventThrottle = 0;
private @Nullable MaintainVisibleScrollPositionHelper mMaintainVisibleContentPositionHelper =
null;
private int mFadingEdgeLengthStart = 0;
private int mFadingEdgeLengthEnd = 0;
private @Nullable ReadableMap mCurrentContentOffset;
private int mPendingContentOffsetX;
private int mPendingContentOffsetY;
private @Nullable StateWrapper mStateWrapper;
private ReactScrollViewScrollState mReactScrollViewScrollState;
private PointerEvents mPointerEvents;
private long mLastScrollDispatchTime;
private int mScrollEventThrottle;
private @Nullable MaintainVisibleScrollPositionHelper mMaintainVisibleContentPositionHelper;
private int mFadingEdgeLengthStart;
private int mFadingEdgeLengthEnd;
public ReactScrollView(Context context) {
this(context, null);
@@ -148,8 +146,64 @@ public class ReactScrollView extends ScrollView
setClipChildren(false);
ViewCompat.setAccessibilityDelegate(this, new ReactScrollViewAccessibilityDelegate());
initView();
}
/**
* Set all default values here as opposed to in the constructor or field defaults. It is important
* that these properties are set during the constructor, but also on-demand whenever an existing
* ReactTextView is recycled.
*/
private void initView() {
mOverflowInset = new Rect();
mVirtualViewContainerState = null;
mActivelyScrolling = false;
mClippingRect = null;
mOverflow = Overflow.SCROLL;
mDragging = false;
mPagingEnabled = false;
mPostTouchRunnable = null;
mRemoveClippedSubviews = false;
mScrollEnabled = true;
mSendMomentumEvents = false;
mFpsListener = null;
mScrollPerfTag = null;
mEndBackground = null;
mEndFillColor = Color.TRANSPARENT;
mDisableIntervalMomentum = false;
mSnapInterval = 0;
mSnapOffsets = null;
mSnapToStart = true;
mSnapToEnd = true;
mSnapToAlignment = SNAP_ALIGNMENT_DISABLED;
mContentView = null;
mCurrentContentOffset = null;
mPendingContentOffsetX = UNSET_CONTENT_OFFSET;
mPendingContentOffsetY = UNSET_CONTENT_OFFSET;
mStateWrapper = null;
mReactScrollViewScrollState = new ReactScrollViewScrollState();
mPointerEvents = PointerEvents.AUTO;
mLastScrollDispatchTime = 0;
mScrollEventThrottle = 0;
mMaintainVisibleContentPositionHelper = null;
mFadingEdgeLengthStart = 0;
mFadingEdgeLengthEnd = 0;
}
/* package */ void recycleView() {
// Set default field values
initView();
// If the view is still attached to a parent, we need to remove it from the parent
// before we can recycle it.
if (getParent() != null) {
((ViewGroup) getParent()).removeView(this);
}
updateView();
}
private void updateView() {}
@Override
public VirtualViewContainerState getVirtualViewContainerState() {
if (mVirtualViewContainerState == null) {
@@ -368,9 +422,9 @@ public class ReactScrollView extends ScrollView
// If a "pending" content offset value has been set, we restore that value.
// Upon call to scrollTo, the "pending" values will be re-set.
int scrollToX =
pendingContentOffsetX != UNSET_CONTENT_OFFSET ? pendingContentOffsetX : getScrollX();
mPendingContentOffsetX != UNSET_CONTENT_OFFSET ? mPendingContentOffsetX : getScrollX();
int scrollToY =
pendingContentOffsetY != UNSET_CONTENT_OFFSET ? pendingContentOffsetY : getScrollY();
mPendingContentOffsetY != UNSET_CONTENT_OFFSET ? mPendingContentOffsetY : getScrollY();
scrollTo(scrollToX, scrollToY);
}
@@ -1269,11 +1323,11 @@ public class ReactScrollView extends ScrollView
*/
private void setPendingContentOffsets(int x, int y) {
if (isContentReady()) {
pendingContentOffsetX = UNSET_CONTENT_OFFSET;
pendingContentOffsetY = UNSET_CONTENT_OFFSET;
mPendingContentOffsetX = UNSET_CONTENT_OFFSET;
mPendingContentOffsetY = UNSET_CONTENT_OFFSET;
} else {
pendingContentOffsetX = x;
pendingContentOffsetY = y;
mPendingContentOffsetX = x;
mPendingContentOffsetY = y;
}
}
@@ -15,6 +15,7 @@ import com.facebook.react.bridge.ReadableArray
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.bridge.ReadableType
import com.facebook.react.bridge.RetryableMountingLayerException
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags
import com.facebook.react.module.annotations.ReactModule
import com.facebook.react.uimanager.BackgroundStyleApplicator.setBorderColor
import com.facebook.react.uimanager.BackgroundStyleApplicator.setBorderRadius
@@ -56,6 +57,24 @@ public open class ReactScrollViewManager
constructor(private val fpsListener: FpsListener? = null) :
ViewGroupManager<ReactScrollView>(), ScrollCommandHandler<ReactScrollView> {
init {
if (ReactNativeFeatureFlags.enableViewRecyclingForScrollView()) {
setupViewRecycling()
}
}
override fun prepareToRecycleView(
reactContext: ThemedReactContext,
view: ReactScrollView,
): ReactScrollView? {
// BaseViewManager
val preparedView = super.prepareToRecycleView(reactContext, view)
if (preparedView != null) {
preparedView.recycleView()
}
return preparedView
}
override fun getName(): String = REACT_CLASS
public override fun createViewInstance(context: ThemedReactContext): ReactScrollView =
@@ -41,6 +41,7 @@ public class ReactVirtualView(context: Context) :
internal var modeChangeEmitter: VirtualViewModeChangeEmitter? = null
internal var prerenderRatio: Double = ReactNativeFeatureFlags.virtualViewPrerenderRatio()
internal val debugLogEnabled: Boolean = ReactNativeFeatureFlags.enableVirtualViewDebugFeatures()
private val hysteresisRatio: Double = ReactNativeFeatureFlags.virtualViewHysteresisRatio()
private val onWindowFocusChangeListener =
if (ReactNativeFeatureFlags.enableVirtualViewWindowFocusDetection()) {
@@ -188,7 +189,7 @@ public class ReactVirtualView(context: Context) :
// If no ScrollView, or ScrollView has disabled removeClippedSubviews, use default behavior
if (
parentScrollView == null ||
!((parentScrollView as ReactClippingViewGroup)?.removeClippedSubviews ?: false)
!((parentScrollView as ReactClippingViewGroup).removeClippedSubviews ?: false)
) {
super.updateClippingRect(excludedViews)
return
@@ -222,6 +223,8 @@ public class ReactVirtualView(context: Context) :
bottom + offsetY,
)
scrollView.getDrawingRect(thresholdRect)
val visibleHeight = thresholdRect.height()
val visibleWidth = thresholdRect.width()
// TODO: Validate whether this is still the case and whether these checks are still needed.
// updateRects will initially get called before the targetRect has any dimensions set, so if
@@ -260,16 +263,32 @@ public class ReactVirtualView(context: Context) :
var prerender = false
if (prerenderRatio > 0.0) {
thresholdRect.inset(
(-thresholdRect.width() * prerenderRatio).toInt(),
(-thresholdRect.height() * prerenderRatio).toInt(),
(-visibleWidth * prerenderRatio).toInt(),
(-visibleHeight * prerenderRatio).toInt(),
)
prerender = rectsOverlap(targetRect, thresholdRect)
}
if (prerender) {
newMode = VirtualViewMode.Prerender
} else {
newMode = VirtualViewMode.Hidden
thresholdRect.setEmpty()
val _mode = mode // local variable so Kotlin knows its not nullable
if (_mode != null && hysteresisRatio > 0.0) {
thresholdRect.inset(
(-visibleWidth * hysteresisRatio).toInt(),
(-visibleHeight * hysteresisRatio).toInt(),
)
if (rectsOverlap(targetRect, thresholdRect)) {
// In hysteresis window, no change to mode
newMode = _mode
debugLog("dispatchOnModeChangeIfNeeded") { "hysteresis, mode=$newMode" }
} else {
newMode = VirtualViewMode.Hidden
thresholdRect.setEmpty()
}
} else {
newMode = VirtualViewMode.Hidden
thresholdRect.setEmpty()
}
}
}
debugLog("dispatchOnModeChangeIfNeeded") {
@@ -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<<0dadaee3f6bd74cc13295b8683e8e470>>
* @generated SignedSource<<16b12024bb363358ef09b9a42cb2fc97>>
*/
/**
@@ -267,6 +267,12 @@ class ReactNativeFeatureFlagsJavaProvider
return method(javaProvider_);
}
bool enableViewRecyclingForScrollView() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableViewRecyclingForScrollView");
return method(javaProvider_);
}
bool enableViewRecyclingForText() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableViewRecyclingForText");
@@ -435,6 +441,12 @@ class ReactNativeFeatureFlagsJavaProvider
return method(javaProvider_);
}
double virtualViewHysteresisRatio() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jdouble()>("virtualViewHysteresisRatio");
return method(javaProvider_);
}
double virtualViewPrerenderRatio() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jdouble()>("virtualViewPrerenderRatio");
@@ -635,6 +647,11 @@ bool JReactNativeFeatureFlagsCxxInterop::enableViewRecycling(
return ReactNativeFeatureFlags::enableViewRecycling();
}
bool JReactNativeFeatureFlagsCxxInterop::enableViewRecyclingForScrollView(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::enableViewRecyclingForScrollView();
}
bool JReactNativeFeatureFlagsCxxInterop::enableViewRecyclingForText(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::enableViewRecyclingForText();
@@ -775,6 +792,11 @@ bool JReactNativeFeatureFlagsCxxInterop::useTurboModules(
return ReactNativeFeatureFlags::useTurboModules();
}
double JReactNativeFeatureFlagsCxxInterop::virtualViewHysteresisRatio(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::virtualViewHysteresisRatio();
}
double JReactNativeFeatureFlagsCxxInterop::virtualViewPrerenderRatio(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::virtualViewPrerenderRatio();
@@ -925,6 +947,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
makeNativeMethod(
"enableViewRecycling",
JReactNativeFeatureFlagsCxxInterop::enableViewRecycling),
makeNativeMethod(
"enableViewRecyclingForScrollView",
JReactNativeFeatureFlagsCxxInterop::enableViewRecyclingForScrollView),
makeNativeMethod(
"enableViewRecyclingForText",
JReactNativeFeatureFlagsCxxInterop::enableViewRecyclingForText),
@@ -1009,6 +1034,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
makeNativeMethod(
"useTurboModules",
JReactNativeFeatureFlagsCxxInterop::useTurboModules),
makeNativeMethod(
"virtualViewHysteresisRatio",
JReactNativeFeatureFlagsCxxInterop::virtualViewHysteresisRatio),
makeNativeMethod(
"virtualViewPrerenderRatio",
JReactNativeFeatureFlagsCxxInterop::virtualViewPrerenderRatio),
@@ -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<<74ac256afe63253ddb6576285858444c>>
* @generated SignedSource<<54118ccd475a8bf1d7db83304b1f17d0>>
*/
/**
@@ -144,6 +144,9 @@ class JReactNativeFeatureFlagsCxxInterop
static bool enableViewRecycling(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static bool enableViewRecyclingForScrollView(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static bool enableViewRecyclingForText(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
@@ -228,6 +231,9 @@ class JReactNativeFeatureFlagsCxxInterop
static bool useTurboModules(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static double virtualViewHysteresisRatio(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static double virtualViewPrerenderRatio(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
@@ -54,7 +54,6 @@ add_library(
CatalystInstanceImpl.cpp
InspectorNetworkRequestListener.cpp
JExecutor.cpp
JInspector.cpp
JMessageQueueThread.cpp
JReactCxxErrorHandler.cpp
JReactSoftExceptionLogger.cpp
@@ -1,112 +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.
*/
#include "JInspector.h"
#include <memory>
namespace facebook::react {
namespace {
class RemoteConnection : public jsinspector_modern::IRemoteConnection {
public:
RemoteConnection(jni::alias_ref<JRemoteConnection::javaobject> connection)
: connection_(jni::make_global(connection)) {}
void onMessage(std::string message) override {
connection_->onMessage(message);
}
void onDisconnect() override {
connection_->onDisconnect();
}
private:
jni::global_ref<JRemoteConnection::javaobject> connection_;
};
} // namespace
jni::local_ref<JPage::javaobject>
JPage::create(int id, const std::string& title, const std::string& vm) {
static auto constructor = javaClassStatic()
->getConstructor<JPage::javaobject(
jint,
jni::local_ref<jni::JString>,
jni::local_ref<jni::JString>)>();
return javaClassStatic()->newObject(
constructor, id, jni::make_jstring(title), jni::make_jstring(vm));
}
void JRemoteConnection::onMessage(const std::string& message) const {
static auto method =
javaClassStatic()->getMethod<void(jni::local_ref<jstring>)>("onMessage");
method(self(), jni::make_jstring(message));
}
void JRemoteConnection::onDisconnect() const {
static auto method = javaClassStatic()->getMethod<void()>("onDisconnect");
method(self());
}
JLocalConnection::JLocalConnection(
std::unique_ptr<jsinspector_modern::ILocalConnection> connection)
: connection_(std::move(connection)) {}
void JLocalConnection::sendMessage(std::string message) {
connection_->sendMessage(std::move(message));
}
void JLocalConnection::disconnect() {
connection_->disconnect();
}
void JLocalConnection::registerNatives() {
javaClassStatic()->registerNatives({
makeNativeMethod("sendMessage", JLocalConnection::sendMessage),
makeNativeMethod("disconnect", JLocalConnection::disconnect),
});
}
jni::global_ref<JInspector::javaobject> JInspector::instance(
jni::alias_ref<jclass> /*unused*/) {
static auto instance = jni::make_global(
newObjectCxxArgs(&jsinspector_modern::getInspectorInstance()));
return instance;
}
jni::local_ref<jni::JArrayClass<JPage::javaobject>> JInspector::getPages() {
std::vector<jsinspector_modern::InspectorPageDescription> pages =
inspector_->getPages();
auto array = jni::JArrayClass<JPage::javaobject>::newArray(pages.size());
for (size_t i = 0; i < pages.size(); i++) {
(*array)[i] = JPage::create(pages[i].id, pages[i].description, pages[i].vm);
}
return array;
}
jni::local_ref<JLocalConnection::javaobject> JInspector::connect(
int pageId,
jni::alias_ref<JRemoteConnection::javaobject> remote) {
auto localConnection = inspector_->connect(
pageId, std::make_unique<RemoteConnection>(std::move(remote)));
return localConnection
? JLocalConnection::newObjectCxxArgs(std::move(localConnection))
: nullptr;
}
void JInspector::registerNatives() {
JLocalConnection::registerNatives();
javaClassStatic()->registerNatives({
makeNativeMethod("instance", JInspector::instance),
makeNativeMethod("getPagesNative", JInspector::getPages),
makeNativeMethod("connectNative", JInspector::connect),
});
}
} // namespace facebook::react
@@ -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.
*/
#pragma once
#include <jsinspector-modern/InspectorInterfaces.h>
#include <fbjni/fbjni.h>
#include <memory>
namespace facebook::react {
class JPage : public jni::JavaClass<JPage> {
public:
static constexpr auto kJavaDescriptor =
"Lcom/facebook/react/bridge/Inspector$Page;";
static jni::local_ref<JPage::javaobject>
create(int id, const std::string& title, const std::string& vm);
};
class JRemoteConnection : public jni::JavaClass<JRemoteConnection> {
public:
static constexpr auto kJavaDescriptor =
"Lcom/facebook/react/bridge/Inspector$RemoteConnection;";
void onMessage(const std::string& message) const;
void onDisconnect() const;
};
class JLocalConnection : public jni::HybridClass<JLocalConnection> {
public:
static constexpr auto kJavaDescriptor =
"Lcom/facebook/react/bridge/Inspector$LocalConnection;";
JLocalConnection(
std::unique_ptr<jsinspector_modern::ILocalConnection> connection);
void sendMessage(std::string message);
void disconnect();
static void registerNatives();
private:
std::unique_ptr<jsinspector_modern::ILocalConnection> connection_;
};
class JInspector : public jni::HybridClass<JInspector> {
public:
static constexpr auto kJavaDescriptor =
"Lcom/facebook/react/bridge/Inspector;";
static jni::global_ref<JInspector::javaobject> instance(
jni::alias_ref<jclass>);
jni::local_ref<jni::JArrayClass<JPage::javaobject>> getPages();
jni::local_ref<JLocalConnection::javaobject> connect(
int pageId,
jni::alias_ref<JRemoteConnection::javaobject> remote);
static void registerNatives();
private:
friend HybridBase;
JInspector(jsinspector_modern::IInspector* inspector)
: inspector_(inspector) {}
jsinspector_modern::IInspector* inspector_;
};
} // namespace facebook::react
@@ -13,7 +13,6 @@
#include "CatalystInstanceImpl.h"
#include "CxxModuleWrapperBase.h"
#include "InspectorNetworkRequestListener.h"
#include "JInspector.h"
#include "JavaScriptExecutorHolder.h"
#include "ReactInstanceManagerInspectorTarget.h"
@@ -41,7 +40,6 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
CatalystInstanceImpl::registerNatives();
#endif
CxxModuleWrapperBase::registerNatives();
JInspector::registerNatives();
ReactInstanceManagerInspectorTarget::registerNatives();
InspectorNetworkRequestListener::registerNatives();
});
@@ -80,15 +80,6 @@ void JReactHostInspectorTarget::sendDebuggerResumeCommand() {
}
}
void JReactHostInspectorTarget::registerNatives() {
registerHybrid({
makeNativeMethod("initHybrid", JReactHostInspectorTarget::initHybrid),
makeNativeMethod(
"sendDebuggerResumeCommand",
JReactHostInspectorTarget::sendDebuggerResumeCommand),
});
}
jsinspector_modern::HostTargetMetadata
JReactHostInspectorTarget::getMetadata() {
jsinspector_modern::HostTargetMetadata metadata = {
@@ -157,4 +148,63 @@ HostTarget* JReactHostInspectorTarget::getInspectorTarget() {
return inspectorTarget_ ? inspectorTarget_.get() : nullptr;
}
bool JReactHostInspectorTarget::startBackgroundTrace() {
if (inspectorTarget_) {
return inspectorTarget_->startTracing(tracing::Mode::Background);
} else {
jni::throwNewJavaException(
"java/lang/IllegalStateException",
"Cannot start Tracing session while the Fusebox backend is not enabled.");
}
}
tracing::TraceRecordingState JReactHostInspectorTarget::stopTracing() {
if (inspectorTarget_) {
return inspectorTarget_->stopTracing();
} else {
jni::throwNewJavaException(
"java/lang/IllegalStateException",
"Cannot stop Tracing session while the Fusebox backend is not enabled.");
}
}
void JReactHostInspectorTarget::stopAndStashBackgroundTrace() {
auto capturedTrace = inspectorTarget_->stopTracing();
stashTraceRecordingState(std::move(capturedTrace));
}
void JReactHostInspectorTarget::stopAndDiscardBackgroundTrace() {
inspectorTarget_->stopTracing();
}
void JReactHostInspectorTarget::stashTraceRecordingState(
tracing::TraceRecordingState&& state) {
stashedTraceRecordingState_ = std::move(state);
}
std::optional<tracing::TraceRecordingState> JReactHostInspectorTarget::
unstable_getTraceRecordingThatWillBeEmittedOnInitialization() {
auto state = std::move(stashedTraceRecordingState_);
stashedTraceRecordingState_.reset();
return state;
}
void JReactHostInspectorTarget::registerNatives() {
registerHybrid({
makeNativeMethod("initHybrid", JReactHostInspectorTarget::initHybrid),
makeNativeMethod(
"sendDebuggerResumeCommand",
JReactHostInspectorTarget::sendDebuggerResumeCommand),
makeNativeMethod(
"startBackgroundTrace",
JReactHostInspectorTarget::startBackgroundTrace),
makeNativeMethod(
"stopAndStashBackgroundTrace",
JReactHostInspectorTarget::stopAndStashBackgroundTrace),
makeNativeMethod(
"stopAndDiscardBackgroundTrace",
JReactHostInspectorTarget::stopAndDiscardBackgroundTrace),
});
}
} // namespace facebook::react
@@ -77,6 +77,22 @@ class JReactHostInspectorTarget
static void registerNatives();
void sendDebuggerResumeCommand();
/**
* Starts a background trace recording for this HostTarget.
*
* \return false if already tracing, true otherwise.
*/
bool startBackgroundTrace();
/**
* Stops previously started trace recording and stashes the captured trace,
* which will be emitted the next time CDP session is created.
*/
void stopAndStashBackgroundTrace();
/**
* Stops previously started trace recording and discards the captured trace.
*/
void stopAndDiscardBackgroundTrace();
jsinspector_modern::HostTarget* getInspectorTarget();
// HostTargetDelegate methods
@@ -90,6 +106,8 @@ class JReactHostInspectorTarget
const jsinspector_modern::LoadNetworkResourceRequest& params,
jsinspector_modern::ScopedExecutor<
jsinspector_modern::NetworkRequestListener> executor) override;
std::optional<jsinspector_modern::tracing::TraceRecordingState>
unstable_getTraceRecordingThatWillBeEmittedOnInitialization() override;
private:
JReactHostInspectorTarget(
@@ -106,6 +124,24 @@ class JReactHostInspectorTarget
std::shared_ptr<jsinspector_modern::HostTarget> inspectorTarget_;
std::optional<int> inspectorPageId_;
/**
* Stops previously started trace recording and returns the captured trace.
*/
jsinspector_modern::tracing::TraceRecordingState stopTracing();
/**
* Stashes previously recorded trace recording state that will be emitted when
* CDP session is created. Once emitted, the value will be cleared from this
* instance.
*/
void stashTraceRecordingState(
jsinspector_modern::tracing::TraceRecordingState&& state);
/**
* Previously recorded trace recording state that will be emitted when
* CDP session is created.
*/
std::optional<jsinspector_modern::tracing::TraceRecordingState>
stashedTraceRecordingState_;
friend HybridBase;
};
} // namespace facebook::react
@@ -44,7 +44,7 @@ class BaseJavaModuleTest {
private fun findMethod(mname: String, methods: List<JavaModuleWrapper.MethodDescriptor>): Int =
methods.indexOfFirst({ it.name === mname })
@Test(expected = NativeArgumentsParseException::class)
@Test(expected = JSApplicationCausedNativeException::class)
fun testCallMethodWithoutEnoughArgs() {
val methodId = findMethod("regularMethod", methods)
whenever(arguments.size()).thenReturn(1)
@@ -328,6 +328,18 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation {
plain_.setPropertyValue(o, name, value);
};
void deleteProperty(const Object& object, const PropNameID& name) override {
plain_.deleteProperty(object, name);
}
void deleteProperty(const Object& object, const String& name) override {
plain_.deleteProperty(object, name);
}
void deleteProperty(const Object& object, const Value& name) override {
plain_.deleteProperty(object, name);
}
bool isArray(const Object& o) const override {
return plain_.isArray(o);
};
@@ -852,6 +864,21 @@ class WithRuntimeDecorator : public RuntimeDecorator<Plain, Base> {
RD::setPropertyValue(o, name, value);
};
void deleteProperty(const Object& object, const PropNameID& name) override {
Around around{with_};
RD::deleteProperty(object, name);
}
void deleteProperty(const Object& object, const String& name) override {
Around around{with_};
RD::deleteProperty(object, name);
}
void deleteProperty(const Object& object, const Value& name) override {
Around around{with_};
RD::deleteProperty(object, name);
}
bool isArray(const Object& o) const override {
Around around{with_};
return RD::isArray(o);
@@ -148,6 +148,23 @@ void Object::setProperty(Runtime& runtime, const PropNameID& name, T&& value)
runtime, name, detail::toValue(runtime, std::forward<T>(value)));
}
inline void Object::deleteProperty(Runtime& runtime, const char* name) const {
deleteProperty(runtime, String::createFromAscii(runtime, name));
}
inline void Object::deleteProperty(Runtime& runtime, const String& name) const {
runtime.deleteProperty(*this, name);
}
inline void Object::deleteProperty(Runtime& runtime, const PropNameID& name)
const {
runtime.deleteProperty(*this, name);
}
inline void Object::deleteProperty(Runtime& runtime, const Value& name) const {
runtime.deleteProperty(*this, name);
}
inline Array Object::getArray(Runtime& runtime) const& {
assert(runtime.isArray(*this));
(void)runtime; // when assert is disabled we need to mark this as used
@@ -416,6 +416,37 @@ Object Runtime::createObjectWithPrototype(const Value& prototype) {
return createFn.call(*this, prototype).asObject(*this);
}
void Runtime::deleteProperty(const Object& object, const PropNameID& name) {
auto nameStr = String::createFromUtf16(*this, name.utf16(*this));
auto deleteFn = global()
.getPropertyAsObject(*this, "Reflect")
.getPropertyAsFunction(*this, "deleteProperty");
auto res = deleteFn.call(*this, object, nameStr).getBool();
if (!res) {
throw JSError(*this, "Failed to delete property");
}
}
void Runtime::deleteProperty(const Object& object, const String& name) {
auto deleteFn = global()
.getPropertyAsObject(*this, "Reflect")
.getPropertyAsFunction(*this, "deleteProperty");
auto res = deleteFn.call(*this, object, name).getBool();
if (!res) {
throw JSError(*this, "Failed to delete property");
}
}
void Runtime::deleteProperty(const Object& object, const Value& name) {
auto deleteFn = global()
.getPropertyAsObject(*this, "Reflect")
.getPropertyAsFunction(*this, "deleteProperty");
auto res = deleteFn.call(*this, object, name).getBool();
if (!res) {
throw JSError(*this, "Failed to delete property");
}
}
void Runtime::setRuntimeDataImpl(
const UUID& uuid,
const void* data,
@@ -486,6 +486,10 @@ class JSI_EXPORT Runtime : public ICast {
virtual void
setPropertyValue(const Object&, const String& name, const Value& value) = 0;
virtual void deleteProperty(const Object&, const PropNameID& name);
virtual void deleteProperty(const Object&, const String& name);
virtual void deleteProperty(const Object&, const Value& name);
virtual bool isArray(const Object&) const = 0;
virtual bool isArrayBuffer(const Object&) const = 0;
virtual bool isFunction(const Object&) const = 0;
@@ -984,6 +988,22 @@ class JSI_EXPORT Object : public Pointer {
template <typename T>
void setProperty(Runtime& runtime, const PropNameID& name, T&& value) const;
/// Delete the property with the given ascii name. Throws if the deletion
/// failed.
void deleteProperty(Runtime& runtime, const char* name) const;
/// Delete the property with the given String name. Throws if the deletion
/// failed.
void deleteProperty(Runtime& runtime, const String& name) const;
/// Delete the property with the given PropNameID name. Throws if the deletion
/// failed.
void deleteProperty(Runtime& runtime, const PropNameID& name) const;
/// Delete the property with the given Value name. Throws if the deletion
/// failed.
void deleteProperty(Runtime& runtime, const Value& name) const;
/// \return true iff JS \c Array.isArray() would return \c true. If
/// so, then \c getArray() will succeed.
bool isArray(Runtime& runtime) const {
@@ -1882,6 +1882,65 @@ TEST_P(JSITest, CastInterface) {
EXPECT_TRUE(ptr == nullptr);
}
TEST_P(JSITest, DeleteProperty) {
// This Runtime Decorator is used to test the default implementation of
// Runtime::deleteProperty
class RD : public RuntimeDecorator<Runtime, Runtime> {
public:
explicit RD(Runtime& rt) : RuntimeDecorator(rt) {}
void deleteProperty(const Object& object, const PropNameID& name) override {
Runtime::deleteProperty(object, name);
}
void deleteProperty(const Object& object, const String& name) override {
Runtime::deleteProperty(object, name);
}
void deleteProperty(const Object& object, const Value& name) override {
Runtime::deleteProperty(object, name);
}
};
RD rd = RD(rt);
auto obj = eval("obj = {1:2, foo: 'bar', 3: 4, salt:'pepper'}").getObject(rd);
auto prop = PropNameID::forAscii(rd, "1");
auto hasRes = obj.hasProperty(rd, prop);
EXPECT_TRUE(hasRes);
obj.deleteProperty(rd, prop);
hasRes = obj.hasProperty(rd, prop);
EXPECT_FALSE(hasRes);
auto str = String::createFromAscii(rd, "foo");
hasRes = obj.hasProperty(rd, str);
EXPECT_TRUE(hasRes);
obj.deleteProperty(rd, str);
hasRes = obj.hasProperty(rd, str);
EXPECT_FALSE(hasRes);
auto valProp = Value(3);
hasRes = obj.hasProperty(rd, "3");
EXPECT_TRUE(hasRes);
obj.deleteProperty(rd, valProp);
auto getRes = obj.getProperty(rd, "3");
EXPECT_TRUE(getRes.isUndefined());
hasRes = obj.hasProperty(rd, "salt");
EXPECT_TRUE(hasRes);
obj.deleteProperty(rd, "salt");
hasRes = obj.hasProperty(rd, "salt");
EXPECT_FALSE(hasRes);
obj = eval(
"const obj = {};"
"Object.defineProperty(obj, 'prop', {"
" value: 10,"
" configurable: false,});"
"obj;")
.getObject(rd);
EXPECT_THROW(obj.deleteProperty(rd, "prop"), JSError);
hasRes = obj.hasProperty(rd, "prop");
EXPECT_TRUE(hasRes);
}
INSTANTIATE_TEST_CASE_P(
Runtimes,
JSITest,
@@ -41,14 +41,18 @@ class HostAgent::Impl final {
HostTargetController& targetController,
HostTargetMetadata hostMetadata,
SessionState& sessionState,
VoidExecutor executor)
VoidExecutor executor,
std::optional<tracing::TraceRecordingState> traceRecordingToEmit)
: frontendChannel_(frontendChannel),
targetController_(targetController),
hostMetadata_(std::move(hostMetadata)),
sessionState_(sessionState),
networkIOAgent_(NetworkIOAgent(frontendChannel, std::move(executor))),
tracingAgent_(
TracingAgent(frontendChannel, sessionState, targetController)) {}
tracingAgent_(TracingAgent(
frontendChannel,
sessionState,
targetController,
std::move(traceRecordingToEmit))) {}
~Impl() {
if (isPausedInDebuggerOverlayVisible_) {
@@ -428,7 +432,8 @@ class HostAgent::Impl final {
HostTargetController& targetController,
HostTargetMetadata hostMetadata,
SessionState& sessionState,
VoidExecutor executor) {}
VoidExecutor executor,
std::optional<tracing::TraceRecordingState> traceRecordingToEmit) {}
void handleRequest(const cdp::PreparsedRequest& req) {}
void setCurrentInstanceAgent(std::shared_ptr<InstanceAgent> agent) {}
@@ -441,14 +446,16 @@ HostAgent::HostAgent(
HostTargetController& targetController,
HostTargetMetadata hostMetadata,
SessionState& sessionState,
VoidExecutor executor)
VoidExecutor executor,
std::optional<tracing::TraceRecordingState> traceRecordingToEmit)
: impl_(std::make_unique<Impl>(
*this,
frontendChannel,
targetController,
std::move(hostMetadata),
sessionState,
std::move(executor))) {}
std::move(executor),
std::move(traceRecordingToEmit))) {}
HostAgent::~HostAgent() = default;
@@ -36,13 +36,16 @@ class HostAgent final {
* \param hostMetadata Metadata about the host that created this agent.
* \param sessionState The state of the session that created this agent.
* \param executor A void executor to be used by async-aware handlers.
* \param traceRecordingToEmit If set, this is the trace that Host has
* requested to display in the Frontend.
*/
HostAgent(
const FrontendChannel& frontendChannel,
HostTargetController& targetController,
HostTargetMetadata hostMetadata,
SessionState& sessionState,
VoidExecutor executor);
VoidExecutor executor,
std::optional<tracing::TraceRecordingState> traceRecordingToEmit);
HostAgent(const HostAgent&) = delete;
HostAgent(HostAgent&&) = delete;
@@ -34,7 +34,8 @@ class HostTargetSession {
std::unique_ptr<IRemoteConnection> remote,
HostTargetController& targetController,
HostTargetMetadata hostMetadata,
VoidExecutor executor)
VoidExecutor executor,
std::optional<tracing::TraceRecordingState> traceRecordingToEmit)
: remote_(std::make_shared<RAIIRemoteConnection>(std::move(remote))),
frontendChannel_(
[remoteWeak = std::weak_ptr(remote_)](std::string_view message) {
@@ -47,7 +48,8 @@ class HostTargetSession {
targetController,
std::move(hostMetadata),
state_,
std::move(executor)) {}
std::move(executor),
std::move(traceRecordingToEmit)) {}
/**
* Called by CallbackLocalConnection to send a message to this Session's
@@ -206,7 +208,8 @@ std::unique_ptr<ILocalConnection> HostTarget::connect(
std::move(connectionToFrontend),
controller_,
delegate_.getMetadata(),
makeVoidExecutor(executorFromThis()));
makeVoidExecutor(executorFromThis()),
delegate_.unstable_getTraceRecordingThatWillBeEmittedOnInitialization());
session->setCurrentInstance(currentInstance_.get());
sessions_.insert(std::weak_ptr(session));
return std::make_unique<CallbackLocalConnection>(
@@ -217,6 +220,11 @@ HostTarget::~HostTarget() {
// HostCommandSender owns a session, so we must release it for the assertion
// below to be valid.
commandSender_.reset();
// HostRuntimeBinding owns a connection, so we must release it for the
// assertion
perfMetricsBinding_.reset();
// Sessions are owned by InspectorPackagerConnection, not by HostTarget, but
// they hold a HostTarget& that we must guarantee is valid.
assert(
@@ -146,6 +146,19 @@ class HostTargetDelegate : public LoadNetworkResourceDelegate {
throw NotImplementedException(
"LoadNetworkResourceDelegate.loadNetworkResource is not implemented by this host target delegate.");
}
/**
* [Experimental] Will be called at the CDP session initialization to get the
* trace recording that may have been stashed by the Host from the previous
* background session.
*
* \return the trace recording state if there is one that needs to be
* displayed, otherwise std::nullopt.
*/
virtual std::optional<tracing::TraceRecordingState>
unstable_getTraceRecordingThatWillBeEmittedOnInitialization() {
return std::nullopt;
}
};
/**
@@ -38,10 +38,17 @@ const uint16_t PROFILE_TRACE_EVENT_CHUNK_SIZE = 1;
TracingAgent::TracingAgent(
FrontendChannel frontendChannel,
SessionState& sessionState,
HostTargetController& hostTargetController)
HostTargetController& hostTargetController,
std::optional<tracing::TraceRecordingState> traceRecordingToEmit)
: frontendChannel_(std::move(frontendChannel)),
sessionState_(sessionState),
hostTargetController_(hostTargetController) {}
hostTargetController_(hostTargetController) {
if (traceRecordingToEmit.has_value()) {
frontendChannel_(
cdp::jsonNotification("ReactNativeApplication.traceRequested"));
emitTraceRecording(std::move(traceRecordingToEmit.value()));
}
}
TracingAgent::~TracingAgent() {
// Agents are owned by the session. If the agent is destroyed, it means that
@@ -86,25 +93,29 @@ bool TracingAgent::handleRequest(const cdp::PreparsedRequest& req) {
// Send response to Tracing.end request.
frontendChannel_(cdp::jsonResult(req.id));
auto dataCollectedCallback = [this](folly::dynamic&& eventsChunk) {
frontendChannel_(cdp::jsonNotification(
"Tracing.dataCollected",
folly::dynamic::object("value", std::move(eventsChunk))));
};
tracing::TraceRecordingStateSerializer::emitAsDataCollectedChunks(
std::move(state),
dataCollectedCallback,
TRACE_EVENT_CHUNK_SIZE,
PROFILE_TRACE_EVENT_CHUNK_SIZE);
frontendChannel_(cdp::jsonNotification(
"Tracing.tracingComplete",
folly::dynamic::object("dataLossOccurred", false)));
emitTraceRecording(std::move(state));
return true;
}
return false;
}
void TracingAgent::emitTraceRecording(
tracing::TraceRecordingState state) const {
auto dataCollectedCallback = [this](folly::dynamic&& eventsChunk) {
frontendChannel_(cdp::jsonNotification(
"Tracing.dataCollected",
folly::dynamic::object("value", std::move(eventsChunk))));
};
tracing::TraceRecordingStateSerializer::emitAsDataCollectedChunks(
std::move(state),
dataCollectedCallback,
TRACE_EVENT_CHUNK_SIZE,
PROFILE_TRACE_EVENT_CHUNK_SIZE);
frontendChannel_(cdp::jsonNotification(
"Tracing.tracingComplete",
folly::dynamic::object("dataLossOccurred", false)));
}
} // namespace facebook::react::jsinspector_modern
@@ -24,11 +24,18 @@ class TracingAgent {
/**
* \param frontendChannel A channel used to send responses to the
* frontend.
* \param sessionState The state of the session that created this agent.
* \param hostTargetController An interface to the HostTarget that this agent
* is attached to. The caller is responsible for ensuring that the
* HostTargetDelegate and underlying HostTarget both outlive the agent.
* \param traceRecordingToEmit If set, this is the trace that Host has
* requested to display in the Frontend.
*/
TracingAgent(
FrontendChannel frontendChannel,
SessionState& sessionState,
HostTargetController& hostTargetController);
HostTargetController& hostTargetController,
std::optional<tracing::TraceRecordingState> traceRecordingToEmit);
~TracingAgent();
@@ -48,6 +55,12 @@ class TracingAgent {
SessionState& sessionState_;
HostTargetController& hostTargetController_;
/**
* Emits the captured Trace Recording state in a series of
* Tracing.dataCollected events, followed by a Tracing.tracingComplete event.
*/
void emitTraceRecording(tracing::TraceRecordingState state) const;
};
} // namespace facebook::react::jsinspector_modern
@@ -190,6 +190,7 @@ void PerformanceTracer::reportTimeStamp(
.trackName = std::move(trackName),
.trackGroup = std::move(trackGroup),
.color = std::move(color),
.threadId = getCurrentThreadId(),
});
}
@@ -399,7 +400,7 @@ void PerformanceTracer::enqueueTraceEventsFromPerformanceTracerEvent(
.ph = 'X',
.ts = event.start,
.pid = processId_,
.tid = getCurrentThreadId(),
.tid = event.threadId,
.dur = event.end - event.start,
});
},
@@ -410,7 +411,7 @@ void PerformanceTracer::enqueueTraceEventsFromPerformanceTracerEvent(
.ph = 'X',
.ts = event.start,
.pid = processId_,
.tid = getCurrentThreadId(),
.tid = event.threadId,
.dur = event.end - event.start,
});
},
@@ -429,7 +430,7 @@ void PerformanceTracer::enqueueTraceEventsFromPerformanceTracerEvent(
.ph = 'I',
.ts = event.start,
.pid = processId_,
.tid = getCurrentThreadId(),
.tid = event.threadId,
.args = std::move(eventArgs),
});
},
@@ -449,7 +450,7 @@ void PerformanceTracer::enqueueTraceEventsFromPerformanceTracerEvent(
.ph = 'b',
.ts = event.start,
.pid = processId_,
.tid = getCurrentThreadId(),
.tid = event.threadId,
.args = std::move(beginEventArgs),
});
events.emplace_back(TraceEvent{
@@ -459,7 +460,7 @@ void PerformanceTracer::enqueueTraceEventsFromPerformanceTracerEvent(
.ph = 'e',
.ts = event.start + event.duration,
.pid = processId_,
.tid = getCurrentThreadId(),
.tid = event.threadId,
});
},
[&](PerformanceTracerEventTimeStamp&& event) {
@@ -500,7 +501,7 @@ void PerformanceTracer::enqueueTraceEventsFromPerformanceTracerEvent(
.ph = 'I',
.ts = event.createdAt,
.pid = processId_,
.tid = getCurrentThreadId(),
.tid = event.threadId,
.args = folly::dynamic::object("data", std::move(data)),
});
},
@@ -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<<392fdd6e857b7c8ae99329b927be6ae0>>
* @generated SignedSource<<12a06ea04fc09c34f1fbdcbdf6046d81>>
*/
/**
@@ -178,6 +178,10 @@ bool ReactNativeFeatureFlags::enableViewRecycling() {
return getAccessor().enableViewRecycling();
}
bool ReactNativeFeatureFlags::enableViewRecyclingForScrollView() {
return getAccessor().enableViewRecyclingForScrollView();
}
bool ReactNativeFeatureFlags::enableViewRecyclingForText() {
return getAccessor().enableViewRecyclingForText();
}
@@ -290,6 +294,10 @@ bool ReactNativeFeatureFlags::useTurboModules() {
return getAccessor().useTurboModules();
}
double ReactNativeFeatureFlags::virtualViewHysteresisRatio() {
return getAccessor().virtualViewHysteresisRatio();
}
double ReactNativeFeatureFlags::virtualViewPrerenderRatio() {
return getAccessor().virtualViewPrerenderRatio();
}
@@ -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<<b601a3c92cd80549ca2391ab0a123214>>
* @generated SignedSource<<eee81e4e9bb13ef5134d4e2d79876b38>>
*/
/**
@@ -229,6 +229,11 @@ class ReactNativeFeatureFlags {
*/
RN_EXPORT static bool enableViewRecycling();
/**
* Enables View Recycling for <ScrollView> via ReactViewGroup/ReactViewManager.
*/
RN_EXPORT static bool enableViewRecyclingForScrollView();
/**
* Enables View Recycling for <Text> via ReactTextView/ReactTextViewManager.
*/
@@ -369,6 +374,11 @@ class ReactNativeFeatureFlags {
*/
RN_EXPORT static bool useTurboModules();
/**
* Sets a hysteresis window for transition between prerender and hidden modes.
*/
RN_EXPORT static double virtualViewHysteresisRatio();
/**
* Initial prerender ratio for VirtualView.
*/
@@ -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<<69518331e8b6225d4aa524e46951302d>>
* @generated SignedSource<<3c5588a851e6cdefaba22236c5ebb828>>
*/
/**
@@ -713,6 +713,24 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecycling() {
return flagValue.value();
}
bool ReactNativeFeatureFlagsAccessor::enableViewRecyclingForScrollView() {
auto flagValue = enableViewRecyclingForScrollView_.load();
if (!flagValue.has_value()) {
// This block is not exclusive but it is not necessary.
// If multiple threads try to initialize the feature flag, we would only
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(38, "enableViewRecyclingForScrollView");
flagValue = currentProvider_->enableViewRecyclingForScrollView();
enableViewRecyclingForScrollView_ = flagValue;
}
return flagValue.value();
}
bool ReactNativeFeatureFlagsAccessor::enableViewRecyclingForText() {
auto flagValue = enableViewRecyclingForText_.load();
@@ -722,7 +740,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecyclingForText() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(38, "enableViewRecyclingForText");
markFlagAsAccessed(39, "enableViewRecyclingForText");
flagValue = currentProvider_->enableViewRecyclingForText();
enableViewRecyclingForText_ = flagValue;
@@ -740,7 +758,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecyclingForView() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(39, "enableViewRecyclingForView");
markFlagAsAccessed(40, "enableViewRecyclingForView");
flagValue = currentProvider_->enableViewRecyclingForView();
enableViewRecyclingForView_ = flagValue;
@@ -758,7 +776,7 @@ bool ReactNativeFeatureFlagsAccessor::enableVirtualViewDebugFeatures() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(40, "enableVirtualViewDebugFeatures");
markFlagAsAccessed(41, "enableVirtualViewDebugFeatures");
flagValue = currentProvider_->enableVirtualViewDebugFeatures();
enableVirtualViewDebugFeatures_ = flagValue;
@@ -776,7 +794,7 @@ bool ReactNativeFeatureFlagsAccessor::enableVirtualViewRenderState() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(41, "enableVirtualViewRenderState");
markFlagAsAccessed(42, "enableVirtualViewRenderState");
flagValue = currentProvider_->enableVirtualViewRenderState();
enableVirtualViewRenderState_ = flagValue;
@@ -794,7 +812,7 @@ bool ReactNativeFeatureFlagsAccessor::enableVirtualViewWindowFocusDetection() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(42, "enableVirtualViewWindowFocusDetection");
markFlagAsAccessed(43, "enableVirtualViewWindowFocusDetection");
flagValue = currentProvider_->enableVirtualViewWindowFocusDetection();
enableVirtualViewWindowFocusDetection_ = flagValue;
@@ -812,7 +830,7 @@ bool ReactNativeFeatureFlagsAccessor::fixMappingOfEventPrioritiesBetweenFabricAn
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(43, "fixMappingOfEventPrioritiesBetweenFabricAndReact");
markFlagAsAccessed(44, "fixMappingOfEventPrioritiesBetweenFabricAndReact");
flagValue = currentProvider_->fixMappingOfEventPrioritiesBetweenFabricAndReact();
fixMappingOfEventPrioritiesBetweenFabricAndReact_ = flagValue;
@@ -830,7 +848,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxEnabledRelease() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(44, "fuseboxEnabledRelease");
markFlagAsAccessed(45, "fuseboxEnabledRelease");
flagValue = currentProvider_->fuseboxEnabledRelease();
fuseboxEnabledRelease_ = flagValue;
@@ -848,7 +866,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxNetworkInspectionEnabled() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(45, "fuseboxNetworkInspectionEnabled");
markFlagAsAccessed(46, "fuseboxNetworkInspectionEnabled");
flagValue = currentProvider_->fuseboxNetworkInspectionEnabled();
fuseboxNetworkInspectionEnabled_ = flagValue;
@@ -866,7 +884,7 @@ bool ReactNativeFeatureFlagsAccessor::hideOffscreenVirtualViewsOnIOS() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(46, "hideOffscreenVirtualViewsOnIOS");
markFlagAsAccessed(47, "hideOffscreenVirtualViewsOnIOS");
flagValue = currentProvider_->hideOffscreenVirtualViewsOnIOS();
hideOffscreenVirtualViewsOnIOS_ = flagValue;
@@ -884,7 +902,7 @@ bool ReactNativeFeatureFlagsAccessor::perfMonitorV2Enabled() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(47, "perfMonitorV2Enabled");
markFlagAsAccessed(48, "perfMonitorV2Enabled");
flagValue = currentProvider_->perfMonitorV2Enabled();
perfMonitorV2Enabled_ = flagValue;
@@ -902,7 +920,7 @@ double ReactNativeFeatureFlagsAccessor::preparedTextCacheSize() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(48, "preparedTextCacheSize");
markFlagAsAccessed(49, "preparedTextCacheSize");
flagValue = currentProvider_->preparedTextCacheSize();
preparedTextCacheSize_ = flagValue;
@@ -920,7 +938,7 @@ bool ReactNativeFeatureFlagsAccessor::preventShadowTreeCommitExhaustion() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(49, "preventShadowTreeCommitExhaustion");
markFlagAsAccessed(50, "preventShadowTreeCommitExhaustion");
flagValue = currentProvider_->preventShadowTreeCommitExhaustion();
preventShadowTreeCommitExhaustion_ = flagValue;
@@ -938,7 +956,7 @@ bool ReactNativeFeatureFlagsAccessor::releaseImageDataWhenConsumed() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(50, "releaseImageDataWhenConsumed");
markFlagAsAccessed(51, "releaseImageDataWhenConsumed");
flagValue = currentProvider_->releaseImageDataWhenConsumed();
releaseImageDataWhenConsumed_ = flagValue;
@@ -956,7 +974,7 @@ bool ReactNativeFeatureFlagsAccessor::shouldPressibilityUseW3CPointerEventsForHo
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(51, "shouldPressibilityUseW3CPointerEventsForHover");
markFlagAsAccessed(52, "shouldPressibilityUseW3CPointerEventsForHover");
flagValue = currentProvider_->shouldPressibilityUseW3CPointerEventsForHover();
shouldPressibilityUseW3CPointerEventsForHover_ = flagValue;
@@ -974,7 +992,7 @@ bool ReactNativeFeatureFlagsAccessor::skipActivityIdentityAssertionOnHostPause()
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(52, "skipActivityIdentityAssertionOnHostPause");
markFlagAsAccessed(53, "skipActivityIdentityAssertionOnHostPause");
flagValue = currentProvider_->skipActivityIdentityAssertionOnHostPause();
skipActivityIdentityAssertionOnHostPause_ = flagValue;
@@ -992,7 +1010,7 @@ bool ReactNativeFeatureFlagsAccessor::sweepActiveTouchOnChildNativeGesturesAndro
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(53, "sweepActiveTouchOnChildNativeGesturesAndroid");
markFlagAsAccessed(54, "sweepActiveTouchOnChildNativeGesturesAndroid");
flagValue = currentProvider_->sweepActiveTouchOnChildNativeGesturesAndroid();
sweepActiveTouchOnChildNativeGesturesAndroid_ = flagValue;
@@ -1010,7 +1028,7 @@ bool ReactNativeFeatureFlagsAccessor::traceTurboModulePromiseRejectionsOnAndroid
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(54, "traceTurboModulePromiseRejectionsOnAndroid");
markFlagAsAccessed(55, "traceTurboModulePromiseRejectionsOnAndroid");
flagValue = currentProvider_->traceTurboModulePromiseRejectionsOnAndroid();
traceTurboModulePromiseRejectionsOnAndroid_ = flagValue;
@@ -1028,7 +1046,7 @@ bool ReactNativeFeatureFlagsAccessor::updateRuntimeShadowNodeReferencesOnCommit(
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(55, "updateRuntimeShadowNodeReferencesOnCommit");
markFlagAsAccessed(56, "updateRuntimeShadowNodeReferencesOnCommit");
flagValue = currentProvider_->updateRuntimeShadowNodeReferencesOnCommit();
updateRuntimeShadowNodeReferencesOnCommit_ = flagValue;
@@ -1046,7 +1064,7 @@ bool ReactNativeFeatureFlagsAccessor::useAlwaysAvailableJSErrorHandling() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(56, "useAlwaysAvailableJSErrorHandling");
markFlagAsAccessed(57, "useAlwaysAvailableJSErrorHandling");
flagValue = currentProvider_->useAlwaysAvailableJSErrorHandling();
useAlwaysAvailableJSErrorHandling_ = flagValue;
@@ -1064,7 +1082,7 @@ bool ReactNativeFeatureFlagsAccessor::useFabricInterop() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(57, "useFabricInterop");
markFlagAsAccessed(58, "useFabricInterop");
flagValue = currentProvider_->useFabricInterop();
useFabricInterop_ = flagValue;
@@ -1082,7 +1100,7 @@ bool ReactNativeFeatureFlagsAccessor::useNativeEqualsInNativeReadableArrayAndroi
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(58, "useNativeEqualsInNativeReadableArrayAndroid");
markFlagAsAccessed(59, "useNativeEqualsInNativeReadableArrayAndroid");
flagValue = currentProvider_->useNativeEqualsInNativeReadableArrayAndroid();
useNativeEqualsInNativeReadableArrayAndroid_ = flagValue;
@@ -1100,7 +1118,7 @@ bool ReactNativeFeatureFlagsAccessor::useNativeTransformHelperAndroid() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(59, "useNativeTransformHelperAndroid");
markFlagAsAccessed(60, "useNativeTransformHelperAndroid");
flagValue = currentProvider_->useNativeTransformHelperAndroid();
useNativeTransformHelperAndroid_ = flagValue;
@@ -1118,7 +1136,7 @@ bool ReactNativeFeatureFlagsAccessor::useNativeViewConfigsInBridgelessMode() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(60, "useNativeViewConfigsInBridgelessMode");
markFlagAsAccessed(61, "useNativeViewConfigsInBridgelessMode");
flagValue = currentProvider_->useNativeViewConfigsInBridgelessMode();
useNativeViewConfigsInBridgelessMode_ = flagValue;
@@ -1136,7 +1154,7 @@ bool ReactNativeFeatureFlagsAccessor::useOptimizedEventBatchingOnAndroid() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(61, "useOptimizedEventBatchingOnAndroid");
markFlagAsAccessed(62, "useOptimizedEventBatchingOnAndroid");
flagValue = currentProvider_->useOptimizedEventBatchingOnAndroid();
useOptimizedEventBatchingOnAndroid_ = flagValue;
@@ -1154,7 +1172,7 @@ bool ReactNativeFeatureFlagsAccessor::useRawPropsJsiValue() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(62, "useRawPropsJsiValue");
markFlagAsAccessed(63, "useRawPropsJsiValue");
flagValue = currentProvider_->useRawPropsJsiValue();
useRawPropsJsiValue_ = flagValue;
@@ -1172,7 +1190,7 @@ bool ReactNativeFeatureFlagsAccessor::useShadowNodeStateOnClone() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(63, "useShadowNodeStateOnClone");
markFlagAsAccessed(64, "useShadowNodeStateOnClone");
flagValue = currentProvider_->useShadowNodeStateOnClone();
useShadowNodeStateOnClone_ = flagValue;
@@ -1190,7 +1208,7 @@ bool ReactNativeFeatureFlagsAccessor::useTurboModuleInterop() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(64, "useTurboModuleInterop");
markFlagAsAccessed(65, "useTurboModuleInterop");
flagValue = currentProvider_->useTurboModuleInterop();
useTurboModuleInterop_ = flagValue;
@@ -1208,7 +1226,7 @@ bool ReactNativeFeatureFlagsAccessor::useTurboModules() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(65, "useTurboModules");
markFlagAsAccessed(66, "useTurboModules");
flagValue = currentProvider_->useTurboModules();
useTurboModules_ = flagValue;
@@ -1217,6 +1235,24 @@ bool ReactNativeFeatureFlagsAccessor::useTurboModules() {
return flagValue.value();
}
double ReactNativeFeatureFlagsAccessor::virtualViewHysteresisRatio() {
auto flagValue = virtualViewHysteresisRatio_.load();
if (!flagValue.has_value()) {
// This block is not exclusive but it is not necessary.
// If multiple threads try to initialize the feature flag, we would only
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(67, "virtualViewHysteresisRatio");
flagValue = currentProvider_->virtualViewHysteresisRatio();
virtualViewHysteresisRatio_ = flagValue;
}
return flagValue.value();
}
double ReactNativeFeatureFlagsAccessor::virtualViewPrerenderRatio() {
auto flagValue = virtualViewPrerenderRatio_.load();
@@ -1226,7 +1262,7 @@ double ReactNativeFeatureFlagsAccessor::virtualViewPrerenderRatio() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(66, "virtualViewPrerenderRatio");
markFlagAsAccessed(68, "virtualViewPrerenderRatio");
flagValue = currentProvider_->virtualViewPrerenderRatio();
virtualViewPrerenderRatio_ = flagValue;
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<e7ebd228905c959f5472fba72bc3f99c>>
* @generated SignedSource<<f1eb31a7412bff743a5c581224d71e2a>>
*/
/**
@@ -70,6 +70,7 @@ class ReactNativeFeatureFlagsAccessor {
bool enableResourceTimingAPI();
bool enableViewCulling();
bool enableViewRecycling();
bool enableViewRecyclingForScrollView();
bool enableViewRecyclingForText();
bool enableViewRecyclingForView();
bool enableVirtualViewDebugFeatures();
@@ -98,6 +99,7 @@ class ReactNativeFeatureFlagsAccessor {
bool useShadowNodeStateOnClone();
bool useTurboModuleInterop();
bool useTurboModules();
double virtualViewHysteresisRatio();
double virtualViewPrerenderRatio();
void override(std::unique_ptr<ReactNativeFeatureFlagsProvider> provider);
@@ -110,7 +112,7 @@ class ReactNativeFeatureFlagsAccessor {
std::unique_ptr<ReactNativeFeatureFlagsProvider> currentProvider_;
bool wasOverridden_;
std::array<std::atomic<const char*>, 67> accessedFeatureFlags_;
std::array<std::atomic<const char*>, 69> accessedFeatureFlags_;
std::atomic<std::optional<bool>> commonTestFlag_;
std::atomic<std::optional<bool>> cdpInteractionMetricsEnabled_;
@@ -150,6 +152,7 @@ class ReactNativeFeatureFlagsAccessor {
std::atomic<std::optional<bool>> enableResourceTimingAPI_;
std::atomic<std::optional<bool>> enableViewCulling_;
std::atomic<std::optional<bool>> enableViewRecycling_;
std::atomic<std::optional<bool>> enableViewRecyclingForScrollView_;
std::atomic<std::optional<bool>> enableViewRecyclingForText_;
std::atomic<std::optional<bool>> enableViewRecyclingForView_;
std::atomic<std::optional<bool>> enableVirtualViewDebugFeatures_;
@@ -178,6 +181,7 @@ class ReactNativeFeatureFlagsAccessor {
std::atomic<std::optional<bool>> useShadowNodeStateOnClone_;
std::atomic<std::optional<bool>> useTurboModuleInterop_;
std::atomic<std::optional<bool>> useTurboModules_;
std::atomic<std::optional<double>> virtualViewHysteresisRatio_;
std::atomic<std::optional<double>> virtualViewPrerenderRatio_;
};
@@ -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<<a7f5d45347dee3c9c5b17731e1bf8993>>
* @generated SignedSource<<a76f1a1e8ba0d65b689b4b87d33d7ced>>
*/
/**
@@ -179,6 +179,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider {
return false;
}
bool enableViewRecyclingForScrollView() override {
return false;
}
bool enableViewRecyclingForText() override {
return true;
}
@@ -260,11 +264,11 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider {
}
bool useNativeEqualsInNativeReadableArrayAndroid() override {
return false;
return true;
}
bool useNativeTransformHelperAndroid() override {
return false;
return true;
}
bool useNativeViewConfigsInBridgelessMode() override {
@@ -276,7 +280,7 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider {
}
bool useRawPropsJsiValue() override {
return false;
return true;
}
bool useShadowNodeStateOnClone() override {
@@ -291,6 +295,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider {
return false;
}
double virtualViewHysteresisRatio() override {
return 0.0;
}
double virtualViewPrerenderRatio() override {
return 5.0;
}
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<60b81844a9af1862b27ed6b4d9be5f59>>
* @generated SignedSource<<e2a5086e5586caf4c90ef503416a0e83>>
*/
/**
@@ -387,6 +387,15 @@ class ReactNativeFeatureFlagsDynamicProvider : public ReactNativeFeatureFlagsDef
return ReactNativeFeatureFlagsDefaults::enableViewRecycling();
}
bool enableViewRecyclingForScrollView() override {
auto value = values_["enableViewRecyclingForScrollView"];
if (!value.isNull()) {
return value.getBool();
}
return ReactNativeFeatureFlagsDefaults::enableViewRecyclingForScrollView();
}
bool enableViewRecyclingForText() override {
auto value = values_["enableViewRecyclingForText"];
if (!value.isNull()) {
@@ -639,6 +648,15 @@ class ReactNativeFeatureFlagsDynamicProvider : public ReactNativeFeatureFlagsDef
return ReactNativeFeatureFlagsDefaults::useTurboModules();
}
double virtualViewHysteresisRatio() override {
auto value = values_["virtualViewHysteresisRatio"];
if (!value.isNull()) {
return value.getDouble();
}
return ReactNativeFeatureFlagsDefaults::virtualViewHysteresisRatio();
}
double virtualViewPrerenderRatio() override {
auto value = values_["virtualViewPrerenderRatio"];
if (!value.isNull()) {
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<c9b7b95d3cc3fed879476f191a60d3f2>>
* @generated SignedSource<<77870f0db494c7b6932950a1fa475fdc>>
*/
/**
@@ -34,14 +34,6 @@ class ReactNativeFeatureFlagsOverridesOSSExperimental : public ReactNativeFeatur
bool preventShadowTreeCommitExhaustion() override {
return true;
}
bool useNativeEqualsInNativeReadableArrayAndroid() override {
return true;
}
bool useNativeTransformHelperAndroid() override {
return true;
}
};
} // namespace facebook::react
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<56fe64198dddcba67062ef52a180128e>>
* @generated SignedSource<<feb44bb7ec97d29787eac070103f9e1b>>
*/
/**
@@ -63,6 +63,7 @@ class ReactNativeFeatureFlagsProvider {
virtual bool enableResourceTimingAPI() = 0;
virtual bool enableViewCulling() = 0;
virtual bool enableViewRecycling() = 0;
virtual bool enableViewRecyclingForScrollView() = 0;
virtual bool enableViewRecyclingForText() = 0;
virtual bool enableViewRecyclingForView() = 0;
virtual bool enableVirtualViewDebugFeatures() = 0;
@@ -91,6 +92,7 @@ class ReactNativeFeatureFlagsProvider {
virtual bool useShadowNodeStateOnClone() = 0;
virtual bool useTurboModuleInterop() = 0;
virtual bool useTurboModules() = 0;
virtual double virtualViewHysteresisRatio() = 0;
virtual double virtualViewPrerenderRatio() = 0;
};
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<3c321b78f9d710e5f3dc3a73e56be298>>
* @generated SignedSource<<c9c36c1dbece9e27f7b71da7611cb747>>
*/
/**
@@ -234,6 +234,11 @@ bool NativeReactNativeFeatureFlags::enableViewRecycling(
return ReactNativeFeatureFlags::enableViewRecycling();
}
bool NativeReactNativeFeatureFlags::enableViewRecyclingForScrollView(
jsi::Runtime& /*runtime*/) {
return ReactNativeFeatureFlags::enableViewRecyclingForScrollView();
}
bool NativeReactNativeFeatureFlags::enableViewRecyclingForText(
jsi::Runtime& /*runtime*/) {
return ReactNativeFeatureFlags::enableViewRecyclingForText();
@@ -374,6 +379,11 @@ bool NativeReactNativeFeatureFlags::useTurboModules(
return ReactNativeFeatureFlags::useTurboModules();
}
double NativeReactNativeFeatureFlags::virtualViewHysteresisRatio(
jsi::Runtime& /*runtime*/) {
return ReactNativeFeatureFlags::virtualViewHysteresisRatio();
}
double NativeReactNativeFeatureFlags::virtualViewPrerenderRatio(
jsi::Runtime& /*runtime*/) {
return ReactNativeFeatureFlags::virtualViewPrerenderRatio();
@@ -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<<15625838a3b9e9ecf3e77940a5f019a6>>
* @generated SignedSource<<320e69fa54228a352fad210e3a43b947>>
*/
/**
@@ -112,6 +112,8 @@ class NativeReactNativeFeatureFlags
bool enableViewRecycling(jsi::Runtime& runtime);
bool enableViewRecyclingForScrollView(jsi::Runtime& runtime);
bool enableViewRecyclingForText(jsi::Runtime& runtime);
bool enableViewRecyclingForView(jsi::Runtime& runtime);
@@ -168,6 +170,8 @@ class NativeReactNativeFeatureFlags
bool useTurboModules(jsi::Runtime& runtime);
double virtualViewHysteresisRatio(jsi::Runtime& runtime);
double virtualViewPrerenderRatio(jsi::Runtime& runtime);
};
@@ -20,7 +20,9 @@ Size SwitchShadowNode::measureContent(
const LayoutConstraints & /*layoutConstraints*/) const
{
CGSize uiSwitchSize = RCTSwitchSize();
return {.width = uiSwitchSize.width, .height = uiSwitchSize.height};
// Apple has some error when returning the width of the component and it doesn't
// account for the borders.
return {.width = uiSwitchSize.width + 2, .height = uiSwitchSize.height};
}
} // namespace facebook::react
@@ -184,7 +184,7 @@ static inline facebook::react::ColorComponents _ColorComponentsFromUIColor(UICol
{
CGFloat rgba[4];
[color getRed:&rgba[0] green:&rgba[1] blue:&rgba[2] alpha:&rgba[3]];
return {(float)rgba[0], (float)rgba[1], (float)rgba[2], (float)rgba[3]};
return {.red = (float)rgba[0], .green = (float)rgba[1], .blue = (float)rgba[2], .alpha = (float)rgba[3]};
}
facebook::react::ColorComponents RCTPlatformColorComponentsFromSemanticItems(std::vector<std::string> &semanticItems)
@@ -126,6 +126,8 @@ static void calculateShadowViewMutations(
const CullingContext& oldCullingContext = {},
const CullingContext& newCullingContext = {});
namespace {
struct OrderedMutationInstructionContainer {
ShadowViewMutation::List createMutations{};
ShadowViewMutation::List deleteMutations{};
@@ -136,6 +138,8 @@ struct OrderedMutationInstructionContainer {
ShadowViewMutation::List destructiveDownwardMutations{};
};
} // namespace
static void updateMatchedPairSubtrees(
ViewNodePairScope& scope,
OrderedMutationInstructionContainer& mutationContainer,
@@ -187,34 +187,36 @@ static NSLineBreakMode RCTNSLineBreakModeFromEllipsizeMode(EllipsizeMode ellipsi
std::vector<LineMeasurement> paragraphLines{};
auto blockParagraphLines = &paragraphLines;
[layoutManager enumerateLineFragmentsForGlyphRange:glyphRange
usingBlock:^(
CGRect overallRect,
CGRect usedRect,
NSTextContainer *_Nonnull usedTextContainer,
NSRange lineGlyphRange,
BOOL *_Nonnull stop) {
NSRange range = [layoutManager characterRangeForGlyphRange:lineGlyphRange
actualGlyphRange:nil];
NSString *renderedString = [textStorage.string substringWithRange:range];
UIFont *font = [[textStorage attributedSubstringFromRange:range]
attribute:NSFontAttributeName
atIndex:0
effectiveRange:nil];
auto rect = facebook::react::Rect{
facebook::react::Point{usedRect.origin.x, usedRect.origin.y},
facebook::react::Size{usedRect.size.width, usedRect.size.height}};
[layoutManager
enumerateLineFragmentsForGlyphRange:glyphRange
usingBlock:^(
CGRect overallRect,
CGRect usedRect,
NSTextContainer *_Nonnull usedTextContainer,
NSRange lineGlyphRange,
BOOL *_Nonnull stop) {
NSRange range = [layoutManager characterRangeForGlyphRange:lineGlyphRange
actualGlyphRange:nil];
NSString *renderedString = [textStorage.string substringWithRange:range];
UIFont *font =
[[textStorage attributedSubstringFromRange:range] attribute:NSFontAttributeName
atIndex:0
effectiveRange:nil];
auto rect = facebook::react::Rect{
.origin = facebook::react::Point{.x = usedRect.origin.x, .y = usedRect.origin.y},
.size = facebook::react::Size{
.width = usedRect.size.width, .height = usedRect.size.height}};
CGFloat baseline = [layoutManager locationForGlyphAtIndex:range.location].y;
auto line = LineMeasurement{
std::string([renderedString UTF8String]),
rect,
overallRect.size.height - baseline,
font.capHeight,
baseline,
font.xHeight};
blockParagraphLines->push_back(line);
}];
CGFloat baseline = [layoutManager locationForGlyphAtIndex:range.location].y;
auto line = LineMeasurement{
std::string([renderedString UTF8String]),
rect,
overallRect.size.height - baseline,
font.capHeight,
baseline,
font.xHeight};
blockParagraphLines->push_back(line);
}];
return paragraphLines;
}
@@ -416,19 +418,20 @@ static NSLineBreakMode RCTNSLineBreakModeFromEllipsizeMode(EllipsizeMode ellipsi
atIndex:0
effectiveRange:nil];
frame = {
{glyphRect.origin.x,
glyphRect.origin.y + glyphRect.size.height - attachmentSize.height + font.descender},
attachmentSize};
.origin =
{glyphRect.origin.x,
glyphRect.origin.y + glyphRect.size.height - attachmentSize.height + font.descender},
.size = attachmentSize};
auto rect = facebook::react::Rect{
facebook::react::Point{frame.origin.x, frame.origin.y},
facebook::react::Size{frame.size.width, frame.size.height}};
.origin = facebook::react::Point{.x = frame.origin.x, .y = frame.origin.y},
.size = facebook::react::Size{.width = frame.size.width, .height = frame.size.height}};
attachments.push_back(TextMeasurement::Attachment{.frame = rect, .isClipped = false});
}
}];
return TextMeasurement{{size.width, size.height}, attachments};
return TextMeasurement{.size = {.width = size.width, .height = size.height}, .attachments = attachments};
}
@end
@@ -39,23 +39,27 @@ TextMeasurement TextLayoutManager::measure(
case AttributedStringBox::Mode::Value: {
auto attributedString = ensurePlaceholderIfEmpty_DO_NOT_USE(attributedStringBox.getValue());
measurement = textMeasureCache_.get({attributedString, paragraphAttributes, layoutConstraints}, [&]() {
auto telemetry = TransactionTelemetry::threadLocalTelemetry();
if (telemetry) {
telemetry->willMeasureText();
}
measurement = textMeasureCache_.get(
{.attributedString = attributedString,
.paragraphAttributes = paragraphAttributes,
.layoutConstraints = layoutConstraints},
[&]() {
auto telemetry = TransactionTelemetry::threadLocalTelemetry();
if (telemetry) {
telemetry->willMeasureText();
}
auto measurement = [textLayoutManager measureAttributedString:attributedString
paragraphAttributes:paragraphAttributes
layoutContext:layoutContext
layoutConstraints:layoutConstraints];
auto measurement = [textLayoutManager measureAttributedString:attributedString
paragraphAttributes:paragraphAttributes
layoutContext:layoutContext
layoutConstraints:layoutConstraints];
if (telemetry) {
telemetry->didMeasureText();
}
if (telemetry) {
telemetry->didMeasureText();
}
return measurement;
});
return measurement;
});
break;
}
@@ -96,12 +100,13 @@ LinesMeasurements TextLayoutManager::measureLines(
RCTTextLayoutManager *textLayoutManager = (RCTTextLayoutManager *)unwrapManagedObject(nativeTextLayoutManager_);
auto measurement = lineMeasureCache_.get({attributedString, paragraphAttributes, size}, [&]() {
auto measurement = [textLayoutManager getLinesForAttributedString:attributedString
paragraphAttributes:paragraphAttributes
size:{size.width, size.height}];
return measurement;
});
auto measurement = lineMeasureCache_.get(
{.attributedString = attributedString, .paragraphAttributes = paragraphAttributes, .size = size}, [&]() {
auto measurement = [textLayoutManager getLinesForAttributedString:attributedString
paragraphAttributes:paragraphAttributes
size:{size.width, size.height}];
return measurement;
});
return measurement;
}
@@ -27,8 +27,6 @@ const std::string JS_SAMPLING_TRACK = "JS Sampling";
const int SAMPLING_HZ = 1000;
using perfetto::TrackEvent;
#if defined(__ANDROID__)
std::string getApplicationId() {
pid_t pid = getpid();
@@ -23,8 +23,6 @@ const int SAMPLING_HZ = 100;
int64_t hermesDeltaTime = 0;
using perfetto::TrackEvent;
uint64_t hermesToPerfettoTime(int64_t hermesTs) {
if (hermesDeltaTime == 0) {
hermesDeltaTime = TrackEvent::GetTraceTimeNs() -
@@ -113,7 +111,7 @@ void HermesPerfettoDataSource::OnStart(const StartArgs&) {
"react-native",
perfetto::DynamicString{"Profiling Started"},
getPerfettoWebPerfTrackSync("JS Sampling"),
perfetto::TrackEvent::GetTraceTimeNs());
TrackEvent::GetTraceTimeNs());
}
void HermesPerfettoDataSource::OnFlush(const FlushArgs&) {
@@ -29,7 +29,7 @@ void initializePerfetto() {
args.backends |= perfetto::kSystemBackend;
args.use_monotonic_clock = true;
perfetto::Tracing::Initialize(args);
perfetto::TrackEvent::Register();
TrackEvent::Register();
});
HermesPerfettoDataSource::RegisterDataSource();
@@ -42,7 +42,7 @@ static perfetto::Track createTrack(const std::string& trackName) {
auto track = perfetto::Track(trackId++);
auto desc = track.Serialize();
desc.set_name(trackName);
perfetto::TrackEvent::SetTrackDescriptor(track, desc);
TrackEvent::SetTrackDescriptor(track, desc);
return track;
}

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