Compare commits

..
Author SHA1 Message Date
Simek 04ae39e603 fix C++ in-code docs comments to silence warnings 2025-09-18 10:50:03 +02:00
Alex HuntandFacebook GitHub Bot fae11d58bd Replace trivial uses of string_view (#53775)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53775

A refactor to align our C++ code style within `jsinpector-modern`.

We prefer `std::string` and `const std::string&` everywhere (see [C++ Core Guidelines F.15](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rf-conventional)), except for when we are handing potentially very large strings — in which case we must use `string_view` all the way down.

Changelog: [Internal]

Reviewed By: hoxyq

Differential Revision: D82446939

fbshipit-source-id: 4b1c43068d1339f4b4a4c7eb06b392d0b0f624e1
2025-09-16 03:17:57 -07:00
Alex HuntandFacebook GitHub Bot 6eb456bc4e Fix data race condition in NetworkHandler (#53788)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53788

Fix thread safety issue due to member variable  in `NetworkHandler` singleton without mutex.

Also intend to un-singleton this class in the imminent future.

Changelog: [Internal]

Reviewed By: hoxyq

Differential Revision: D82460574

fbshipit-source-id: c0c614f8f1bb5ffba22872ae5717fbd2ca01f2e9
2025-09-16 03:03:06 -07:00
Nicola CortiandFacebook GitHub Bot 27630d3106 Remove unused --otp property from release infrastructure (#53779)
Summary:
The `--otp` flag is completely unused now, therefore it can be removed.
We don't pass the `NPM_CONFIG_OTP` env variable either as this was done back in the days of CircleCI so I'm cleaning this up.

## Changelog:

[INTERNAL] - Remove unused --otp property from release infrastructure

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

Test Plan: CI

Reviewed By: lunaleaps

Differential Revision: D82453539

Pulled By: cortinico

fbshipit-source-id: 84a6b82a037c754165c21e17976dc534d9a7ba4c
2025-09-16 02:52:58 -07:00
Pieter De BaetsandFacebook GitHub Bot 96c33a8b0b Update ws to 7.5.10 (#53781)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53781

Fixes deprecation warning printed when starting various `js1` tools

Changelog: [Internal]

Reviewed By: robhogan

Differential Revision: D82449982

fbshipit-source-id: 852b5a6980badef146b4e194434f2f9c6dd9a1d5
2025-09-16 02:51:06 -07:00
Zeya PengandFacebook GitHub Bot c9dcd64ed5 Clean up batchingControlledByJS in NativeAnimated kotlin (#53793)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53793

## Changelog:

[Android] [Deprecated] - Clean up batchingControlledByJS in NativeAnimated kotlin

`start/finishOperationBatch` will no longer be called on kotlin NativeAnimated since D78005971 (https://github.com/facebook/react-native/pull/52521), so `batchingControlledByJS` will remain false. Cleaning up some logic and TODO comments there

this feature was added in D23010844

Reviewed By: christophpurrer

Differential Revision: D82461457

fbshipit-source-id: a1208720b83e614c2a5f994ec1a5005189c5f197
2025-09-16 00:44:23 -07:00
generatedunixname537391475639613andFacebook GitHub Bot 15daa27871 xplat/js/react-native-github/packages/react-native/ReactCommon/react/renderer/components/view/LayoutConformanceShadowNode.h (#53772)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/53772

Reviewed By: javache

Differential Revision: D82292073

fbshipit-source-id: 3a3f8e54b4217c8ce9432520e04c4f232b538687
2025-09-15 16:11:00 -07:00
nishan (o^▽^o)andFacebook GitHub Bot b365e26593 feat(iOS) - blur filter using SwiftUI (#52495)
Summary:
As per the discussion on the previous [PR thread](https://github.com/facebook/react-native/pull/52028#issuecomment-2979481948), this PR uses `SwiftUI` to implement blur filter on iOS.

## Approach:

To implement blur filter on iOS, we have two options:

1. Use `CAFilter` (private API, app can get rejected/API can break). Earlier [PR](https://github.com/facebook/react-native/pull/52028) was using that approach. Thanks to Nick for suggesting SwiftUI API.

2. Use `SwiftUI`. Wrap the view in a SwiftUI view and apply [blur](https://developer.apple.com/documentation/swiftui/view/blur(radius:opaque:)). This PR builds on top of that approach. This also enables a way to add `SwiftUI` only features like this one. Additional filters (grayscale, saturate, contrast, hueRotate) can also be added.

There are a few ways we can implement the SwiftUI approach:

1. Create a new `RCTSwiftUIComponentView` -> do style flattening in View -> check if `filter` is present and conditionally render the `RCTSwiftUIComponentView` on iOS, wrap children with a `SwiftUI` view. Tradeoff with this approach is that it adds `StyleSheet.flatten` overhead on JS side.
2. Add a `SwiftUI` container view inside of `RCTViewComponentView`. Tradeoff with this approach is that it complicates `RCTViewComponentView` a bit.

I decided to go with **2** to avoid the flattening tradeoff and try to minimize complicating `RCTViewComponentView`. it only adds the wrapper if it's required and removes if not (in this PR, blur filter style will add the wrapper, it will get removed if blur filter styling gets removed). It uses the existing container view pattern.

## Changelog:
[IOS][ADDED] - Filter blur

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

Test Plan:
Test filter blur example on iOS. SwiftUI view should be added to the hierarchy.

<img src="https://github.com/user-attachments/assets/742539f4-a96d-45f4-94ba-5eb588d0ad5a" width="300px" />

## Aside:

- This PR also adds a new swift podspec. Creating a new podspec felt the right approach as adding swift in existing ones were adding some complexity. But open for changes here. Also, need some eyes on the podspec configs. cc - chrfalch  🙏   this might also affect the SPM migration.
- Unrelated: Existing brightness filter has some inconsistency compared to android and web, it uses [self.layer.opacity](https://github.com/facebook/react-native/blob/6892dde36373bbef2d0afe535ae818b1a7164f08/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm#L1008) so transparent background color do not blend well unless the view has an opacity. One solution would be to calculate true background color by using brightness or else use the `SwiftUI`'s [brightness](https://developer.apple.com/documentation/swiftui/view/brightness(_:)), which would be cleaner imo (tested and it works).

Reviewed By: cipolleschi

Differential Revision: D79666764

Pulled By: joevilches

fbshipit-source-id: 05e43d75ce7b6f25b67b4eed632524a559ea1c2e
2025-09-15 15:04:54 -07:00
generatedunixname537391475639613andFacebook GitHub Bot 7e85653c18 xplat/js/react-native-github/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/internal/PrepareGlogTaskTest.kt (#53750)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/53750

Reviewed By: cortinico

Differential Revision: D82293987

fbshipit-source-id: 46bf93c7b8a2bf48a2246d9f5fc4ab8c1163badf
2025-09-15 13:04:17 -07:00
Ruslan LesiutinandFacebook GitHub Bot 01b4749f6a Emit stashed trace to an active Fusebox client (#53771)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53771

# Changelog: [Internal]

Instead of opening DevTools every time we emit a background trace, we are going to check if there is an active session with Fusebox client and will send it to the first one registered.

Reviewed By: huntie

Differential Revision: D82321146

fbshipit-source-id: 46b4d090ae9a6f8b4fc98181b303ff552c561eb8
2025-09-15 12:45:53 -07:00
Ruslan LesiutinandFacebook GitHub Bot 1b6d3c9ce1 refactor: emit the trace recoding on ReactNativeApplication domain initialization (#53760)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53760

# Changelog: [Internal]

This is a different approach from the one that I've introduced initially in [1].

This saves us from the scenario, where any local session could snatch the stashed trace recording. For example, if some session was created for a Runtime binding right after we've stashed the trace and before initializing real CDP session with the Frontend.

Reviewed By: huntie

Differential Revision: D82316584

fbshipit-source-id: 806a0f6dbdb4e4e928ce33af228cae86d43772e9
2025-09-15 12:45:53 -07:00
generatedunixname1395667395051502andFacebook GitHub Bot fedad125bf Update React Native DevTools binaries
Summary:
Automated update of React Native DevTools binaries
bypass-github-export-checks
Changelog: [Internal]

Reviewed By: motiz88

Differential Revision: D82459089

fbshipit-source-id: 3ccf7a1f07da7e79732c785afda1b938ee585ea6
2025-09-15 11:54:30 -07:00
Pieter De BaetsandFacebook GitHub Bot 64b30a9376 Fix newarch ignoring defaultfonthandler (#53755)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53755

Changelog: [iOS][Fixed] Make `RCTSetDefaultFontHandler` compatible with the new arch, and add a more powerful version as `RCTSetDefaultFontResolver`

Reviewed By: fkgozali

Differential Revision: D82207676

fbshipit-source-id: eeeaf708491de9156ef4f1e045864e4322213902
2025-09-15 11:31:30 -07:00
ismarbesicandFacebook GitHub Bot 07da2ff3e1 feat(ios): support condensed system font on fabric (#52259)
Summary:
This PR adds support for using the condensed system font on iOS when passing "SystemCondensed" as fontFamily. This behavior existed in the old architecture but was never ported to the new one, see [RCTFont.mm](https://github.com/facebook/react-native/blob/main/packages/react-native/React/Views/RCTFont.mm#L434) as reference. Fixes https://github.com/facebook/react-native/issues/52258.

## Changelog:

[IOS] [ADDED] - Add support for condensed system font when using the new react native architecture.

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

Test Plan:
Before:
<img width="275" src="https://github.com/user-attachments/assets/8744a5ae-252c-46db-b5f9-b803f3e1c671" />

After:
<img width="275" src="https://github.com/user-attachments/assets/69ec27a3-5c9a-46e3-a80a-0e02b76d8813" />

Reviewed By: cortinico

Differential Revision: D82208140

Pulled By: javache

fbshipit-source-id: b23a97c94bf45144c3f0860c30e35cae88c7dc2f
2025-09-15 11:31:30 -07:00
Alex HuntandFacebook GitHub Bot 90ac3ac7bd Expose unstable_NativeText and unstable_NativeView components (#53777)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53777

Expose `unstable_NativeText` and `unstable_NativeView` components as root exports of the `react-native` package.

These are exposed as `unstable_` APIs which have no semver guarantee.

**Motivation**

There is significant community interest / dependance on the currently private `TextNativeComponent` and `ViewNativeComponent` deep imports, to access the faster-performing inner versions of these UI components.

Using `<Text>` and `<View>`, while recommended and stable, has led to measurable performance overhead in some apps when compared with these `<Native*>` counterparts.

Notably, these APIs are also referenced by low-level libraries such as React Strict DOM.

I am proposing this change in order to:
- Unblock libraries which safely use these.
- Meet users where they are at.
- Unblock us from enabling the Strict TypeScript API (no deep imports).

References:

- https://github.com/react-native-community/discussions-and-proposals/discussions/893#discussioncomment-13452047
- https://javascript.plainenglish.io/optimizing-text-component-rendering-in-react-native-b9d3565659d9
- https://github.com/search?type=code&q=react-native%2FLibraries%2FText%2FTextNativeComponent

**Ideal future state**

We are exposing these as unstable APIs because they should not be part of React Native's final API. The ideal end state is we improve the regular `<Text>` and `<View>` components to eliminate performance overhead and the need to access any lower level API.

Changelog:
[General][Added] - `unstable_NativeText` and `unstable_NativeView` are now exported from the `react-native` package

Reviewed By: javache

Differential Revision: D81588145

fbshipit-source-id: 2ea9b7f822286de85f49607944c6a484d1fcf242
2025-09-15 10:55:55 -07:00
Alex HuntandFacebook GitHub Bot dba8dbdeeb Implement support for Network trace events (#53761)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53761

Updates `NetworkReporter` and `PerformanceEntryReporter` to populate (minimal) `"ResourceSendRequest"` and `"ResourceFinished"` events when a CDP performance trace is active. This allows the Chrome DevTools Performance panel to display the "Network" track.

**Notes**

- The trace events that Chrome requires need extra fields which aren't present on `PerformanceResourceTiming`, hence the new + optional `devtoolsRequestId`, `requestMethod`, `resourceType` params. We only populate these in debug builds.

**Limitations**

- We emit a *complete trace event set* within `reportResourceTiming`, implementing basic initial support in the Performance panel Network track. This means 1/ either all/no events are sent for a given request (rather than incrementally), 2/ we aren't yet handling failed/cancelled requests in this pipeline.

Changelog: [Internal]

Reviewed By: hoxyq

Differential Revision: D82212362

fbshipit-source-id: 4c6d5d2510cc98ddc819a2778222b835411295c8
2025-09-15 07:45:32 -07:00
Jakub PiaseckiandFacebook GitHub Bot 0caf8e70d5 Add dependency on hermes-compiler (#53773)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53773

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

Reviewed By: cortinico

Differential Revision: D82437752

fbshipit-source-id: 3b2d92b765f3a5ba949363ce7656e936403a1155
2025-09-15 06:16:25 -07:00
Luna WeiandFacebook GitHub Bot 56e5dff73f Hysteresis window for VirtualViewExperimental (#53765)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53765

Changelog: [Internal] Introduce hysteresis window for experimental VirtualView

Reviewed By: yungsters

Differential Revision: D82354142

fbshipit-source-id: 13ec0e3a46930d3bea0ea67060c5f0e1c137dec1
2025-09-13 21:41:49 -07:00
Luna WeiandFacebook GitHub Bot 4f20e4d0fc Subview clipping for VirtualViewExperiment (#53759)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53759

Changelog: [Internal] - Enable subview clipping for experimental version of VirtualView

Reviewed By: mdvacca

Differential Revision: D82313841

fbshipit-source-id: c6726fd5f443a55ec47c93ef13092fe8bb9297e0
2025-09-13 21:41:49 -07:00
Alex HuntandFacebook GitHub Bot 09a7e0a0fc Restore NOT_FOCUSABLE flag on Perf Monitor overlay (#53754)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53754

Fix following D82302063.

Changelog: [Internal]

Reviewed By: hoxyq

Differential Revision: D82311593

fbshipit-source-id: 07305c8d3fdbd9199662e20a813ccfbf46e6491b
2025-09-13 06:23:56 -07:00
David VaccaandFacebook GitHub Bot 4fb42c84d8 Delete ScreenshotTestsManagerModule (#53746)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53746

ScreenshotTestsManagerModule and ReactAppScreenshotTestActivity are not in use anymore, let's delete them

changelog: [internal] internal

Reviewed By: javache

Differential Revision: D82249453

fbshipit-source-id: 73b0f2ef2e9a5370057c07c3bee03f9c0793d61a
2025-09-12 11:43:51 -07:00
generatedunixname89002005287564andFacebook GitHub Bot ebe51d6ce8 Fix CQS signal readability-static-accessed-through-instance in xplat/js/react-native-github/packages (#53756)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/53756

Reviewed By: javache

Differential Revision: D82289100

fbshipit-source-id: 432d9cdf4116aadbd6f21e8fdb994a91a163bfd5
2025-09-12 10:18:49 -07:00
vladandFacebook GitHub Bot 81bbbe3c45 Fix deprecation message (#53751)
Summary:
This pull request fixes a small error in the deprecation message for `ReactContextBaseJavaModule#getCurrentActivity()`, where the reference to `getReactApplicationContext().getCurrentActivity()` contained a syntax error.

## Changelog:

[ANDROID] [FIXED] - Correct deprecation message for `ReactContextBaseJavaModule#getCurrentActivity()`

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

Reviewed By: javache

Differential Revision: D82302032

Pulled By: cortinico

fbshipit-source-id: 130991ef514663223165c30fccb920ce87403148
2025-09-12 09:11:04 -07:00
90 changed files with 1537 additions and 466 deletions
+1 -1
View File
@@ -117,7 +117,7 @@
"temp-dir": "^2.0.0",
"tinybench": "^4.1.0",
"typescript": "5.8.3",
"ws": "^6.2.3"
"ws": "^7.5.10"
},
"resolutions": {
"eslint-plugin-react-hooks": "6.1.0-canary-12bc60f5-20250613",
@@ -1,71 +1,71 @@
#!/usr/bin/env dotslash
// @generated SignedSource<<e93d55b5e28943e44271f5d3738083e0>>
// @generated SignedSource<<9df662721aea6e3774a8677e2a6065e4>>
{
"name": "React Native DevTools",
"platforms": {
"linux-aarch64": {
"size": 116060647,
"size": 116056584,
"hash": "sha256",
"digest": "4352f1c9848ca919101ec628bd08b87a72a828d1ab55fa43a02098329fa452fa",
"digest": "fac3912f10e3c373c874be6c4696f11e05cbaa754c116db6ea72189afae5efe6",
"providers": [
{
"type": "http",
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQM24LW0nPZRk0ypuIG9prz_72YjBJNcVlGSIEpO4zdlLXgw4dFNodH7MKg9eKNTnx7wrVDDBNACrnEPt_OfXOjZyZsV9Oaqu0-vNFRdlEyis4YqmpqGLtz3LvD-9R6fzcWxJI9zrhdPvOvlXP-3Syt1UNITaxXDVqIwAAYpCaAh0oLpupAFCc2yvYw"
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQPdlYV_w4y_wxd5Rs8c_F-soLMbY1zwXJjD-JM4TkOtOELyxZGyreTb6dTehp_X6e3qVFZUT05ETRs0MbvqYr4mqdb6dkG9DqNQEVv3TBoHwl7TYSygtHJEs3gXTAtMLYEKW9xXODJlVF-9II7fdTdHU7x7Pyf6NR6S3nv7sKUVD-zKpxF50L2TwUQ"
}
],
"format": "tar.gz",
"path": "React Native DevTools-linux-arm64/React Native DevTools"
},
"linux-x86_64": {
"size": 115930333,
"size": 115929093,
"hash": "sha256",
"digest": "11c7b07942928a6301b07fbf2bc77ce1229b2a52891f23541cdd9858b5250e64",
"digest": "06bbaeb62ae2e0081d184eba42b9f15be0d0b3f4901142b08a8a1430ff83e722",
"providers": [
{
"type": "http",
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQNDwm7HZRhtNxHqMr1FfSb0afHFGrn1OHxH0gOiggrLrht9QRUgJ3GG5jj7huhQzMRogE-LCMsnxh1ioOZks-YYX4KRt6Kj1-whdWsGFc7lBhPOpk1ssbYFGN1NNyuyFRmH-3nCY3lBC4AmbCUkbDTUeCi9DidCtJeyc73CZJEu7M62rIzxR2yV"
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQPENbrxrg0RF_TiyxSY_YVYqC1UfRKj_bMfKb3qHUsIhBlya8n3FkbfJqTXTNdqL4riFRulXS5ecXZprtvk_9kao-zY59r3kiTRwobzF0jnjM507_9UOnEHWzG5ZJYzQyOtS3kQmT0HwZabVj9qw38OB9mk-MPVCZIPZay2PRnIThBzpKDoOOP9"
}
],
"format": "tar.gz",
"path": "React Native DevTools-linux-x64/React Native DevTools"
},
"macos-aarch64": {
"size": 110891041,
"size": 110891603,
"hash": "sha256",
"digest": "3cbe8b1b3d17e433347f1601435bb9a6cb758528a5c176a66fc52d9977223175",
"digest": "eeb9cc1399c0c38c429848dbf622f1b46e88d7d97788dcdc4c30a9fcce37705c",
"providers": [
{
"type": "http",
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQOmC2cqqSv4OrSJKJroYVg_NE8OE4O73AXqY7wXiYqiWQVkDt0Xnyw3ZeUpQT_Qb0-OoT5F8REKoFrB6eqwat8Ovkyina30peYTTwNUzmwnnGQEg7J0fOHNxLF4dkmU1FagXtsoWgex4dKgsK_VpcMsHj3Vp7diomkYvWBVTf_gPVEseYSN9oKq92qa"
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQN9bd7nbXi-uF_MooJEiUL2jJVifMqgQxZ236aqbSdiJe5Uzjud5ANf0LDAl8GDVVRShd6x4B-gsZ-qRowH0qJikoGatQIkBgyzp4i8ors52etGOIIwdAxdNIng5Vtp441j2_N__btkJqlHcMMbbqvO8fg9oeYTlhMpOx3MLLWXIlG7ix5IFUDiYChf"
}
],
"format": "tar.gz",
"path": "React Native DevTools.app/Contents/MacOS/React Native DevTools"
},
"macos-x86_64": {
"size": 117766158,
"size": 117770388,
"hash": "sha256",
"digest": "6fb79bc2ba3008401b4c9c128248657b95b98581ccde60f8fadb622163779775",
"digest": "a65e446e526502b267cbe6800ae031e4e1b5b0aca21412152a66ffe1d3a29410",
"providers": [
{
"type": "http",
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQMMtGn-YGdfLfTVWC8zbQkQx65Asq6iArKt1t__cjZ8UY_s6-sX5XBHr8k1SaexAO21dFZENQVZ1jW_wn_gJ9ENvosQDG1KfWMViKsHli0xRzZ1HVsgPIj_KVXe907QZwwtJf2XhgH0HT8dfH-AQdDcd0_TB5DFUwOsHzhH0nBrHet7YFkbJtPTaA"
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQN29ukKLZS48QcCU-gms06YFnG-fxxDfrWTup-Z6KoIAP-QEu3sFzrpqeZz4g-jFsh3o-IIoHJsdbu4a2U7ROjPfWGguGJrPK8fdc3iV67Qw1_VAPU13dm0dI1DbSY50ah05wh43jdBG3LGCAYYJ-W8_mZMC3HqM2v-8KVd-DoPT4hOh1s9CCFgEQ"
}
],
"format": "tar.gz",
"path": "React Native DevTools.app/Contents/MacOS/React Native DevTools"
},
"windows-x86_64": {
"size": 125527537,
"size": 125526370,
"hash": "sha256",
"digest": "579a5b0944c51c3b1b541ad5af66c1ffedf93cae2a891ecdf88cb7219fd9b096",
"digest": "26b190c0f85249dee91999e020b8fe7ffd5c007458a2103ed3822558861dbe87",
"providers": [
{
"type": "http",
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQOQ3E8lBXqdVHbDPyVb5AOQMrDWjFrFV8fnLLBsygQvLWdpu6ixyG9PgWdwpi5jM-XcDdCHkhBdhaq-5dwT_tgRWKCAMsEBoAIUk0Xg77mGyHG2VF7bNfQ2qFBMuObrsTmrKy1nJ-UFDDm29pJD4GkFQW5NesiBwndJj8t3B8Ur8cczh_XR8rF5"
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQO0mdIJx1eYiSDJNiAZ2soaeECILayWnvOeiey-fpS4ydDTreAMfwL4QZ5GZo4-AsGwOXCSdF3hBMM2ufnvw6BDFg5UEiTc4DALJu7o6YBBG4wlVZbI-2kkaXd7u8RhBQPjmhsdcX3sDmCGmSr3WK9EkTRKStE2lb6ilOn-969h4dYWekwUUCSX"
}
],
"format": "tar.gz",
+1 -1
View File
@@ -33,7 +33,7 @@
"nullthrows": "^1.1.1",
"open": "^7.0.3",
"serve-static": "^1.16.2",
"ws": "^6.2.3"
"ws": "^7.5.10"
},
"engines": {
"node": ">= 20.19.4"
@@ -98,11 +98,11 @@ class PrepareGlogTaskTest {
val glogThirdPartyJniPath = tempFolder.newFolder("glogpath/jni")
val output = tempFolder.newFolder("output")
val task =
createTestTask<PrepareGlogTask> {
it.glogPath.setFrom(glogpath)
it.glogThirdPartyJniPath.set(glogThirdPartyJniPath)
it.glogVersion.set("1.0.0")
it.outputDir.set(output)
createTestTask<PrepareGlogTask> { task ->
task.glogPath.setFrom(glogpath)
task.glogThirdPartyJniPath.set(glogThirdPartyJniPath)
task.glogVersion.set("1.0.0")
task.outputDir.set(output)
}
File(glogpath, "glog-1.0.0/src/glog.h.in").apply {
parentFile.mkdirs()
@@ -29,6 +29,16 @@ export const Commands: NativeCommands = codegenNativeCommands<NativeCommands>({
supportedCommands: ['hotspotUpdate', 'setPressed'],
});
/**
* `ViewNativeComponent` is an internal React Native host component, and is
* exported to provide lower-level access for libraries.
*
* @warning `<unstable_NativeView>` provides no semver guarantees and is not
* intended to be used in app code. Please use
* [`<View>`](https://reactnative.dev/docs/view) instead.
*/
// Additional note: Our long term plan is to reduce the overhead of the <Text>
// and <View> wrappers so that we no longer have any reason to export these APIs.
export default ViewNativeComponent;
export type ViewNativeComponentType = HostComponent<Props>;
@@ -65,6 +65,16 @@ const virtualTextViewConfig = {
uiViewClassName: 'RCTVirtualText',
};
/**
* `NativeText` is an internal React Native host component, and is exported to
* provide lower-level access for libraries.
*
* @warning `<unstable_NativeText>` provides no semver guarantees and is not
* intended to be used in app code. Please use
* [`<Text>`](https://reactnative.dev/docs/text) instead.
*/
// Additional note: Our long term plan is to reduce the overhead of the <Text>
// and <View> wrappers so that we no longer have any reason to export these APIs.
export const NativeText: HostComponent<NativeTextProps> =
(createReactNativeComponentClass('RCTText', () =>
/* $FlowFixMe[incompatible-type] Natural Inference rollout. See
+17 -1
View File
@@ -68,6 +68,17 @@ let reactOSCompat = RNTarget(
path: "ReactCommon/oscompat"
)
let rctSwiftUI = RNTarget(
name: .rctSwiftUI,
path: "ReactApple/RCTSwiftUI"
)
let rctSwiftUIWrapper = RNTarget(
name: .rctSwiftUIWrapper,
path: "ReactApple/RCTSwiftUIWrapper",
dependencies: [.rctSwiftUI]
)
// React-rendererconsistency.podspec
let reactRendererConsistency = RNTarget(
name: .reactRendererConsistency,
@@ -439,7 +450,7 @@ let reactFabric = RNTarget(
let reactRCTFabric = RNTarget(
name: .reactRCTFabric,
path: "React/Fabric",
dependencies: [.reactNativeDependencies, .reactCore, .reactRCTImage, .yoga, .reactRCTText, .jsi, .reactFabricComponents, .reactGraphics, .reactImageManager, .reactDebug, .reactUtils, .reactPerformanceTimeline, .reactRendererDebug, .reactRendererConsistency, .reactRuntimeScheduler, .reactRCTAnimation, .reactJsInspector, .reactJsInspectorNetwork, .reactJsInspectorTracing, .reactFabric, .reactFabricImage]
dependencies: [.reactNativeDependencies, .reactCore, .reactRCTImage, .yoga, .reactRCTText, .jsi, .reactFabricComponents, .reactGraphics, .reactImageManager, .reactDebug, .reactUtils, .reactPerformanceTimeline, .reactRendererDebug, .reactRendererConsistency, .reactRuntimeScheduler, .reactRCTAnimation, .reactJsInspector, .reactJsInspectorNetwork, .reactJsInspectorTracing, .reactFabric, .reactFabricImage, .rctSwiftUIWrapper]
)
/// React-FabricComponents.podspec
@@ -579,6 +590,8 @@ let targets = [
reactCore,
reactCoreRCTWebsocket,
reactFabric,
rctSwiftUI,
rctSwiftUIWrapper,
reactRCTFabric,
reactFabricComponents,
reactFabricImage,
@@ -728,6 +741,9 @@ extension String {
static let logger = "React-logger"
static let mapbuffer = "React-Mapbuffer"
static let rctSwiftUI = "RCTSwiftUI"
static let rctSwiftUIWrapper = "RCTSwiftUIWrapper"
static let rctDeprecation = "RCT-Deprecation"
static let yoga = "Yoga"
static let reactUtils = "React-utils"
@@ -12,6 +12,7 @@
#import <objc/runtime.h>
#import <ranges>
#import <RCTSwiftUIWrapper/RCTSwiftUIContainerViewWrapper.h>
#import <React/RCTAssert.h>
#import <React/RCTBorderDrawing.h>
#import <React/RCTBoxShadow.h>
@@ -50,6 +51,7 @@ const CGFloat BACKGROUND_COLOR_ZPOSITION = -1024.0f;
UIView *_containerView;
BOOL _useCustomContainerView;
NSMutableSet<NSString *> *_accessibilityOrderNativeIDs;
RCTSwiftUIContainerViewWrapper *_swiftUIWrapper;
}
#ifdef RCT_DYNAMIC_FRAMEWORKS
@@ -576,6 +578,10 @@ const CGFloat BACKGROUND_COLOR_ZPOSITION = -1024.0f;
auto newTransform = _props->resolveTransform(layoutMetrics);
self.layer.transform = RCTCATransform3DFromTransformMatrix(newTransform);
}
if (_swiftUIWrapper != nullptr) {
[_swiftUIWrapper updateLayoutWithBounds:self.bounds];
}
}
- (BOOL)isJSResponder
@@ -793,43 +799,95 @@ static RCTBorderStyle RCTBorderStyleFromOutlineStyle(OutlineStyle outlineStyle)
((!_props->boxShadow.empty() || (clipToPaddingBox && nonZeroBorderWidth)) || _props->outlineWidth != 0);
}
// The view that is used as the receiver for all styling (borders, background,
// etc.). Most of the time, this is just `self`. When a view has a filter like
// `blur` applied, we need to wrap it in a SwiftUI view to render the effect.
// In this case, `effectiveContentView` will be the content view inside the
// SwiftUI wrapper.
- (UIView *)effectiveContentView
{
if (!ReactNativeFeatureFlags::enableSwiftUIBasedFilters()) {
return self;
}
UIView *effectiveContentView = self;
if (self.styleNeedsSwiftUIContainer) {
if (_swiftUIWrapper == nullptr) {
_swiftUIWrapper = [RCTSwiftUIContainerViewWrapper new];
UIView *swiftUIContentView = [[UIView alloc] init];
for (UIView *subview = nullptr in self.subviews) {
[swiftUIContentView addSubview:subview];
}
swiftUIContentView.clipsToBounds = self.clipsToBounds;
self.clipsToBounds = NO;
swiftUIContentView.layer.mask = self.layer.mask;
self.layer.mask = nil;
[_swiftUIWrapper updateContentView:swiftUIContentView];
[_swiftUIWrapper updateLayoutWithBounds:self.bounds];
[self addSubview:_swiftUIWrapper.hostingView];
[self transferVisualPropertiesFromView:self toView:swiftUIContentView];
}
effectiveContentView = _swiftUIWrapper.contentView;
} else {
if (_swiftUIWrapper != nullptr) {
UIView *swiftUIContentView = _swiftUIWrapper.contentView;
for (UIView *subview = nullptr in swiftUIContentView.subviews) {
[self addSubview:subview];
}
self.clipsToBounds = swiftUIContentView.clipsToBounds;
self.layer.mask = swiftUIContentView.layer.mask;
[self transferVisualPropertiesFromView:swiftUIContentView toView:self];
[_swiftUIWrapper.hostingView removeFromSuperview];
_swiftUIWrapper = nil;
}
}
return effectiveContentView;
}
// This UIView is the UIView that holds all subviews. It is sometimes not self
// because we want to render "overflow ink" that extends beyond the bounds of
// the view and is not affected by clipping.
- (UIView *)currentContainerView
{
UIView *effectiveContentView = self.effectiveContentView;
if (_useCustomContainerView) {
if (!_containerView) {
_containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
for (UIView *subview in self.subviews) {
for (UIView *subview = nullptr in effectiveContentView.subviews) {
[_containerView addSubview:subview];
}
_containerView.clipsToBounds = self.clipsToBounds;
self.clipsToBounds = NO;
_containerView.layer.mask = self.layer.mask;
self.layer.mask = nil;
[self addSubview:_containerView];
_containerView.clipsToBounds = effectiveContentView.clipsToBounds;
effectiveContentView.clipsToBounds = NO;
_containerView.layer.mask = effectiveContentView.layer.mask;
effectiveContentView.layer.mask = nil;
[effectiveContentView addSubview:_containerView];
}
return _containerView;
effectiveContentView = _containerView;
} else {
if (_containerView) {
for (UIView *subview in _containerView.subviews) {
[self addSubview:subview];
[effectiveContentView addSubview:subview];
}
self.clipsToBounds = _containerView.clipsToBounds;
self.layer.mask = _containerView.layer.mask;
effectiveContentView.clipsToBounds = _containerView.clipsToBounds;
effectiveContentView.layer.mask = _containerView.layer.mask;
[_containerView removeFromSuperview];
_containerView = nil;
}
return self;
}
return effectiveContentView;
}
- (void)invalidateLayer
{
CALayer *layer = self.layer;
CALayer *layer = self.effectiveContentView.layer;
if (CGSizeEqualToSize(layer.bounds.size, CGSizeZero)) {
return;
@@ -910,7 +968,7 @@ static RCTBorderStyle RCTBorderStyleFromOutlineStyle(OutlineStyle outlineStyle)
if (!_backgroundColorLayer) {
_backgroundColorLayer = [CALayer layer];
_backgroundColorLayer.zPosition = BACKGROUND_COLOR_ZPOSITION;
[self.layer addSublayer:_backgroundColorLayer];
[layer addSublayer:_backgroundColorLayer];
}
[self shapeLayerToMatchView:_backgroundColorLayer borderMetrics:borderMetrics];
_backgroundColorLayer.backgroundColor = backgroundColor.CGColor;
@@ -986,31 +1044,43 @@ static RCTBorderStyle RCTBorderStyleFromOutlineStyle(OutlineStyle outlineStyle)
// filter
[_filterLayer removeFromSuperlayer];
_filterLayer = nil;
if (_swiftUIWrapper != nullptr) {
[_swiftUIWrapper updateBlurRadius:@(0)];
}
self.layer.opacity = (float)_props->opacity;
if (!_props->filter.empty()) {
float multiplicativeBrightness = 1;
bool hasBrightnessFilter = false;
for (const auto &primitive : _props->filter) {
if (std::holds_alternative<Float>(primitive.parameters)) {
if (primitive.type == FilterType::Brightness) {
multiplicativeBrightness *= std::get<Float>(primitive.parameters);
hasBrightnessFilter = true;
} else if (primitive.type == FilterType::Opacity) {
self.layer.opacity *= std::get<Float>(primitive.parameters);
} else if (primitive.type == FilterType::Blur) {
if (_swiftUIWrapper != nullptr) {
Float blurRadius = std::get<Float>(primitive.parameters);
[_swiftUIWrapper updateBlurRadius:@(blurRadius)];
}
}
}
}
_filterLayer = [CALayer layer];
[self shapeLayerToMatchView:_filterLayer borderMetrics:borderMetrics];
_filterLayer.compositingFilter = @"multiplyBlendMode";
_filterLayer.backgroundColor = [UIColor colorWithRed:multiplicativeBrightness
green:multiplicativeBrightness
blue:multiplicativeBrightness
alpha:self.layer.opacity]
.CGColor;
// So that this layer is always above any potential sublayers this view may
// add
_filterLayer.zPosition = CGFLOAT_MAX;
[self.layer addSublayer:_filterLayer];
if (hasBrightnessFilter) {
_filterLayer = [CALayer layer];
[self shapeLayerToMatchView:_filterLayer borderMetrics:borderMetrics];
_filterLayer.compositingFilter = @"multiplyBlendMode";
_filterLayer.backgroundColor = [UIColor colorWithRed:multiplicativeBrightness
green:multiplicativeBrightness
blue:multiplicativeBrightness
alpha:self.layer.opacity]
.CGColor;
// So that this layer is always above any potential sublayers this view may
// add
_filterLayer.zPosition = CGFLOAT_MAX;
[layer addSublayer:_filterLayer];
}
}
// background image
@@ -1025,7 +1095,7 @@ static RCTBorderStyle RCTBorderStyleFromOutlineStyle(OutlineStyle outlineStyle)
[self shapeLayerToMatchView:backgroundImageLayer borderMetrics:borderMetrics];
backgroundImageLayer.masksToBounds = YES;
backgroundImageLayer.zPosition = BACKGROUND_COLOR_ZPOSITION;
[self.layer addSublayer:backgroundImageLayer];
[layer addSublayer:backgroundImageLayer];
[_backgroundImageLayers addObject:backgroundImageLayer];
} else if (std::holds_alternative<RadialGradient>(backgroundImage)) {
const auto &radialGradient = std::get<RadialGradient>(backgroundImage);
@@ -1034,7 +1104,7 @@ static RCTBorderStyle RCTBorderStyleFromOutlineStyle(OutlineStyle outlineStyle)
[self shapeLayerToMatchView:backgroundImageLayer borderMetrics:borderMetrics];
backgroundImageLayer.masksToBounds = YES;
backgroundImageLayer.zPosition = BACKGROUND_COLOR_ZPOSITION;
[self.layer addSublayer:backgroundImageLayer];
[layer addSublayer:backgroundImageLayer];
[_backgroundImageLayers addObject:backgroundImageLayer];
}
}
@@ -1056,7 +1126,7 @@ static RCTBorderStyle RCTBorderStyleFromOutlineStyle(OutlineStyle outlineStyle)
RCTUIEdgeInsetsFromEdgeInsets(borderMetrics.borderWidths),
self.layer.bounds.size);
shadowLayer.zPosition = _borderLayer.zPosition;
[self.layer addSublayer:shadowLayer];
[layer addSublayer:shadowLayer];
[_boxShadowLayers addObject:shadowLayer];
}
}
@@ -1410,6 +1480,66 @@ static NSString *RCTRecursiveAccessibilityLabel(UIView *view)
return RCTNSStringFromString([[self class] componentDescriptorProvider].name);
}
- (BOOL)styleNeedsSwiftUIContainer
{
if (!_props->filter.empty()) {
for (const auto &primitive : _props->filter) {
if (primitive.type == FilterType::Blur) {
return YES;
}
}
}
return NO;
}
- (void)transferVisualPropertiesFromView:(UIView *)sourceView toView:(UIView *)destinationView
{
// shadow
destinationView.layer.shadowColor = sourceView.layer.shadowColor;
sourceView.layer.shadowColor = nil;
destinationView.layer.shadowOffset = sourceView.layer.shadowOffset;
sourceView.layer.shadowOffset = CGSizeZero;
destinationView.layer.shadowOpacity = sourceView.layer.shadowOpacity;
sourceView.layer.shadowOpacity = 0;
destinationView.layer.shadowRadius = sourceView.layer.shadowRadius;
sourceView.layer.shadowRadius = 0;
// background
destinationView.layer.backgroundColor = sourceView.layer.backgroundColor;
sourceView.layer.backgroundColor = nil;
if (_backgroundColorLayer != nullptr) {
[destinationView.layer addSublayer:_backgroundColorLayer];
}
// border
destinationView.layer.borderColor = sourceView.layer.borderColor;
sourceView.layer.borderColor = nil;
destinationView.layer.borderWidth = sourceView.layer.borderWidth;
sourceView.layer.borderWidth = 0;
// corner
destinationView.layer.cornerRadius = sourceView.layer.cornerRadius;
sourceView.layer.cornerRadius = 0;
destinationView.layer.cornerCurve = sourceView.layer.cornerCurve;
// custom layers
if (_borderLayer != nullptr) {
[destinationView.layer addSublayer:_borderLayer];
}
if (_outlineLayer != nullptr) {
[destinationView.layer addSublayer:_outlineLayer];
}
if (_filterLayer != nullptr) {
[destinationView.layer addSublayer:_filterLayer];
}
for (CALayer *layer = nullptr in _backgroundImageLayers) {
[destinationView.layer addSublayer:layer];
}
for (CALayer *layer = nullptr in _boxShadowLayers) {
[destinationView.layer addSublayer:layer];
}
}
@end
#ifdef __cplusplus
@@ -63,6 +63,7 @@ Pod::Spec.new do |s|
s.dependency "Yoga"
s.dependency "React-RCTText"
s.dependency "React-jsi"
s.dependency "RCTSwiftUIWrapper"
add_dependency(s, "React-FabricImage")
add_dependency(s, "React-Fabric", :additional_framework_paths => [
@@ -0,0 +1,16 @@
/*
* 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.
*/
#import <UIKit/UIKit.h>
#import <React/RCTDefines.h>
NS_ASSUME_NONNULL_BEGIN
RCT_EXTERN UIFont *__nullable RCTGetLegacyDefaultFont(CGFloat fontSize, UIFontWeight fontWeight);
NS_ASSUME_NONNULL_END
+3 -1
View File
@@ -17,8 +17,10 @@ typedef CGFloat RCTFontWeight;
* provide a different base font, use this override. The font weight supplied to your
* handler will be one of "ultralight", "thin", "light", "regular", "medium",
* "semibold", "extrabold", "bold", "heavy", or "black".
*
* @deprecated Use RCTSetDefaultFontResolver
*/
RCT_EXTERN void RCTSetDefaultFontHandler(RCTFontHandler handler);
RCT_EXTERN void RCTSetDefaultFontHandler(RCTFontHandler handler) __attribute__((deprecated));
RCT_EXTERN BOOL RCTHasFontHandlerSet(void);
RCT_EXTERN RCTFontWeight RCTGetFontWeight(UIFont *font);
+13 -2
View File
@@ -6,6 +6,8 @@
*/
#import "RCTFont.h"
#import "RCTFont+Private.h"
#import "RCTAssert.h"
#import "RCTLog.h"
@@ -122,6 +124,15 @@ static NSString *FontWeightDescriptionFromUIFontWeight(UIFontWeight fontWeight)
return @"regular";
}
UIFont *RCTGetLegacyDefaultFont(CGFloat size, UIFontWeight fontWeight)
{
if (defaultFontHandler != nil) {
return defaultFontHandler(size, FontWeightDescriptionFromUIFontWeight(fontWeight));
} else {
return nil;
}
}
static UIFont *cachedSystemFont(CGFloat size, RCTFontWeight weight)
{
static NSCache<NSValue *, UIFont *> *fontCache = [NSCache new];
@@ -135,8 +146,8 @@ static UIFont *cachedSystemFont(CGFloat size, RCTFontWeight weight)
NSValue *cacheKey = [[NSValue alloc] initWithBytes:&key objCType:@encode(CacheKey)];
UIFont *font = [fontCache objectForKey:cacheKey];
if (!font) {
if (defaultFontHandler) {
if (font == nil) {
if (defaultFontHandler != nil) {
NSString *fontWeightDescription = FontWeightDescriptionFromUIFontWeight(weight);
font = defaultFontHandler(size, fontWeightDescription);
} else {
@@ -5246,6 +5246,7 @@ public class com/facebook/react/viewmanagers/VirtualViewExperimentalManagerDeleg
public abstract interface class com/facebook/react/viewmanagers/VirtualViewExperimentalManagerInterface : com/facebook/react/uimanager/ViewManagerWithGeneratedInterface {
public abstract fun setInitialHidden (Landroid/view/View;Z)V
public abstract fun setRemoveClippedSubviews (Landroid/view/View;Z)V
public abstract fun setRenderState (Landroid/view/View;I)V
}
@@ -6725,9 +6726,10 @@ public final class com/facebook/react/views/virtual/viewexperimental/ReactVirtua
public fun onLayoutChange (Landroid/view/View;IIIIIIII)V
public fun onModeChange (Lcom/facebook/react/views/virtual/VirtualViewMode;Landroid/graphics/Rect;)V
public synthetic fun recycleView$xplat_js_react_native_github_packages_react_native_ReactAndroid_src_main_java_com_facebook_react_views_view_viewAndroid ()V
public fun updateClippingRect (Ljava/util/Set;)V
}
public final class com/facebook/react/views/virtual/viewexperimental/ReactVirtualViewExperimentalManager : com/facebook/react/uimanager/ViewGroupManager, com/facebook/react/viewmanagers/VirtualViewExperimentalManagerInterface {
public final class com/facebook/react/views/virtual/viewexperimental/ReactVirtualViewExperimentalManager : com/facebook/react/views/view/ReactClippingViewManager, com/facebook/react/viewmanagers/VirtualViewExperimentalManagerInterface {
public static final field Companion Lcom/facebook/react/views/virtual/viewexperimental/ReactVirtualViewExperimentalManager$Companion;
public static final field REACT_CLASS Ljava/lang/String;
public fun <init> ()V
@@ -6739,6 +6741,7 @@ public final class com/facebook/react/views/virtual/viewexperimental/ReactVirtua
public fun setInitialHidden (Lcom/facebook/react/views/virtual/viewexperimental/ReactVirtualViewExperimental;Z)V
public synthetic fun setNativeId (Landroid/view/View;Ljava/lang/String;)V
public fun setNativeId (Lcom/facebook/react/views/virtual/viewexperimental/ReactVirtualViewExperimental;Ljava/lang/String;)V
public synthetic fun setRemoveClippedSubviews (Landroid/view/View;Z)V
public synthetic fun setRenderState (Landroid/view/View;I)V
public fun setRenderState (Lcom/facebook/react/views/virtual/viewexperimental/ReactVirtualViewExperimental;I)V
}
@@ -196,11 +196,9 @@ public class NativeAnimatedModule(reactContext: ReactApplicationContext) :
private val nodesManagerRef = AtomicReference<NativeAnimatedNodesManager?>()
private var batchingControlledByJS = false // TODO T71377544: delete
@Volatile private var currentFrameNumber: Long = 0
@Volatile private var currentFrameNumber: Long = 0 // TODO T71377544: delete
@Volatile private var currentBatchNumber: Long = 0
@Volatile private var currentBatchNumber: Long = 0 // frame number at last operations dispatch
private var initializedForFabric = false
private var initializedForNonFabric = false
@@ -282,22 +280,19 @@ public class NativeAnimatedModule(reactContext: ReactApplicationContext) :
var batchNumber = currentBatchNumber - 1
// TODO T71377544: delete this when the JS method is confirmed safe
if (!batchingControlledByJS) {
// The problem we're trying to solve here: we could be in the middle of queueing
// a batch of related animation operations when Fabric flushes a batch of MountItems.
// It's visually bad if we execute half of the animation ops and then wait another frame
// (or more) to execute the rest.
// See mFrameNumber. If the dispatchedFrameNumber drifts too far - that
// is, if no MountItems are scheduled for a while, which can happen if a tree
// is committed but there are no changes - bring these counts back in sync and
// execute any queued operations. This number is arbitrary, but we want it low
// enough that the user shouldn't be able to see this delay in most cases.
currentFrameNumber++
if ((currentFrameNumber - currentBatchNumber) > 2) {
currentBatchNumber = currentFrameNumber
batchNumber = currentBatchNumber
}
// The problem we're trying to solve here: we could be in the middle of queueing
// a batch of related animation operations when Fabric flushes a batch of MountItems.
// It's visually bad if we execute half of the animation ops and then wait another frame
// (or more) to execute the rest.
// See mFrameNumber. If the dispatchedFrameNumber drifts too far - that
// is, if no MountItems are scheduled for a while, which can happen if a tree
// is committed but there are no changes - bring these counts back in sync and
// execute any queued operations. This number is arbitrary, but we want it low
// enough that the user shouldn't be able to see this delay in most cases.
currentFrameNumber++
if ((currentFrameNumber - currentBatchNumber) > 2) {
currentBatchNumber = currentFrameNumber
batchNumber = currentBatchNumber
}
preOperations.executeBatch(batchNumber, nodesManager)
@@ -484,14 +479,14 @@ public class NativeAnimatedModule(reactContext: ReactApplicationContext) :
}
}
@Suppress("DEPRECATION")
override fun startOperationBatch() {
batchingControlledByJS = true
currentBatchNumber++
// no-op
}
@Suppress("DEPRECATION")
override fun finishOperationBatch() {
batchingControlledByJS = false
currentBatchNumber++
// no-op
}
override fun createAnimatedNode(tagDouble: Double, config: ReadableMap) {
@@ -774,12 +774,8 @@ public class NativeAnimatedNodesManager(
("Looks like animated nodes graph has ${reason}, there are $activeNodesCount but toposort visited only $updatedNodesCount")
)
if (eventListenerInitializedForFabric && cyclesDetected == 0) {
// TODO T71377544: investigate these SoftExceptions and see if we can remove entirely
// or fix the root cause
ReactSoftExceptionLogger.logSoftException(TAG, ReactNoCrashSoftException(ex))
} else if (eventListenerInitializedForFabric) {
// TODO T71377544: investigate these SoftExceptions and see if we can remove entirely
// or fix the root cause
ReactSoftExceptionLogger.logSoftException(TAG, ReactNoCrashSoftException(ex))
} else {
throw ex
@@ -25,7 +25,7 @@ public abstract class ReactContextBaseJavaModule : BaseJavaModule {
* this method whenever you actually need the Activity and make sure to check for `null`.
*/
@Deprecated(
"Deprecated in 0.80.0. Use getReactApplicationContext.getCurrentActivity() instead.",
"Deprecated in 0.80.0. Use getReactApplicationContext().getCurrentActivity() instead.",
ReplaceWith("reactApplicationContext.currentActivity"),
)
protected fun getCurrentActivity(): Activity? {
@@ -387,10 +387,14 @@ public abstract class DevSupportManagerBase(
TracingState.ENABLEDINBACKGROUNDMODE ->
DevOptionHandler {
UiThreadUtil.runOnUiThread {
if (reactInstanceDevHelper is PerfMonitorDevHelper)
reactInstanceDevHelper.inspectorTarget?.pauseAndAnalyzeBackgroundTrace()
if (reactInstanceDevHelper is PerfMonitorDevHelper) {
reactInstanceDevHelper.inspectorTarget?.let {
if (it.pauseAndAnalyzeBackgroundTrace()) {
openDebugger(DebuggerFrontendPanelName.PERFORMANCE.toString())
}
}
}
}
openDebugger(DebuggerFrontendPanelName.PERFORMANCE.toString())
}
TracingState.DISABLED ->
DevOptionHandler {
@@ -17,8 +17,11 @@ internal interface PerfMonitorInspectorTargetBinding {
/** Get the current CDP or background performance tracing state. */
public fun getTracingState(): TracingState
/** Attempt to pause the current background performance trace, and open in DevTools. */
public fun pauseAndAnalyzeBackgroundTrace()
/**
* Attempt to pause the current background performance trace, and open in DevTools. Returns true
* if there is an active session that can display the trace, false otherwise.
*/
public fun pauseAndAnalyzeBackgroundTrace(): Boolean
/** Attempt to start a new background performance trace. */
public fun resumeBackgroundTrace()
@@ -68,8 +68,11 @@ internal class PerfMonitorOverlayManager(
private fun handleRecordingButtonPress() {
when (tracingState) {
TracingState.ENABLEDINBACKGROUNDMODE -> {
devHelper.inspectorTarget?.pauseAndAnalyzeBackgroundTrace()
onRequestOpenDevTools()
devHelper.inspectorTarget?.let {
if (!it.pauseAndAnalyzeBackgroundTrace()) {
onRequestOpenDevTools()
}
}
}
TracingState.DISABLED -> {
devHelper.inspectorTarget?.resumeBackgroundTrace()
@@ -106,7 +106,14 @@ internal class PerfMonitorOverlayView(
containerLayout.addView(statusIndicator)
containerLayout.addView(textContainer)
return createAnchoredDialog(dpToPx(12f), dpToPx(12f)).apply { setContentView(containerLayout) }
val dialog =
createAnchoredDialog(dpToPx(12f), dpToPx(12f)).apply { setContentView(containerLayout) }
dialog.window?.apply {
attributes =
attributes?.apply { flags = flags or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE }
}
return dialog
}
private fun createAnchoredDialog(offsetX: Float, offsetY: Float): Dialog {
@@ -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<<af10f4eea240ae4a228de9bbc4b78b7e>>
* @generated SignedSource<<f089964c958dfcac00f83c3371ccbefc>>
*/
/**
@@ -252,6 +252,12 @@ public object ReactNativeFeatureFlags {
@JvmStatic
public fun enableResourceTimingAPI(): Boolean = accessor.enableResourceTimingAPI()
/**
* When enabled, it will use SwiftUI for filter effects like blur on iOS.
*/
@JvmStatic
public fun enableSwiftUIBasedFilters(): Boolean = accessor.enableSwiftUIBasedFilters()
/**
* Enables View Culling: as soon as a view goes off screen, it can be reused anywhere in the UI and pieced together with other items to create new UI elements.
*/
@@ -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<<0b5ee4e7d8800ea89c97b2501d121b6e>>
* @generated SignedSource<<912dec895495052328e7e52b94a6738a>>
*/
/**
@@ -57,6 +57,7 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
private var enablePreparedTextLayoutCache: Boolean? = null
private var enablePropsUpdateReconciliationAndroidCache: Boolean? = null
private var enableResourceTimingAPICache: Boolean? = null
private var enableSwiftUIBasedFiltersCache: Boolean? = null
private var enableViewCullingCache: Boolean? = null
private var enableViewRecyclingCache: Boolean? = null
private var enableViewRecyclingForImageCache: Boolean? = null
@@ -426,6 +427,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
return cached
}
override fun enableSwiftUIBasedFilters(): Boolean {
var cached = enableSwiftUIBasedFiltersCache
if (cached == null) {
cached = ReactNativeFeatureFlagsCxxInterop.enableSwiftUIBasedFilters()
enableSwiftUIBasedFiltersCache = cached
}
return cached
}
override fun enableViewCulling(): Boolean {
var cached = enableViewCullingCache
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<<5fbbabfffca4f13066ad1ab7f9462c13>>
* @generated SignedSource<<ba1e53d93b9fdaf298a034543bc44a57>>
*/
/**
@@ -102,6 +102,8 @@ public object ReactNativeFeatureFlagsCxxInterop {
@DoNotStrip @JvmStatic public external fun enableResourceTimingAPI(): Boolean
@DoNotStrip @JvmStatic public external fun enableSwiftUIBasedFilters(): Boolean
@DoNotStrip @JvmStatic public external fun enableViewCulling(): Boolean
@DoNotStrip @JvmStatic public external fun enableViewRecycling(): Boolean
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<bcad5baef5d072b71afba69bffabdb41>>
* @generated SignedSource<<7601cbcde75ff19ef0fe67f6faef2549>>
*/
/**
@@ -97,6 +97,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
override fun enableResourceTimingAPI(): Boolean = false
override fun enableSwiftUIBasedFilters(): Boolean = false
override fun enableViewCulling(): Boolean = false
override fun enableViewRecycling(): Boolean = false
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<0733f7a2ea498a0230bcfaa5b15a0b89>>
* @generated SignedSource<<3a13f8e35423b634ed4ef46fbac3c1e9>>
*/
/**
@@ -61,6 +61,7 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
private var enablePreparedTextLayoutCache: Boolean? = null
private var enablePropsUpdateReconciliationAndroidCache: Boolean? = null
private var enableResourceTimingAPICache: Boolean? = null
private var enableSwiftUIBasedFiltersCache: Boolean? = null
private var enableViewCullingCache: Boolean? = null
private var enableViewRecyclingCache: Boolean? = null
private var enableViewRecyclingForImageCache: Boolean? = null
@@ -467,6 +468,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
return cached
}
override fun enableSwiftUIBasedFilters(): Boolean {
var cached = enableSwiftUIBasedFiltersCache
if (cached == null) {
cached = currentProvider.enableSwiftUIBasedFilters()
accessedFeatureFlags.add("enableSwiftUIBasedFilters")
enableSwiftUIBasedFiltersCache = cached
}
return cached
}
override fun enableViewCulling(): Boolean {
var cached = enableViewCullingCache
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<<a51d970a5ea4e74b7871cc9521f9edce>>
* @generated SignedSource<<143b568248e68033efaefc3f178ff6db>>
*/
/**
@@ -97,6 +97,8 @@ public interface ReactNativeFeatureFlagsProvider {
@DoNotStrip public fun enableResourceTimingAPI(): Boolean
@DoNotStrip public fun enableSwiftUIBasedFilters(): Boolean
@DoNotStrip public fun enableViewCulling(): Boolean
@DoNotStrip public fun enableViewRecycling(): Boolean
@@ -55,7 +55,7 @@ public class AndroidInfoModule(reactContext: ReactApplicationContext) :
constants["ServerHost"] =
AndroidInfoHelpers.getServerHost(reactApplicationContext.applicationContext)
}
constants["isTesting"] = "true" == System.getProperty(IS_TESTING) || isRunningScreenshotTest()
constants["isTesting"] = "true" == System.getProperty(IS_TESTING)
val isDisableAnimations = System.getProperty(IS_DISABLE_ANIMATIONS)
if (isDisableAnimations != null) {
constants["isDisableAnimations"] = "true" == isDisableAnimations
@@ -71,15 +71,6 @@ public class AndroidInfoModule(reactContext: ReactApplicationContext) :
override fun invalidate() {}
private fun isRunningScreenshotTest(): Boolean {
return try {
Class.forName("com.facebook.testing.react.screenshots.ReactAppScreenshotTestActivity")
true
} catch (ignored: ClassNotFoundException) {
false
}
}
public companion object {
public const val NAME: String = NativePlatformConstantsAndroidSpec.NAME
private const val IS_TESTING = "IS_TESTING"
@@ -37,7 +37,7 @@ internal class ReactHostInspectorTarget(reactHostImpl: ReactHostImpl) :
external fun startBackgroundTrace(): Boolean
external fun stopAndStashBackgroundTrace()
external fun stopAndMaybeEmitBackgroundTrace(): Boolean
external fun stopAndDiscardBackgroundTrace()
@@ -51,11 +51,13 @@ internal class ReactHostInspectorTarget(reactHostImpl: ReactHostImpl) :
perfMonitorListeners.add(listener)
}
override fun pauseAndAnalyzeBackgroundTrace() {
stopAndStashBackgroundTrace()
override fun pauseAndAnalyzeBackgroundTrace(): Boolean {
val emitted = stopAndMaybeEmitBackgroundTrace()
perfMonitorListeners.forEach { listener ->
listener.onRecordingStateChanged(TracingState.DISABLED)
}
return emitted
}
override fun resumeBackgroundTrace() {
@@ -50,11 +50,13 @@ private fun rectsOverlap(rect1: Rect, rect2: Rect): Boolean {
internal class VirtualViewContainerState {
private val prerenderRatio: Double = ReactNativeFeatureFlags.virtualViewPrerenderRatio()
private val hysteresisRatio: Double = ReactNativeFeatureFlags.virtualViewHysteresisRatio()
private val virtualViews: MutableSet<VirtualView> = mutableSetOf()
private val emptyRect: Rect = Rect()
private val visibleRect: Rect = Rect()
private val prerenderRect: Rect = Rect()
private val hysteresisRect: Rect = Rect()
private val onWindowFocusChangeListener =
if (ReactNativeFeatureFlags.enableVirtualViewWindowFocusDetection()) {
ViewTreeObserver.OnWindowFocusChangeListener {
@@ -119,11 +121,12 @@ internal class VirtualViewContainerState {
(-prerenderRect.height() * prerenderRatio).toInt(),
)
val virtualViewsIt = if (virtualView != null) listOf(virtualView) else virtualViews
val virtualViewsIt =
if (virtualView != null) listOf(virtualView) else virtualViews.toMutableSet()
virtualViewsIt.forEach { vv ->
val rect = vv.containerRelativeRect
var mode = VirtualViewMode.Hidden
var mode: VirtualViewMode? = VirtualViewMode.Hidden
var thresholdRect = emptyRect
when {
rectsOverlap(rect, visibleRect) -> {
@@ -142,14 +145,29 @@ internal class VirtualViewContainerState {
mode = VirtualViewMode.Prerender
thresholdRect = prerenderRect
}
else -> {}
else -> {
if (hysteresisRatio > 0.0) {
hysteresisRect.set(prerenderRect)
hysteresisRect.inset(
(-visibleRect.width() * hysteresisRatio).toInt(),
(-visibleRect.height() * hysteresisRatio).toInt(),
)
if (rectsOverlap(rect, hysteresisRect)) {
mode = null
}
}
}
}
debugLog(
"updateModes",
{ "virtualView=${vv.virtualViewID} mode=$mode rect=$rect thresholdRect=$thresholdRect" },
)
vv.onModeChange(mode, thresholdRect)
if (mode != null) {
vv.onModeChange(mode, thresholdRect)
debugLog(
"updateModes",
{
"virtualView=${vv.virtualViewID} mode=$mode rect=$rect thresholdRect=$thresholdRect"
},
)
}
}
}
}
@@ -16,9 +16,11 @@ import com.facebook.common.logging.FLog
import com.facebook.react.R
import com.facebook.react.common.build.ReactBuildConfig
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags
import com.facebook.react.uimanager.ReactClippingViewGroup
import com.facebook.react.uimanager.ReactRoot
import com.facebook.react.views.scroll.VirtualView
import com.facebook.react.views.scroll.VirtualViewContainer
import com.facebook.react.views.scroll.debugLog
import com.facebook.react.views.view.ReactViewGroup
import com.facebook.react.views.virtual.VirtualViewMode
import com.facebook.react.views.virtual.VirtualViewModeChangeEmitter
@@ -34,6 +36,7 @@ public class ReactVirtualViewExperimental(context: Context) :
private var scrollView: VirtualViewContainer? = null
private val lastContainerRelativeRect: Rect = Rect()
private val lastClippingRect: Rect = Rect()
override val containerRelativeRect: Rect = Rect()
private var offsetX: Int = 0
private var offsetY: Int = 0
@@ -120,6 +123,7 @@ public class ReactVirtualViewExperimental(context: Context) :
modeChangeEmitter = null
hadLayout = false
lastContainerRelativeRect.setEmpty()
lastClippingRect.setEmpty()
containerRelativeRect.setEmpty()
}
@@ -132,7 +136,12 @@ public class ReactVirtualViewExperimental(context: Context) :
modeChangeEmitter ?: return
scrollView ?: return
if (newMode == VirtualViewMode.Visible) {
updateClippingRect(null)
}
if (newMode == mode) {
debugLog("onModeChange") { "no change $newMode" }
return
}
@@ -141,6 +150,10 @@ public class ReactVirtualViewExperimental(context: Context) :
debugLog("onModeChange") { "$oldMode->$newMode" }
if (oldMode == VirtualViewMode.Visible) {
updateClippingRect(null)
}
when (newMode) {
VirtualViewMode.Visible -> {
if (renderState == VirtualViewRenderState.Unknown) {
@@ -187,6 +200,37 @@ public class ReactVirtualViewExperimental(context: Context) :
}
}
// Note: We co-opt subview clipping on ReactVirtualView by returning the
// clipping rect of the ScrollView. This means we clip the children of ReactVirtualView
// when they are out of the viewport, but not ReactVirtualView itself.
override fun updateClippingRect(excludedViews: Set<Int>?) {
if (!_removeClippedSubviews) {
return
}
// If no ScrollView, or ScrollView has disabled removeClippedSubviews, use default behavior
if (
scrollView == null ||
!((scrollView as ReactClippingViewGroup)?.removeClippedSubviews ?: false)
) {
super.updateClippingRect(excludedViews)
return
}
val clippingRect = checkNotNull(clippingRect)
(scrollView as ReactClippingViewGroup).getClippingRect(clippingRect)
clippingRect.intersect(containerRelativeRect)
clippingRect.offset(-containerRelativeRect.left, -containerRelativeRect.top)
if (lastClippingRect == clippingRect) {
return
}
updateClippingToRect(clippingRect, excludedViews)
lastClippingRect.set(clippingRect)
}
private fun updateParentOffset() {
val virtualViewScrollView = scrollView ?: return
offsetX = 0
@@ -212,8 +256,11 @@ public class ReactVirtualViewExperimental(context: Context) :
debugLog("reportRectChangeToContainer") { "no rect change $containerRelativeRect" }
return
}
scrollView?.virtualViewContainerState?.onChange(this)
lastContainerRelativeRect.set(containerRelativeRect)
if (scrollView != null) {
scrollView?.virtualViewContainerState?.onChange(this)
lastContainerRelativeRect.set(containerRelativeRect)
}
}
private fun getScrollView(): VirtualViewContainer? = traverseParentStack(true)
@@ -13,12 +13,12 @@ import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags
import com.facebook.react.module.annotations.ReactModule
import com.facebook.react.uimanager.ThemedReactContext
import com.facebook.react.uimanager.UIManagerHelper
import com.facebook.react.uimanager.ViewGroupManager
import com.facebook.react.uimanager.ViewManagerDelegate
import com.facebook.react.uimanager.annotations.ReactProp
import com.facebook.react.uimanager.events.EventDispatcher
import com.facebook.react.viewmanagers.VirtualViewExperimentalManagerDelegate
import com.facebook.react.viewmanagers.VirtualViewExperimentalManagerInterface
import com.facebook.react.views.view.ReactClippingViewManager
import com.facebook.react.views.virtual.VirtualViewMode
import com.facebook.react.views.virtual.VirtualViewModeChangeEmitter
import com.facebook.react.views.virtual.VirtualViewModeChangeEvent
@@ -26,7 +26,7 @@ import com.facebook.react.views.virtual.VirtualViewRenderState
@ReactModule(name = ReactVirtualViewExperimentalManager.REACT_CLASS)
public class ReactVirtualViewExperimentalManager :
ViewGroupManager<ReactVirtualViewExperimental>(),
ReactClippingViewManager<ReactVirtualViewExperimental>(),
VirtualViewExperimentalManagerInterface<ReactVirtualViewExperimental> {
private val _delegate = VirtualViewExperimentalManagerDelegate(this)
@@ -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<<b3357ac501bc00f026a3a7ed90c83ba3>>
* @generated SignedSource<<92c9aa29df580c6d12faa14e60b00e4f>>
*/
/**
@@ -261,6 +261,12 @@ class ReactNativeFeatureFlagsJavaProvider
return method(javaProvider_);
}
bool enableSwiftUIBasedFilters() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableSwiftUIBasedFilters");
return method(javaProvider_);
}
bool enableViewCulling() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableViewCulling");
@@ -660,6 +666,11 @@ bool JReactNativeFeatureFlagsCxxInterop::enableResourceTimingAPI(
return ReactNativeFeatureFlags::enableResourceTimingAPI();
}
bool JReactNativeFeatureFlagsCxxInterop::enableSwiftUIBasedFilters(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::enableSwiftUIBasedFilters();
}
bool JReactNativeFeatureFlagsCxxInterop::enableViewCulling(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::enableViewCulling();
@@ -977,6 +988,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
makeNativeMethod(
"enableResourceTimingAPI",
JReactNativeFeatureFlagsCxxInterop::enableResourceTimingAPI),
makeNativeMethod(
"enableSwiftUIBasedFilters",
JReactNativeFeatureFlagsCxxInterop::enableSwiftUIBasedFilters),
makeNativeMethod(
"enableViewCulling",
JReactNativeFeatureFlagsCxxInterop::enableViewCulling),
@@ -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<<2c969005f4c7bb24f98bf4e3ed3dc0e9>>
* @generated SignedSource<<124d1378990fdd09a4d97f9103f81a6a>>
*/
/**
@@ -141,6 +141,9 @@ class JReactNativeFeatureFlagsCxxInterop
static bool enableResourceTimingAPI(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static bool enableSwiftUIBasedFilters(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static bool enableViewCulling(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
@@ -157,9 +157,16 @@ tracing::TraceRecordingState JReactHostInspectorTarget::stopTracing() {
}
}
void JReactHostInspectorTarget::stopAndStashBackgroundTrace() {
jboolean JReactHostInspectorTarget::stopAndMaybeEmitBackgroundTrace() {
auto capturedTrace = inspectorTarget_->stopTracing();
if (inspectorTarget_->hasActiveSessionWithFuseboxClient()) {
inspectorTarget_->emitTraceRecordingForFirstFuseboxClient(
std::move(capturedTrace));
return jboolean(true);
}
stashTraceRecordingState(std::move(capturedTrace));
return jboolean(false);
}
void JReactHostInspectorTarget::stopAndDiscardBackgroundTrace() {
@@ -188,8 +195,8 @@ void JReactHostInspectorTarget::registerNatives() {
"startBackgroundTrace",
JReactHostInspectorTarget::startBackgroundTrace),
makeNativeMethod(
"stopAndStashBackgroundTrace",
JReactHostInspectorTarget::stopAndStashBackgroundTrace),
"stopAndMaybeEmitBackgroundTrace",
JReactHostInspectorTarget::stopAndMaybeEmitBackgroundTrace),
makeNativeMethod(
"stopAndDiscardBackgroundTrace",
JReactHostInspectorTarget::stopAndDiscardBackgroundTrace),
@@ -82,17 +82,6 @@ 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();
/**
* Get the state of the background trace: running, stopped, or disabled
* Background tracing will be disabled if there is no metro connection or if
@@ -101,6 +90,20 @@ class JReactHostInspectorTarget
* \return the background trace state
*/
jint tracingState();
/**
* Starts a background trace recording for this HostTarget.
*
* \return false if already tracing, true otherwise.
*/
bool startBackgroundTrace();
/**
* Stops previously started trace recording and:
* - If there is an active CDP session with Fusebox client enabled, emits the
* trace and returns true.
* - Otherwise, stashes the captured trace, that will be emitted when the CDP
* session is initialized. Returns false.
*/
jboolean stopAndMaybeEmitBackgroundTrace();
/**
* Stops previously started trace recording and discards the captured trace.
*/
@@ -0,0 +1,39 @@
# 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.
require "json"
package = JSON.parse(File.read(File.join(__dir__, "..", "..", "package.json")))
version = package['version']
source = { :git => 'https://github.com/facebook/react-native.git' }
if version == '1000.0.0'
# This is an unpublished version, use the latest commit hash of the react-native repo, which we're presumably in.
source[:commit] = `git rev-parse HEAD`.strip if system("git rev-parse --git-dir > /dev/null 2>&1")
else
source[:tag] = "v#{version}"
end
Pod::Spec.new do |s|
s.name = "RCTSwiftUI"
s.version = version
s.summary = "Swift utilities for React Native."
s.homepage = "https://reactnative.dev/"
s.license = package["license"]
s.author = "Meta Platforms, Inc. and its affiliates"
s.platforms = min_supported_versions
s.source = source
s.source_files = "*.{h,m,swift}"
s.public_header_files = "*.h"
s.module_name = "RCTSwiftUI"
s.header_dir = "RCTSwiftUI"
# Swift-specific configuration
s.pod_target_xcconfig = {
"SWIFT_VERSION" => "5.0",
"DEFINES_MODULE" => "YES",
}
end
@@ -0,0 +1,76 @@
/*
* 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.
*/
import SwiftUI
import UIKit
@MainActor @objc public class RCTSwiftUIContainerView: NSObject {
private var containerViewModel = ContainerViewModel()
private var hostingController: UIHostingController<SwiftUIContainerView>?
@objc public override init() {
super.init()
hostingController = UIHostingController(rootView: SwiftUIContainerView(viewModel: containerViewModel))
guard let view = hostingController?.view else {
return
}
view.backgroundColor = .clear
}
@objc public func updateContentView(_ view: UIView) {
containerViewModel.contentView = view
}
@objc public func hostingView() -> UIView? {
return hostingController?.view
}
@objc public func contentView() -> UIView? {
return containerViewModel.contentView
}
@objc public func updateBlurRadius(_ radius: NSNumber) {
let blurRadius = CGFloat(radius.floatValue)
containerViewModel.blurRadius = blurRadius
}
@objc public func updateLayout(withBounds bounds: CGRect) {
hostingController?.view.frame = bounds
containerViewModel.contentView?.frame = bounds
}
@objc public func resetStyles() {
containerViewModel.blurRadius = 0
}
}
class ContainerViewModel: ObservableObject {
@Published var blurRadius: CGFloat = 0
@Published var contentView: UIView?
}
struct SwiftUIContainerView: View {
@ObservedObject var viewModel: ContainerViewModel
var body: some View {
if let contentView = viewModel.contentView {
UIViewWrapper(view: contentView)
.blur(radius: viewModel.blurRadius)
}
}
}
struct UIViewWrapper: UIViewRepresentable {
let view: UIView
func makeUIView(context: Context) -> UIView {
return view
}
func updateUIView(_ uiView: UIView, context: Context) {
}
}
@@ -0,0 +1,24 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface RCTSwiftUIContainerViewWrapper : NSObject
- (UIView *_Nullable)contentView;
- (void)updateBlurRadius:(NSNumber *)radius;
- (void)updateContentView:(UIView *)view;
- (UIView *_Nullable)hostingView;
- (void)resetStyles;
- (void)updateLayoutWithBounds:(CGRect)bounds;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,56 @@
/*
* 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.
*/
#import "RCTSwiftUIContainerViewWrapper.h"
@import RCTSwiftUI;
@interface RCTSwiftUIContainerViewWrapper ()
@property (nonatomic, strong) RCTSwiftUIContainerView *swiftContainerView;
@end
@implementation RCTSwiftUIContainerViewWrapper
- (instancetype)init
{
if (self = [super init]) {
_swiftContainerView = [RCTSwiftUIContainerView new];
}
return self;
}
- (UIView *_Nullable)contentView
{
return [self.swiftContainerView contentView];
}
- (UIView *_Nullable)hostingView
{
return [self.swiftContainerView hostingView];
}
- (void)resetStyles
{
[self.swiftContainerView resetStyles];
}
- (void)updateContentView:(UIView *)view
{
return [self.swiftContainerView updateContentView:view];
}
- (void)updateBlurRadius:(NSNumber *)radius
{
[self.swiftContainerView updateBlurRadius:radius];
}
- (void)updateLayoutWithBounds:(CGRect)bounds
{
[self.swiftContainerView updateLayoutWithBounds:bounds];
}
@end
@@ -0,0 +1,38 @@
# 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.
require "json"
package = JSON.parse(File.read(File.join(__dir__, "..", "..", "package.json")))
version = package['version']
source = { :git => 'https://github.com/facebook/react-native.git' }
if version == '1000.0.0'
# This is an unpublished version, use the latest commit hash of the react-native repo, which we're presumably in.
source[:commit] = `git rev-parse HEAD`.strip if system("git rev-parse --git-dir > /dev/null 2>&1")
else
source[:tag] = "v#{version}"
end
Pod::Spec.new do |s|
s.name = "RCTSwiftUIWrapper"
s.version = version
s.summary = "Swift utilities for React Native."
s.homepage = "https://reactnative.dev/"
s.license = package["license"]
s.author = "Meta Platforms, Inc. and its affiliates"
s.platforms = min_supported_versions
s.source = source
s.source_files = "*.{h,m}"
s.public_header_files = "*.h"
s.module_name = "RCTSwiftUIWrapper"
s.header_dir = "RCTSwiftUIWrapper"
s.dependency "RCTSwiftUI"
s.pod_target_xcconfig = {
"SWIFT_VERSION" => "5.0",
}
end
@@ -41,18 +41,14 @@ class HostAgent::Impl final {
HostTargetController& targetController,
HostTargetMetadata hostMetadata,
SessionState& sessionState,
VoidExecutor executor,
std::optional<tracing::TraceRecordingState> traceRecordingToEmit)
VoidExecutor executor)
: frontendChannel_(frontendChannel),
targetController_(targetController),
hostMetadata_(std::move(hostMetadata)),
sessionState_(sessionState),
networkIOAgent_(NetworkIOAgent(frontendChannel, std::move(executor))),
tracingAgent_(TracingAgent(
frontendChannel,
sessionState,
targetController,
std::move(traceRecordingToEmit))) {}
tracingAgent_(
TracingAgent(frontendChannel, sessionState, targetController)) {}
~Impl() {
if (isPausedInDebuggerOverlayVisible_) {
@@ -201,6 +197,14 @@ class HostAgent::Impl final {
"ReactNativeApplication.metadataUpdated",
createHostMetadataPayload(hostMetadata_)));
auto stashedTraceRecording =
targetController_.getDelegate()
.unstable_getTraceRecordingThatWillBeEmittedOnInitialization();
if (stashedTraceRecording.has_value()) {
tracingAgent_.emitExternalTraceRecording(
std::move(stashedTraceRecording.value()));
}
return {
.isFinishedHandlingRequest = true,
.shouldSendOKResponse = true,
@@ -336,12 +340,24 @@ class HostAgent::Impl final {
}
}
bool hasFuseboxClientConnected() const {
return fuseboxClientType_ == FuseboxClientType::Fusebox;
}
void emitExternalTraceRecording(
tracing::TraceRecordingState traceRecording) const {
assert(
hasFuseboxClientConnected() &&
"Attempted to emit a trace recording to a non-Fusebox client");
tracingAgent_.emitExternalTraceRecording(std::move(traceRecording));
}
private:
enum class FuseboxClientType { Unknown, Fusebox, NonFusebox };
/**
* Send a simple Log.entryAdded notification with the given
* \param text. You must ensure that the frontend has enabled Log
* \param text You must ensure that the frontend has enabled Log
* notifications (using Log.enable) prior to calling this function. In Chrome
* DevTools, the message will appear in the Console tab along with regular
* console messages. The difference between Log.entryAdded and
@@ -432,11 +448,15 @@ class HostAgent::Impl final {
HostTargetController& targetController,
HostTargetMetadata hostMetadata,
SessionState& sessionState,
VoidExecutor executor,
std::optional<tracing::TraceRecordingState> traceRecordingToEmit) {}
VoidExecutor executor) {}
void handleRequest(const cdp::PreparsedRequest& req) {}
void setCurrentInstanceAgent(std::shared_ptr<InstanceAgent> agent) {}
bool hasFuseboxClientConnected() const {
return false;
}
void emitExternalTraceRecording(tracing::TraceRecordingState traceRecording) {
}
};
#endif // REACT_NATIVE_DEBUGGER_ENABLED
@@ -446,16 +466,14 @@ HostAgent::HostAgent(
HostTargetController& targetController,
HostTargetMetadata hostMetadata,
SessionState& sessionState,
VoidExecutor executor,
std::optional<tracing::TraceRecordingState> traceRecordingToEmit)
VoidExecutor executor)
: impl_(std::make_unique<Impl>(
*this,
frontendChannel,
targetController,
std::move(hostMetadata),
sessionState,
std::move(executor),
std::move(traceRecordingToEmit))) {}
std::move(executor))) {}
HostAgent::~HostAgent() = default;
@@ -468,6 +486,15 @@ void HostAgent::setCurrentInstanceAgent(
impl_->setCurrentInstanceAgent(std::move(instanceAgent));
}
bool HostAgent::hasFuseboxClientConnected() const {
return impl_->hasFuseboxClientConnected();
}
void HostAgent::emitExternalTraceRecording(
tracing::TraceRecordingState traceRecording) const {
impl_->emitExternalTraceRecording(std::move(traceRecording));
}
#pragma mark - Tracing
HostTracingAgent::HostTracingAgent(tracing::TraceRecordingState& state)
@@ -36,16 +36,13 @@ 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,
std::optional<tracing::TraceRecordingState> traceRecordingToEmit);
VoidExecutor executor);
HostAgent(const HostAgent&) = delete;
HostAgent(HostAgent&&) = delete;
@@ -69,6 +66,20 @@ class HostAgent final {
*/
void setCurrentInstanceAgent(std::shared_ptr<InstanceAgent> agent);
/**
* Returns whether this HostAgent is part of the session that has an active
* Fusebox client connecte, i.e. with Chrome DevTools Frontend fork for React
* Native.
*/
bool hasFuseboxClientConnected() const;
/**
* Emits the trace recording that was captured externally, not via the
* CDP-initiated request.
*/
void emitExternalTraceRecording(
tracing::TraceRecordingState traceRecording) const;
private:
// We use the private implementation idiom to ensure this class has the same
// layout regardless of whether REACT_NATIVE_DEBUGGER_ENABLED is defined. The
@@ -34,8 +34,7 @@ class HostTargetSession {
std::unique_ptr<IRemoteConnection> remote,
HostTargetController& targetController,
HostTargetMetadata hostMetadata,
VoidExecutor executor,
std::optional<tracing::TraceRecordingState> traceRecordingToEmit)
VoidExecutor executor)
: remote_(std::make_shared<RAIIRemoteConnection>(std::move(remote))),
frontendChannel_(
[remoteWeak = std::weak_ptr(remote_)](std::string_view message) {
@@ -48,8 +47,7 @@ class HostTargetSession {
targetController,
std::move(hostMetadata),
state_,
std::move(executor),
std::move(traceRecordingToEmit)) {}
std::move(executor)) {}
/**
* Called by CallbackLocalConnection to send a message to this Session's
@@ -103,6 +101,19 @@ class HostTargetSession {
}
}
/**
* Returns whether the ReactNativeApplication CDP domain is enabled.
*
* Chrome DevTools Frontend enables this domain as a client.
*/
bool hasFuseboxClient() const {
return hostAgent_.hasFuseboxClientConnected();
}
void emitTraceRecording(tracing::TraceRecordingState traceRecording) const {
hostAgent_.emitExternalTraceRecording(std::move(traceRecording));
}
private:
// Owned by this instance, but shared (weakly) with the frontend channel
std::shared_ptr<RAIIRemoteConnection> remote_;
@@ -205,8 +216,7 @@ std::unique_ptr<ILocalConnection> HostTarget::connect(
std::move(connectionToFrontend),
controller_,
delegate_.getMetadata(),
makeVoidExecutor(executorFromThis()),
delegate_.unstable_getTraceRecordingThatWillBeEmittedOnInitialization());
makeVoidExecutor(executorFromThis()));
session->setCurrentInstance(currentInstance_.get());
sessions_.insert(std::weak_ptr(session));
return std::make_unique<CallbackLocalConnection>(
@@ -347,4 +357,32 @@ folly::dynamic createHostMetadataPayload(const HostTargetMetadata& metadata) {
return result;
}
bool HostTarget::hasActiveSessionWithFuseboxClient() const {
bool hasActiveFuseboxSession = false;
sessions_.forEach([&](HostTargetSession& session) {
hasActiveFuseboxSession |= session.hasFuseboxClient();
});
return hasActiveFuseboxSession;
}
void HostTarget::emitTraceRecordingForFirstFuseboxClient(
tracing::TraceRecordingState traceRecording) const {
bool emitted = false;
sessions_.forEach([&](HostTargetSession& session) {
if (emitted) {
/**
* TraceRecordingState object is not copiable for performance reasons,
* because it could contain large Runtime sampling profile object.
*
* This approach would not work with multi-client debugger setup.
*/
return;
}
if (session.hasFuseboxClient()) {
session.emitTraceRecording(std::move(traceRecording));
emitted = true;
}
});
}
} // namespace facebook::react::jsinspector_modern
@@ -297,6 +297,21 @@ class JSINSPECTOR_EXPORT HostTarget
*/
tracing::TracingState tracingState() const;
/**
* Returns whether there is an active session with the Fusebox client, i.e.
* with Chrome DevTools Frontend fork for React Native.
*/
bool hasActiveSessionWithFuseboxClient() const;
/**
* Emits the trace recording for the first active session with the Fusebox
* client.
*
* @see \c hasActiveFrontendSession
*/
void emitTraceRecordingForFirstFuseboxClient(
tracing::TraceRecordingState traceRecording) const;
private:
/**
* Constructs a new HostTarget.
@@ -38,17 +38,10 @@ const uint16_t PROFILE_TRACE_EVENT_CHUNK_SIZE = 1;
TracingAgent::TracingAgent(
FrontendChannel frontendChannel,
SessionState& sessionState,
HostTargetController& hostTargetController,
std::optional<tracing::TraceRecordingState> traceRecordingToEmit)
HostTargetController& hostTargetController)
: frontendChannel_(std::move(frontendChannel)),
sessionState_(sessionState),
hostTargetController_(hostTargetController) {
if (traceRecordingToEmit.has_value()) {
frontendChannel_(
cdp::jsonNotification("ReactNativeApplication.traceRequested"));
emitTraceRecording(std::move(traceRecordingToEmit.value()));
}
}
hostTargetController_(hostTargetController) {}
TracingAgent::~TracingAgent() {
// Agents are owned by the session. If the agent is destroyed, it means that
@@ -100,15 +93,22 @@ bool TracingAgent::handleRequest(const cdp::PreparsedRequest& req) {
return false;
}
void TracingAgent::emitExternalTraceRecording(
tracing::TraceRecordingState traceRecording) const {
frontendChannel_(
cdp::jsonNotification("ReactNativeApplication.traceRequested"));
emitTraceRecording(std::move(traceRecording));
}
void TracingAgent::emitTraceRecording(
tracing::TraceRecordingState state) const {
tracing::TraceRecordingState traceRecording) 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),
std::move(traceRecording),
dataCollectedCallback,
TRACE_EVENT_CHUNK_SIZE,
PROFILE_TRACE_EVENT_CHUNK_SIZE);
@@ -28,14 +28,11 @@ class TracingAgent {
* \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,
std::optional<tracing::TraceRecordingState> traceRecordingToEmit);
HostTargetController& hostTargetController);
~TracingAgent();
@@ -46,6 +43,12 @@ class TracingAgent {
*/
bool handleRequest(const cdp::PreparsedRequest& req);
/**
* Emits the Trace Recording that was stashed externally by the HostTarget.
*/
void emitExternalTraceRecording(
tracing::TraceRecordingState traceRecording) const;
private:
/**
* A channel used to send responses and events to the frontend.
@@ -60,7 +63,7 @@ class TracingAgent {
* 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;
void emitTraceRecording(tracing::TraceRecordingState traceRecording) const;
};
} // namespace facebook::react::jsinspector_modern
@@ -49,7 +49,7 @@ std::string jsonResult(RequestId id, const folly::dynamic& result) {
}
std::string jsonNotification(
std::string_view method,
const std::string& method,
std::optional<folly::dynamic> params) {
auto dynamicNotification = folly::dynamic::object("method", method);
if (params) {
@@ -60,7 +60,7 @@ std::string jsonNotification(
std::string jsonRequest(
RequestId id,
std::string_view method,
const std::string& method,
std::optional<folly::dynamic> params) {
auto dynamicRequest = folly::dynamic::object("id", id)("method", method);
if (params) {
@@ -118,7 +118,7 @@ std::string jsonResult(
* \param params Optional payload object.
*/
std::string jsonNotification(
std::string_view method,
const std::string& method,
std::optional<folly::dynamic> params = std::nullopt);
/**
@@ -132,7 +132,7 @@ std::string jsonNotification(
*/
std::string jsonRequest(
RequestId id,
std::string_view method,
const std::string& method,
std::optional<folly::dynamic> params = std::nullopt);
} // namespace facebook::react::jsinspector_modern::cdp
@@ -56,7 +56,7 @@ bool NetworkHandler::disable() {
}
enabled_.store(false, std::memory_order_release);
requestBodyBuffer_.clear();
responseBodyBuffer_.clear();
return true;
}
@@ -113,7 +113,10 @@ void NetworkHandler::onResponseReceived(
}
auto resourceType = cdp::network::resourceTypeFromMimeType(response.mimeType);
resourceTypeMap_.emplace(requestId, resourceType);
{
std::lock_guard<std::mutex> lock(resourceTypeMapMutex_);
resourceTypeMap_.emplace(requestId, resourceType);
}
auto params = cdp::network::ResponseReceivedParams{
.requestId = requestId,
@@ -166,23 +169,26 @@ void NetworkHandler::onLoadingFinished(
void NetworkHandler::onLoadingFailed(
const std::string& requestId,
bool cancelled) const {
bool cancelled) {
if (!isEnabledNoSync()) {
return;
}
auto params = cdp::network::LoadingFailedParams{
.requestId = requestId,
.timestamp = getCurrentUnixTimestampSeconds(),
.type = resourceTypeMap_.find(requestId) != resourceTypeMap_.end()
? resourceTypeMap_.at(requestId)
: "Other",
.errorText = cancelled ? "net::ERR_ABORTED" : "net::ERR_FAILED",
.canceled = cancelled,
};
{
std::lock_guard<std::mutex> lock(resourceTypeMapMutex_);
auto params = cdp::network::LoadingFailedParams{
.requestId = requestId,
.timestamp = getCurrentUnixTimestampSeconds(),
.type = resourceTypeMap_.find(requestId) != resourceTypeMap_.end()
? resourceTypeMap_.at(requestId)
: "Other",
.errorText = cancelled ? "net::ERR_ABORTED" : "net::ERR_FAILED",
.canceled = cancelled,
};
frontendChannel_(
cdp::jsonNotification("Network.loadingFailed", params.toDynamic()));
frontendChannel_(
cdp::jsonNotification("Network.loadingFailed", params.toDynamic()));
}
}
void NetworkHandler::storeResponseBody(
@@ -190,13 +196,13 @@ void NetworkHandler::storeResponseBody(
std::string_view body,
bool base64Encoded) {
std::lock_guard<std::mutex> lock(requestBodyMutex_);
requestBodyBuffer_.put(requestId, body, base64Encoded);
responseBodyBuffer_.put(requestId, body, base64Encoded);
}
std::optional<std::tuple<std::string, bool>> NetworkHandler::getResponseBody(
const std::string& requestId) {
std::lock_guard<std::mutex> lock(requestBodyMutex_);
auto responseBody = requestBodyBuffer_.get(requestId);
auto responseBody = responseBodyBuffer_.get(requestId);
if (responseBody == nullptr) {
return std::nullopt;
@@ -100,7 +100,7 @@ class NetworkHandler {
/**
* @cdp Network.loadingFailed
*/
void onLoadingFailed(const std::string& requestId, bool cancelled) const;
void onLoadingFailed(const std::string& requestId, bool cancelled);
/**
* Store the fetched response body for a text or image network response.
@@ -139,8 +139,9 @@ class NetworkHandler {
FrontendChannel frontendChannel_;
std::map<std::string, std::string> resourceTypeMap_{};
std::mutex resourceTypeMapMutex_{};
BoundedRequestBuffer requestBodyBuffer_{};
BoundedRequestBuffer responseBodyBuffer_{};
std::mutex requestBodyMutex_;
};
@@ -124,7 +124,7 @@ std::optional<std::vector<TraceEvent>> PerformanceTracer::stopTracing() {
}
void PerformanceTracer::reportMark(
const std::string_view& name,
const std::string& name,
HighResTimeStamp start,
folly::dynamic&& detail) {
if (!tracingAtomic_) {
@@ -137,7 +137,7 @@ void PerformanceTracer::reportMark(
}
enqueueEvent(PerformanceTracerEventMark{
.name = std::string(name),
.name = name,
.start = start,
.detail = std::move(detail),
.threadId = getCurrentThreadId(),
@@ -145,7 +145,7 @@ void PerformanceTracer::reportMark(
}
void PerformanceTracer::reportMeasure(
const std::string_view& name,
const std::string& name,
HighResTimeStamp start,
HighResDuration duration,
folly::dynamic&& detail) {
@@ -159,7 +159,7 @@ void PerformanceTracer::reportMeasure(
}
enqueueEvent(PerformanceTracerEventMeasure{
.name = std::string(name),
.name = name,
.start = start,
.duration = duration,
.detail = std::move(detail),
@@ -168,7 +168,7 @@ void PerformanceTracer::reportMeasure(
}
void PerformanceTracer::reportTimeStamp(
std::string name,
const std::string& name,
std::optional<ConsoleTimeStampEntry> start,
std::optional<ConsoleTimeStampEntry> end,
std::optional<std::string> trackName,
@@ -184,7 +184,7 @@ void PerformanceTracer::reportTimeStamp(
}
enqueueEvent(PerformanceTracerEventTimeStamp{
.name = std::move(name),
.name = name,
.start = std::move(start),
.end = std::move(end),
.trackName = std::move(trackName),
@@ -232,6 +232,50 @@ void PerformanceTracer::reportEventLoopMicrotasks(
});
}
void PerformanceTracer::reportResourceTiming(
const std::string& requestId,
const std::string& url,
HighResTimeStamp fetchStart,
HighResTimeStamp responseStart,
HighResTimeStamp responseEnd,
int statusCode,
const std::string& requestMethod,
const std::string& resourceType) {
if (!tracingAtomic_) {
return;
}
std::lock_guard<std::mutex> lock(mutex_);
if (!tracingAtomic_) {
return;
}
enqueueEvent(PerformanceTracerResourceWillSendRequest{
.requestId = requestId,
.start = fetchStart,
.threadId = getCurrentThreadId(),
});
enqueueEvent(PerformanceTracerResourceSendRequest{
.requestId = requestId,
.url = url,
.start = fetchStart,
.requestMethod = requestMethod,
.resourceType = resourceType,
.threadId = getCurrentThreadId(),
});
enqueueEvent(PerformanceTracerResourceReceiveResponse{
.requestId = requestId,
.start = responseStart,
.statusCode = statusCode,
.threadId = getCurrentThreadId(),
});
enqueueEvent(PerformanceTracerResourceFinish{
.requestId = requestId,
.start = responseEnd,
.threadId = getCurrentThreadId(),
});
}
/* static */ TraceEvent PerformanceTracer::constructRuntimeProfileTraceEvent(
RuntimeProfileId profileId,
ProcessId processId,
@@ -505,6 +549,73 @@ void PerformanceTracer::enqueueTraceEventsFromPerformanceTracerEvent(
.args = folly::dynamic::object("data", std::move(data)),
});
},
[&](PerformanceTracerResourceWillSendRequest&& event) {
folly::dynamic data =
folly::dynamic::object("requestId", std::move(event.requestId));
events.emplace_back(TraceEvent{
.name = "ResourceWillSendRequest",
.cat = "devtools.timeline",
.ph = 'I',
.ts = event.start,
.pid = processId_,
.s = 't',
.tid = event.threadId,
.args = folly::dynamic::object("data", std::move(data)),
});
},
[&](PerformanceTracerResourceSendRequest&& event) {
folly::dynamic data =
folly::dynamic::object("initiator", folly::dynamic::object())(
"renderBlocking", "non_blocking")(
"requestId", std::move(event.requestId))(
"requestMethod", std::move(event.requestMethod))(
"resourceType", std::move(event.resourceType))(
"url", std::move(event.url));
events.emplace_back(TraceEvent{
.name = "ResourceSendRequest",
.cat = "devtools.timeline",
.ph = 'I',
.ts = event.start,
.pid = processId_,
.s = 't',
.tid = event.threadId,
.args = folly::dynamic::object("data", std::move(data)),
});
},
[&](PerformanceTracerResourceReceiveResponse&& event) {
folly::dynamic data = folly::dynamic::object("protocol", "h2")(
"requestId", std::move(event.requestId))(
"statusCode", event.statusCode)(
"timing", folly::dynamic::object());
events.emplace_back(TraceEvent{
.name = "ResourceReceiveResponse",
.cat = "devtools.timeline",
.ph = 'I',
.ts = event.start,
.pid = processId_,
.s = 't',
.tid = event.threadId,
.args = folly::dynamic::object("data", std::move(data)),
});
},
[&](PerformanceTracerResourceFinish&& event) {
folly::dynamic data = folly::dynamic::object("didFail", false)(
"requestId", std::move(event.requestId));
events.emplace_back(TraceEvent{
.name = "ResourceFinish",
.cat = "devtools.timeline",
.ph = 'I',
.ts = event.start,
.pid = processId_,
.s = 't',
.tid = event.threadId,
.args = folly::dynamic::object("data", std::move(data)),
});
},
},
std::move(event));
}
@@ -65,7 +65,7 @@ class PerformanceTracer {
* See https://w3c.github.io/user-timing/#mark-method.
*/
void reportMark(
const std::string_view& name,
const std::string& name,
HighResTimeStamp start,
folly::dynamic&& detail = nullptr);
@@ -76,7 +76,7 @@ class PerformanceTracer {
* See https://w3c.github.io/user-timing/#measure-method.
*/
void reportMeasure(
const std::string_view& name,
const std::string& name,
HighResTimeStamp start,
HighResDuration duration,
folly::dynamic&& detail = nullptr);
@@ -89,7 +89,7 @@ class PerformanceTracer {
https://developer.chrome.com/docs/devtools/performance/extension#inject_your_data_with_consoletimestamp
*/
void reportTimeStamp(
std::string name,
const std::string& name,
std::optional<ConsoleTimeStampEntry> start = std::nullopt,
std::optional<ConsoleTimeStampEntry> end = std::nullopt,
std::optional<std::string> trackName = std::nullopt,
@@ -108,6 +108,21 @@ class PerformanceTracer {
*/
void reportEventLoopMicrotasks(HighResTimeStamp start, HighResTimeStamp end);
/**
* Record a "ResourceSendRequest"/"ResourceFinish" event pair - a labelled
* duration in the Performance timeline Network track. If not currently
* tracing, this is a no-op.
*/
void reportResourceTiming(
const std::string& requestId,
const std::string& url,
HighResTimeStamp fetchStart,
HighResTimeStamp responseStart,
HighResTimeStamp responseEnd,
int statusCode,
const std::string& requestMethod,
const std::string& resourceType);
/**
* Creates "Profile" Trace Event.
*
@@ -181,12 +196,48 @@ class PerformanceTracer {
HighResTimeStamp createdAt = HighResTimeStamp::now();
};
struct PerformanceTracerResourceWillSendRequest {
std::string requestId;
HighResTimeStamp start;
ThreadId threadId;
HighResTimeStamp createdAt = HighResTimeStamp::now();
};
struct PerformanceTracerResourceSendRequest {
std::string requestId;
std::string url;
HighResTimeStamp start;
std::string requestMethod;
std::string resourceType;
ThreadId threadId;
HighResTimeStamp createdAt = HighResTimeStamp::now();
};
struct PerformanceTracerResourceFinish {
std::string requestId;
HighResTimeStamp start;
ThreadId threadId;
HighResTimeStamp createdAt = HighResTimeStamp::now();
};
struct PerformanceTracerResourceReceiveResponse {
std::string requestId;
HighResTimeStamp start;
int statusCode;
ThreadId threadId;
HighResTimeStamp createdAt = HighResTimeStamp::now();
};
using PerformanceTracerEvent = std::variant<
PerformanceTracerEventTimeStamp,
PerformanceTracerEventEventLoopTask,
PerformanceTracerEventEventLoopMicrotask,
PerformanceTracerEventMark,
PerformanceTracerEventMeasure>;
PerformanceTracerEventMeasure,
PerformanceTracerResourceWillSendRequest,
PerformanceTracerResourceSendRequest,
PerformanceTracerResourceReceiveResponse,
PerformanceTracerResourceFinish>;
#pragma mark - Private fields and methods
@@ -49,8 +49,14 @@ struct RuntimeSamplingProfile {
/// id of the corresponding script in the VM.
uint32_t scriptId;
/// name of the function that represents call frame.
/// Storing a std::string_view should be considered safe here, beacause
/// the lifetime of the string contents are guaranteed as long as the raw
// Sampling Profiler object from Hermes is allocated.
std::string_view functionName;
/// source url of the corresponding script in the VM.
/// Storing a std::string_view should be considered safe here, beacause
/// the lifetime of the string contents are guaranteed as long as the raw
// Sampling Profiler object from Hermes is allocated.
std::optional<std::string_view> scriptURL = std::nullopt;
/// 0-based line number of the corresponding call frame.
std::optional<uint32_t> lineNumber = std::nullopt;
@@ -55,6 +55,12 @@ struct TraceEvent {
/** The ID for the process that output this event. */
ProcessId pid;
/**
* The scope of the event, either global (g), process (p), or thread (t).
* Only applicable to instant events ("ph": "i").
*/
std::optional<char> s;
/** The ID for the thread that output this event. */
ThreadId tid;
@@ -26,6 +26,9 @@ namespace facebook::react::jsinspector_modern::tracing {
result["ph"] = std::string(1, event.ph);
result["ts"] = highResTimeStampToTracingClockTimeStamp(event.ts);
result["pid"] = event.pid;
if (event.s.has_value()) {
result["s"] = std::string(1, event.s.value());
}
result["tid"] = event.tid;
result["args"] = std::move(event.args);
if (event.dur.has_value()) {
@@ -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<<2cbb1a339481d2ba6d3047c2f16d6d10>>
* @generated SignedSource<<42bea10b4b62a91dce8fde7674f76ceb>>
*/
/**
@@ -174,6 +174,10 @@ bool ReactNativeFeatureFlags::enableResourceTimingAPI() {
return getAccessor().enableResourceTimingAPI();
}
bool ReactNativeFeatureFlags::enableSwiftUIBasedFilters() {
return getAccessor().enableSwiftUIBasedFilters();
}
bool ReactNativeFeatureFlags::enableViewCulling() {
return getAccessor().enableViewCulling();
}
@@ -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<<f35eabad586b13eb735569c22e9ee2ce>>
* @generated SignedSource<<40421ac664927693136a8e3197e3c07c>>
*/
/**
@@ -224,6 +224,11 @@ class ReactNativeFeatureFlags {
*/
RN_EXPORT static bool enableResourceTimingAPI();
/**
* When enabled, it will use SwiftUI for filter effects like blur on iOS.
*/
RN_EXPORT static bool enableSwiftUIBasedFilters();
/**
* Enables View Culling: as soon as a view goes off screen, it can be reused anywhere in the UI and pieced together with other items to create new UI elements.
*/
@@ -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<<e3f5d6617de0780d530908a7246676d4>>
* @generated SignedSource<<e433f2f36d7a2852aaea2b37f671a7e1>>
*/
/**
@@ -695,6 +695,24 @@ bool ReactNativeFeatureFlagsAccessor::enableResourceTimingAPI() {
return flagValue.value();
}
bool ReactNativeFeatureFlagsAccessor::enableSwiftUIBasedFilters() {
auto flagValue = enableSwiftUIBasedFilters_.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(37, "enableSwiftUIBasedFilters");
flagValue = currentProvider_->enableSwiftUIBasedFilters();
enableSwiftUIBasedFilters_ = flagValue;
}
return flagValue.value();
}
bool ReactNativeFeatureFlagsAccessor::enableViewCulling() {
auto flagValue = enableViewCulling_.load();
@@ -704,7 +722,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewCulling() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(37, "enableViewCulling");
markFlagAsAccessed(38, "enableViewCulling");
flagValue = currentProvider_->enableViewCulling();
enableViewCulling_ = flagValue;
@@ -722,7 +740,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecycling() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(38, "enableViewRecycling");
markFlagAsAccessed(39, "enableViewRecycling");
flagValue = currentProvider_->enableViewRecycling();
enableViewRecycling_ = flagValue;
@@ -740,7 +758,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecyclingForImage() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(39, "enableViewRecyclingForImage");
markFlagAsAccessed(40, "enableViewRecyclingForImage");
flagValue = currentProvider_->enableViewRecyclingForImage();
enableViewRecyclingForImage_ = flagValue;
@@ -758,7 +776,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecyclingForScrollView() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(40, "enableViewRecyclingForScrollView");
markFlagAsAccessed(41, "enableViewRecyclingForScrollView");
flagValue = currentProvider_->enableViewRecyclingForScrollView();
enableViewRecyclingForScrollView_ = flagValue;
@@ -776,7 +794,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(41, "enableViewRecyclingForText");
markFlagAsAccessed(42, "enableViewRecyclingForText");
flagValue = currentProvider_->enableViewRecyclingForText();
enableViewRecyclingForText_ = flagValue;
@@ -794,7 +812,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(42, "enableViewRecyclingForView");
markFlagAsAccessed(43, "enableViewRecyclingForView");
flagValue = currentProvider_->enableViewRecyclingForView();
enableViewRecyclingForView_ = flagValue;
@@ -812,7 +830,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(43, "enableVirtualViewDebugFeatures");
markFlagAsAccessed(44, "enableVirtualViewDebugFeatures");
flagValue = currentProvider_->enableVirtualViewDebugFeatures();
enableVirtualViewDebugFeatures_ = flagValue;
@@ -830,7 +848,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(44, "enableVirtualViewRenderState");
markFlagAsAccessed(45, "enableVirtualViewRenderState");
flagValue = currentProvider_->enableVirtualViewRenderState();
enableVirtualViewRenderState_ = flagValue;
@@ -848,7 +866,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(45, "enableVirtualViewWindowFocusDetection");
markFlagAsAccessed(46, "enableVirtualViewWindowFocusDetection");
flagValue = currentProvider_->enableVirtualViewWindowFocusDetection();
enableVirtualViewWindowFocusDetection_ = flagValue;
@@ -866,7 +884,7 @@ bool ReactNativeFeatureFlagsAccessor::enableWebPerformanceAPIsByDefault() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(46, "enableWebPerformanceAPIsByDefault");
markFlagAsAccessed(47, "enableWebPerformanceAPIsByDefault");
flagValue = currentProvider_->enableWebPerformanceAPIsByDefault();
enableWebPerformanceAPIsByDefault_ = flagValue;
@@ -884,7 +902,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(47, "fixMappingOfEventPrioritiesBetweenFabricAndReact");
markFlagAsAccessed(48, "fixMappingOfEventPrioritiesBetweenFabricAndReact");
flagValue = currentProvider_->fixMappingOfEventPrioritiesBetweenFabricAndReact();
fixMappingOfEventPrioritiesBetweenFabricAndReact_ = flagValue;
@@ -902,7 +920,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(48, "fuseboxEnabledRelease");
markFlagAsAccessed(49, "fuseboxEnabledRelease");
flagValue = currentProvider_->fuseboxEnabledRelease();
fuseboxEnabledRelease_ = flagValue;
@@ -920,7 +938,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(49, "fuseboxNetworkInspectionEnabled");
markFlagAsAccessed(50, "fuseboxNetworkInspectionEnabled");
flagValue = currentProvider_->fuseboxNetworkInspectionEnabled();
fuseboxNetworkInspectionEnabled_ = flagValue;
@@ -938,7 +956,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(50, "hideOffscreenVirtualViewsOnIOS");
markFlagAsAccessed(51, "hideOffscreenVirtualViewsOnIOS");
flagValue = currentProvider_->hideOffscreenVirtualViewsOnIOS();
hideOffscreenVirtualViewsOnIOS_ = flagValue;
@@ -956,7 +974,7 @@ bool ReactNativeFeatureFlagsAccessor::overrideBySynchronousMountPropsAtMountingA
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(51, "overrideBySynchronousMountPropsAtMountingAndroid");
markFlagAsAccessed(52, "overrideBySynchronousMountPropsAtMountingAndroid");
flagValue = currentProvider_->overrideBySynchronousMountPropsAtMountingAndroid();
overrideBySynchronousMountPropsAtMountingAndroid_ = flagValue;
@@ -974,7 +992,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(52, "perfMonitorV2Enabled");
markFlagAsAccessed(53, "perfMonitorV2Enabled");
flagValue = currentProvider_->perfMonitorV2Enabled();
perfMonitorV2Enabled_ = flagValue;
@@ -992,7 +1010,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(53, "preparedTextCacheSize");
markFlagAsAccessed(54, "preparedTextCacheSize");
flagValue = currentProvider_->preparedTextCacheSize();
preparedTextCacheSize_ = flagValue;
@@ -1010,7 +1028,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(54, "preventShadowTreeCommitExhaustion");
markFlagAsAccessed(55, "preventShadowTreeCommitExhaustion");
flagValue = currentProvider_->preventShadowTreeCommitExhaustion();
preventShadowTreeCommitExhaustion_ = flagValue;
@@ -1028,7 +1046,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(55, "shouldPressibilityUseW3CPointerEventsForHover");
markFlagAsAccessed(56, "shouldPressibilityUseW3CPointerEventsForHover");
flagValue = currentProvider_->shouldPressibilityUseW3CPointerEventsForHover();
shouldPressibilityUseW3CPointerEventsForHover_ = flagValue;
@@ -1046,7 +1064,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(56, "skipActivityIdentityAssertionOnHostPause");
markFlagAsAccessed(57, "skipActivityIdentityAssertionOnHostPause");
flagValue = currentProvider_->skipActivityIdentityAssertionOnHostPause();
skipActivityIdentityAssertionOnHostPause_ = flagValue;
@@ -1064,7 +1082,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(57, "sweepActiveTouchOnChildNativeGesturesAndroid");
markFlagAsAccessed(58, "sweepActiveTouchOnChildNativeGesturesAndroid");
flagValue = currentProvider_->sweepActiveTouchOnChildNativeGesturesAndroid();
sweepActiveTouchOnChildNativeGesturesAndroid_ = flagValue;
@@ -1082,7 +1100,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(58, "traceTurboModulePromiseRejectionsOnAndroid");
markFlagAsAccessed(59, "traceTurboModulePromiseRejectionsOnAndroid");
flagValue = currentProvider_->traceTurboModulePromiseRejectionsOnAndroid();
traceTurboModulePromiseRejectionsOnAndroid_ = flagValue;
@@ -1100,7 +1118,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(59, "updateRuntimeShadowNodeReferencesOnCommit");
markFlagAsAccessed(60, "updateRuntimeShadowNodeReferencesOnCommit");
flagValue = currentProvider_->updateRuntimeShadowNodeReferencesOnCommit();
updateRuntimeShadowNodeReferencesOnCommit_ = flagValue;
@@ -1118,7 +1136,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(60, "useAlwaysAvailableJSErrorHandling");
markFlagAsAccessed(61, "useAlwaysAvailableJSErrorHandling");
flagValue = currentProvider_->useAlwaysAvailableJSErrorHandling();
useAlwaysAvailableJSErrorHandling_ = flagValue;
@@ -1136,7 +1154,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(61, "useFabricInterop");
markFlagAsAccessed(62, "useFabricInterop");
flagValue = currentProvider_->useFabricInterop();
useFabricInterop_ = flagValue;
@@ -1154,7 +1172,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(62, "useNativeEqualsInNativeReadableArrayAndroid");
markFlagAsAccessed(63, "useNativeEqualsInNativeReadableArrayAndroid");
flagValue = currentProvider_->useNativeEqualsInNativeReadableArrayAndroid();
useNativeEqualsInNativeReadableArrayAndroid_ = flagValue;
@@ -1172,7 +1190,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(63, "useNativeTransformHelperAndroid");
markFlagAsAccessed(64, "useNativeTransformHelperAndroid");
flagValue = currentProvider_->useNativeTransformHelperAndroid();
useNativeTransformHelperAndroid_ = flagValue;
@@ -1190,7 +1208,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(64, "useNativeViewConfigsInBridgelessMode");
markFlagAsAccessed(65, "useNativeViewConfigsInBridgelessMode");
flagValue = currentProvider_->useNativeViewConfigsInBridgelessMode();
useNativeViewConfigsInBridgelessMode_ = flagValue;
@@ -1208,7 +1226,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(65, "useOptimizedEventBatchingOnAndroid");
markFlagAsAccessed(66, "useOptimizedEventBatchingOnAndroid");
flagValue = currentProvider_->useOptimizedEventBatchingOnAndroid();
useOptimizedEventBatchingOnAndroid_ = flagValue;
@@ -1226,7 +1244,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(66, "useRawPropsJsiValue");
markFlagAsAccessed(67, "useRawPropsJsiValue");
flagValue = currentProvider_->useRawPropsJsiValue();
useRawPropsJsiValue_ = flagValue;
@@ -1244,7 +1262,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(67, "useShadowNodeStateOnClone");
markFlagAsAccessed(68, "useShadowNodeStateOnClone");
flagValue = currentProvider_->useShadowNodeStateOnClone();
useShadowNodeStateOnClone_ = flagValue;
@@ -1262,7 +1280,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(68, "useTurboModuleInterop");
markFlagAsAccessed(69, "useTurboModuleInterop");
flagValue = currentProvider_->useTurboModuleInterop();
useTurboModuleInterop_ = flagValue;
@@ -1280,7 +1298,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(69, "useTurboModules");
markFlagAsAccessed(70, "useTurboModules");
flagValue = currentProvider_->useTurboModules();
useTurboModules_ = flagValue;
@@ -1298,7 +1316,7 @@ double ReactNativeFeatureFlagsAccessor::virtualViewHysteresisRatio() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(70, "virtualViewHysteresisRatio");
markFlagAsAccessed(71, "virtualViewHysteresisRatio");
flagValue = currentProvider_->virtualViewHysteresisRatio();
virtualViewHysteresisRatio_ = flagValue;
@@ -1316,7 +1334,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(71, "virtualViewPrerenderRatio");
markFlagAsAccessed(72, "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<<a2ef803074301ea53c309422af099355>>
* @generated SignedSource<<6f05211b44f2be076b37ef9178e5ef43>>
*/
/**
@@ -69,6 +69,7 @@ class ReactNativeFeatureFlagsAccessor {
bool enablePreparedTextLayout();
bool enablePropsUpdateReconciliationAndroid();
bool enableResourceTimingAPI();
bool enableSwiftUIBasedFilters();
bool enableViewCulling();
bool enableViewRecycling();
bool enableViewRecyclingForImage();
@@ -115,7 +116,7 @@ class ReactNativeFeatureFlagsAccessor {
std::unique_ptr<ReactNativeFeatureFlagsProvider> currentProvider_;
bool wasOverridden_;
std::array<std::atomic<const char*>, 72> accessedFeatureFlags_;
std::array<std::atomic<const char*>, 73> accessedFeatureFlags_;
std::atomic<std::optional<bool>> commonTestFlag_;
std::atomic<std::optional<bool>> cdpInteractionMetricsEnabled_;
@@ -154,6 +155,7 @@ class ReactNativeFeatureFlagsAccessor {
std::atomic<std::optional<bool>> enablePreparedTextLayout_;
std::atomic<std::optional<bool>> enablePropsUpdateReconciliationAndroid_;
std::atomic<std::optional<bool>> enableResourceTimingAPI_;
std::atomic<std::optional<bool>> enableSwiftUIBasedFilters_;
std::atomic<std::optional<bool>> enableViewCulling_;
std::atomic<std::optional<bool>> enableViewRecycling_;
std::atomic<std::optional<bool>> enableViewRecyclingForImage_;
@@ -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<<680ccef60b08f17fcbfd718087d30955>>
* @generated SignedSource<<b6da08857919846dda053b3635fb9702>>
*/
/**
@@ -175,6 +175,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider {
return false;
}
bool enableSwiftUIBasedFilters() override {
return false;
}
bool enableViewCulling() override {
return false;
}
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<7f3aa6b2ab640df702ea9e8f248d1098>>
* @generated SignedSource<<737e882a924b2730d0c67cc8dc27c8a7>>
*/
/**
@@ -378,6 +378,15 @@ class ReactNativeFeatureFlagsDynamicProvider : public ReactNativeFeatureFlagsDef
return ReactNativeFeatureFlagsDefaults::enableResourceTimingAPI();
}
bool enableSwiftUIBasedFilters() override {
auto value = values_["enableSwiftUIBasedFilters"];
if (!value.isNull()) {
return value.getBool();
}
return ReactNativeFeatureFlagsDefaults::enableSwiftUIBasedFilters();
}
bool enableViewCulling() override {
auto value = values_["enableViewCulling"];
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<<d3b21492391b7b81324b22de1b28771f>>
* @generated SignedSource<<4045a760f000400d47117728119f0d21>>
*/
/**
@@ -62,6 +62,7 @@ class ReactNativeFeatureFlagsProvider {
virtual bool enablePreparedTextLayout() = 0;
virtual bool enablePropsUpdateReconciliationAndroid() = 0;
virtual bool enableResourceTimingAPI() = 0;
virtual bool enableSwiftUIBasedFilters() = 0;
virtual bool enableViewCulling() = 0;
virtual bool enableViewRecycling() = 0;
virtual bool enableViewRecyclingForImage() = 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<<c5fd32fcb5f9241f8039ee983e2fc872>>
* @generated SignedSource<<5042321d7d0da40cc0436ffaeedda168>>
*/
/**
@@ -229,6 +229,11 @@ bool NativeReactNativeFeatureFlags::enableResourceTimingAPI(
return ReactNativeFeatureFlags::enableResourceTimingAPI();
}
bool NativeReactNativeFeatureFlags::enableSwiftUIBasedFilters(
jsi::Runtime& /*runtime*/) {
return ReactNativeFeatureFlags::enableSwiftUIBasedFilters();
}
bool NativeReactNativeFeatureFlags::enableViewCulling(
jsi::Runtime& /*runtime*/) {
return ReactNativeFeatureFlags::enableViewCulling();
@@ -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<<b5d49010286872a588ff74942fd22723>>
* @generated SignedSource<<b1583692e9e07ae68b946496cb94e3e9>>
*/
/**
@@ -110,6 +110,8 @@ class NativeReactNativeFeatureFlags
bool enableResourceTimingAPI(jsi::Runtime& runtime);
bool enableSwiftUIBasedFilters(jsi::Runtime& runtime);
bool enableViewCulling(jsi::Runtime& runtime);
bool enableViewRecycling(jsi::Runtime& runtime);
@@ -8,7 +8,9 @@
#include "NetworkReporter.h"
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
#include "jsinspector-modern/network/NetworkHandler.h"
#include <jsinspector-modern/network/CdpNetwork.h>
#include <jsinspector-modern/network/HttpUtils.h>
#include <jsinspector-modern/network/NetworkHandler.h>
#endif
#include <react/featureflags/ReactNativeFeatureFlags.h>
#include <react/performance/timeline/PerformanceEntryReporter.h>
@@ -43,6 +45,7 @@ void NetworkReporter::reportRequestStart(
requestId,
ResourceTimingData{
.url = requestInfo.url,
.requestMethod = requestInfo.httpMethod,
.fetchStart = now,
.requestStart = now,
});
@@ -108,6 +111,13 @@ void NetworkReporter::reportResponseStart(
it->second.connectEnd = now;
it->second.responseStart = now;
it->second.responseStatus = responseInfo.statusCode;
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
// Debug build: Compute additional fields to send in CDP trace events
it->second.resourceType =
jsinspector_modern::cdp::network::resourceTypeFromMimeType(
jsinspector_modern::mimeTypeFromHeaders(
responseInfo.headers.value_or(Headers{})));
#endif
}
}
}
@@ -155,7 +165,10 @@ void NetworkReporter::reportResponseEnd(
eventData.connectEnd.value_or(now),
eventData.responseStart.value_or(now),
now,
eventData.responseStatus);
eventData.responseStatus,
requestId,
eventData.requestMethod,
eventData.resourceType);
perfTimingsBuffer_.erase(requestId);
}
}
@@ -28,6 +28,8 @@ namespace facebook::react {
*/
struct ResourceTimingData {
std::string url;
std::string requestMethod;
std::optional<std::string> resourceType;
HighResTimeStamp fetchStart;
HighResTimeStamp requestStart;
std::optional<HighResTimeStamp> connectStart;
@@ -307,7 +307,10 @@ void PerformanceEntryReporter::reportResourceTiming(
std::optional<HighResTimeStamp> connectEnd,
HighResTimeStamp responseStart,
HighResTimeStamp responseEnd,
const std::optional<int>& responseStatus) {
const std::optional<int>& responseStatus,
const std::optional<std::string>& devtoolsRequestId,
const std::optional<std::string>& requestMethod,
const std::optional<std::string>& resourceType) {
const auto entry = PerformanceResourceTiming{
{.name = url, .startTime = fetchStart},
fetchStart,
@@ -319,6 +322,8 @@ void PerformanceEntryReporter::reportResourceTiming(
responseStatus,
};
traceResourceTiming(entry, devtoolsRequestId, requestMethod, resourceType);
// Add to buffers & notify observers
{
std::unique_lock lock(buffersMutex_);
@@ -370,4 +375,31 @@ void PerformanceEntryReporter::traceMeasure(
}
}
void PerformanceEntryReporter::traceResourceTiming(
const PerformanceResourceTiming& entry,
const std::optional<std::string>& devtoolsRequestId,
const std::optional<std::string>& requestMethod,
const std::optional<std::string>& resourceType) const {
if (!entry.responseStart.has_value() || !entry.responseEnd.has_value() ||
!entry.responseStatus.has_value() || !devtoolsRequestId.has_value() ||
!requestMethod.has_value() || !resourceType.has_value()) {
return;
}
auto& performanceTracer =
jsinspector_modern::tracing::PerformanceTracer::getInstance();
if (performanceTracer.isTracing()) {
performanceTracer.reportResourceTiming(
*devtoolsRequestId,
entry.name,
entry.fetchStart,
*entry.responseStart,
*entry.responseEnd,
*entry.responseStatus,
*requestMethod,
*resourceType);
}
}
} // namespace facebook::react
@@ -118,7 +118,10 @@ class PerformanceEntryReporter {
std::optional<HighResTimeStamp> connectEnd,
HighResTimeStamp responseStart,
HighResTimeStamp responseEnd,
const std::optional<int>& responseStatus);
const std::optional<int>& responseStatus,
const std::optional<std::string>& devtoolsRequestId,
const std::optional<std::string>& requestMethod,
const std::optional<std::string>& resourceType);
private:
std::unique_ptr<PerformanceObserverRegistry> observerRegistry_;
@@ -182,6 +185,11 @@ class PerformanceEntryReporter {
void traceMeasure(
const PerformanceMeasure& entry,
UserTimingDetailProvider&& detailProvider) const;
void traceResourceTiming(
const PerformanceResourceTiming& entry,
const std::optional<std::string>& devtoolsRequestId,
const std::optional<std::string>& requestMethod,
const std::optional<std::string>& resourceType) const;
};
} // namespace facebook::react
@@ -13,6 +13,7 @@
namespace facebook::react {
// NOLINTNEXTLINE(facebook-hte-CArray,modernize-avoid-c-arrays)
constexpr const char LayoutConformanceShadowNodeComponentName[] =
"LayoutConformance";
@@ -147,7 +147,7 @@ class CSSSyntaxParser {
*
* https://www.w3.org/TR/css-syntax-3/#consume-component-value
*
* @param <ReturnT> caller-specified return type of visitors. This type will
* @tparam ReturnT caller-specified return type of visitors. This type will
* be set to its default constructed state if consuming a component value with
* no matching visitors, or syntax error
* @param visitors A unique list of CSSComponentValueVisitor to be called on a
@@ -5,15 +5,23 @@
* LICENSE file in the root directory of this source tree.
*/
#import <React/RCTDefines.h>
#import <UIKit/UIKit.h>
#import <react/renderer/textlayoutmanager/RCTFontProperties.h>
NS_ASSUME_NONNULL_BEGIN
using RCTDefaultFontResolver = UIFont *__nullable (^)(const RCTFontProperties &);
/**
* React Native will use the System font for rendering by default. If you want to
* provide a different base font, use this override.
*/
RCT_EXTERN void RCTSetDefaultFontResolver(RCTDefaultFontResolver handler);
/**
* Returns UIFont instance corresponded to given font properties.
*/
UIFont *RCTFontWithFontProperties(RCTFontProperties fontProperties);
RCT_EXTERN UIFont *RCTFontWithFontProperties(RCTFontProperties fontProperties);
NS_ASSUME_NONNULL_END
@@ -6,7 +6,9 @@
*/
#import "RCTFontUtils.h"
#import <CoreText/CoreText.h>
#import <React/RCTFont+Private.h>
#import <React/RCTFont.h>
#import <algorithm>
@@ -246,32 +248,61 @@ static NSArray *RCTFontFeatures(RCTFontVariant fontVariant)
return fontFeatures;
}
static UIFont *RCTDefaultFontWithFontProperties(RCTFontProperties fontProperties)
static RCTDefaultFontResolver defaultFontResolver;
void RCTSetDefaultFontResolver(RCTDefaultFontResolver handler)
{
defaultFontResolver = handler;
}
static UIFont *RCTDefaultFontWithFontProperties(const RCTFontProperties &fontProperties)
{
static NSCache *fontCache;
static std::mutex fontCacheMutex;
CGFloat effectiveFontSize = fontProperties.sizeMultiplier * fontProperties.size;
NSString *cacheKey = [NSString
stringWithFormat:@"%.1f/%.2f/%ld", effectiveFontSize, fontProperties.weight, (long)fontProperties.style];
NSString *cacheKey = [NSString stringWithFormat:@"%@/%.1f/%.2f/%ld",
fontProperties.family,
effectiveFontSize,
fontProperties.weight,
(long)fontProperties.style];
UIFont *font;
{
std::lock_guard<std::mutex> lock(fontCacheMutex);
if (fontCache == nullptr) {
if (fontCache == nil) {
fontCache = [NSCache new];
}
font = [fontCache objectForKey:cacheKey];
}
if (font == nullptr) {
font = [UIFont systemFontOfSize:effectiveFontSize weight:fontProperties.weight];
if (font == nil) {
if (defaultFontResolver != nil) {
font = defaultFontResolver(fontProperties);
}
if (fontProperties.style == RCTFontStyleItalic) {
if (font == nil) {
font = RCTGetLegacyDefaultFont(effectiveFontSize, fontProperties.weight);
}
if (font == nil) {
font = [UIFont systemFontOfSize:effectiveFontSize weight:fontProperties.weight];
}
BOOL isItalicFont = fontProperties.style == RCTFontStyleItalic;
BOOL isCondensedFont = [fontProperties.family isEqualToString:@"SystemCondensed"];
if (isItalicFont || isCondensedFont) {
UIFontDescriptor *fontDescriptor = [font fontDescriptor];
UIFontDescriptorSymbolicTraits symbolicTraits = fontDescriptor.symbolicTraits;
symbolicTraits |= UIFontDescriptorTraitItalic;
if (isItalicFont) {
symbolicTraits |= UIFontDescriptorTraitItalic;
}
if (isCondensedFont) {
symbolicTraits |= UIFontDescriptorTraitCondensed;
}
fontDescriptor = [fontDescriptor fontDescriptorWithSymbolicTraits:symbolicTraits];
font = [UIFont fontWithDescriptor:fontDescriptor size:effectiveFontSize];
@@ -333,7 +364,7 @@ UIFont *RCTFontWithFontProperties(RCTFontProperties fontProperties)
fontWeight = (fontWeight != 0.0) ?: RCTGetFontWeight(font);
} else {
// Failback to system font.
font = [UIFont systemFontOfSize:effectiveFontSize weight:fontProperties.weight];
font = RCTDefaultFontWithFontProperties(fontProperties);
}
}
@@ -354,7 +385,7 @@ UIFont *RCTFontWithFontProperties(RCTFontProperties fontProperties)
}
}
if (font == nullptr) {
if (font == nil) {
// If we still don't have a match at least return the first font in the
// fontFamily This is to support built-in font Zapfino and other custom
// single font families like Impact
+6
View File
@@ -66,6 +66,12 @@ module.exports = {
get Modal() {
return require('./Libraries/Modal/Modal').default;
},
get unstable_NativeText() {
return require('./Libraries/Text/TextNativeComponent').NativeText;
},
get unstable_NativeView() {
return require('./Libraries/Components/View/ViewNativeComponent').default;
},
get Pressable() {
return require('./Libraries/Components/Pressable/Pressable').default;
},
+3
View File
@@ -127,6 +127,8 @@ export {default as Switch} from './Libraries/Components/Switch/Switch';
export type {TextProps} from './Libraries/Text/Text';
export {default as Text} from './Libraries/Text/Text';
export type {NativeTextProps as unstable_NativeTextProps} from './Libraries/Text/TextNativeComponent';
export {NativeText as unstable_NativeText} from './Libraries/Text/TextNativeComponent';
export {default as unstable_TextAncestorContext} from './Libraries/Text/TextAncestorContext';
export type {
@@ -180,6 +182,7 @@ export type {
ViewPropsIOS,
} from './Libraries/Components/View/ViewPropTypes';
export {default as View} from './Libraries/Components/View/View';
export {default as unstable_NativeView} from './Libraries/Components/View/ViewNativeComponent';
export type {
ListRenderItemInfo,
+2 -1
View File
@@ -175,6 +175,7 @@
"commander": "^12.0.0",
"flow-enums-runtime": "^0.0.6",
"glob": "^7.1.1",
"hermes-compiler": "0.0.0",
"invariant": "^2.2.4",
"jest-environment-node": "^29.7.0",
"memoize-one": "^5.0.0",
@@ -190,7 +191,7 @@
"semver": "^7.1.3",
"stacktrace-parser": "^0.1.10",
"whatwg-fetch": "^3.0.0",
"ws": "^6.2.3",
"ws": "^7.5.10",
"yargs": "^17.6.2"
},
"codegenConfig": {
@@ -440,6 +440,17 @@ const definitions: FeatureFlagDefinitions = {
},
ossReleaseStage: 'none',
},
enableSwiftUIBasedFilters: {
defaultValue: false,
metadata: {
dateAdded: '2025-07-30',
description:
'When enabled, it will use SwiftUI for filter effects like blur on iOS.',
expectedReleaseValue: true,
purpose: 'experimentation',
},
ossReleaseStage: 'none',
},
enableViewCulling: {
defaultValue: false,
metadata: {
@@ -151,6 +151,8 @@ def use_react_native! (
pod 'RCTDeprecation', :path => "#{prefix}/ReactApple/Libraries/RCTFoundation/RCTDeprecation"
pod 'React-RCTFBReactNativeSpec', :path => "#{prefix}/React"
pod 'React-jsi', :path => "#{prefix}/ReactCommon/jsi"
pod 'RCTSwiftUI', :path => "#{prefix}/ReactApple/RCTSwiftUI"
pod 'RCTSwiftUIWrapper', :path => "#{prefix}/ReactApple/RCTSwiftUIWrapper"
if hermes_enabled
setup_hermes!(:react_native_path => prefix)
@@ -79,6 +79,12 @@ type VirtualViewExperimentalNativeProps = $ReadOnly<{
*/
renderState: Int32,
/**
* This was needed to get VirtualViewManagerDelegate to set this property.
* TODO: Investigate why spread ViewProps doesn't call setter
*/
removeClippedSubviews?: boolean,
/**
* See `NativeModeChangeEvent`.
*/
@@ -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<<b1ab664114aa99d0f674d049c81bdc67>>
* @generated SignedSource<<054add14ea0c9a96d3c3e32af8995437>>
* @flow strict
* @noformat
*/
@@ -87,6 +87,7 @@ export type ReactNativeFeatureFlags = $ReadOnly<{
enablePreparedTextLayout: Getter<boolean>,
enablePropsUpdateReconciliationAndroid: Getter<boolean>,
enableResourceTimingAPI: Getter<boolean>,
enableSwiftUIBasedFilters: Getter<boolean>,
enableViewCulling: Getter<boolean>,
enableViewRecycling: Getter<boolean>,
enableViewRecyclingForImage: Getter<boolean>,
@@ -351,6 +352,10 @@ export const enablePropsUpdateReconciliationAndroid: Getter<boolean> = createNat
* Enables the reporting of network resource timings through `PerformanceObserver`.
*/
export const enableResourceTimingAPI: Getter<boolean> = createNativeFlagGetter('enableResourceTimingAPI', false);
/**
* When enabled, it will use SwiftUI for filter effects like blur on iOS.
*/
export const enableSwiftUIBasedFilters: Getter<boolean> = createNativeFlagGetter('enableSwiftUIBasedFilters', false);
/**
* Enables View Culling: as soon as a view goes off screen, it can be reused anywhere in the UI and pieced together with other items to create new UI elements.
*/
@@ -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<<14e017052313836604a3150fa08a1ebe>>
* @generated SignedSource<<ae5e2e1799601c6f630a465ec8e64ef6>>
* @flow strict
* @noformat
*/
@@ -62,6 +62,7 @@ export interface Spec extends TurboModule {
+enablePreparedTextLayout?: () => boolean;
+enablePropsUpdateReconciliationAndroid?: () => boolean;
+enableResourceTimingAPI?: () => boolean;
+enableSwiftUIBasedFilters?: () => boolean;
+enableViewCulling?: () => boolean;
+enableViewRecycling?: () => boolean;
+enableViewRecyclingForImage?: () => boolean;
+33
View File
@@ -94,6 +94,9 @@ PODS:
- glog
- RCTDeprecation (1000.0.0)
- RCTRequired (1000.0.0)
- RCTSwiftUI (1000.0.0)
- RCTSwiftUIWrapper (1000.0.0):
- RCTSwiftUI
- RCTTypeSafety (1000.0.0):
- FBLazyVector (= 1000.0.0)
- RCTRequired (= 1000.0.0)
@@ -576,6 +579,7 @@ PODS:
- RCT-Folly
- RCT-Folly/Fabric
- RCTRequired
- RCTSwiftUIWrapper
- RCTTypeSafety
- React-Core
- React-cxxreact
@@ -618,6 +622,7 @@ PODS:
- RCT-Folly
- RCT-Folly/Fabric
- RCTRequired
- RCTSwiftUIWrapper
- RCTTypeSafety
- React-Core
- React-cxxreact
@@ -643,6 +648,7 @@ PODS:
- RCT-Folly
- RCT-Folly/Fabric
- RCTRequired
- RCTSwiftUIWrapper
- RCTTypeSafety
- React-Core
- React-cxxreact
@@ -668,6 +674,7 @@ PODS:
- RCT-Folly
- RCT-Folly/Fabric
- RCTRequired
- RCTSwiftUIWrapper
- RCTTypeSafety
- React-Core
- React-cxxreact
@@ -693,6 +700,7 @@ PODS:
- RCT-Folly
- RCT-Folly/Fabric
- RCTRequired
- RCTSwiftUIWrapper
- RCTTypeSafety
- React-Core
- React-cxxreact
@@ -718,6 +726,7 @@ PODS:
- RCT-Folly
- RCT-Folly/Fabric
- RCTRequired
- RCTSwiftUIWrapper
- RCTTypeSafety
- React-Core
- React-cxxreact
@@ -743,6 +752,7 @@ PODS:
- RCT-Folly
- RCT-Folly/Fabric
- RCTRequired
- RCTSwiftUIWrapper
- RCTTypeSafety
- React-Core
- React-cxxreact
@@ -772,6 +782,7 @@ PODS:
- RCT-Folly
- RCT-Folly/Fabric
- RCTRequired
- RCTSwiftUIWrapper
- RCTTypeSafety
- React-Core
- React-cxxreact
@@ -797,6 +808,7 @@ PODS:
- RCT-Folly
- RCT-Folly/Fabric
- RCTRequired
- RCTSwiftUIWrapper
- RCTTypeSafety
- React-Core
- React-cxxreact
@@ -822,6 +834,7 @@ PODS:
- RCT-Folly
- RCT-Folly/Fabric
- RCTRequired
- RCTSwiftUIWrapper
- RCTTypeSafety
- React-Core
- React-cxxreact
@@ -847,6 +860,7 @@ PODS:
- RCT-Folly
- RCT-Folly/Fabric
- RCTRequired
- RCTSwiftUIWrapper
- RCTTypeSafety
- React-Core
- React-cxxreact
@@ -874,6 +888,7 @@ PODS:
- RCT-Folly
- RCT-Folly/Fabric
- RCTRequired
- RCTSwiftUIWrapper
- RCTTypeSafety
- React-Core
- React-cxxreact
@@ -899,6 +914,7 @@ PODS:
- RCT-Folly
- RCT-Folly/Fabric
- RCTRequired
- RCTSwiftUIWrapper
- RCTTypeSafety
- React-Core
- React-cxxreact
@@ -924,6 +940,7 @@ PODS:
- RCT-Folly
- RCT-Folly/Fabric
- RCTRequired
- RCTSwiftUIWrapper
- RCTTypeSafety
- React-Core
- React-cxxreact
@@ -949,6 +966,7 @@ PODS:
- RCT-Folly
- RCT-Folly/Fabric
- RCTRequired
- RCTSwiftUIWrapper
- RCTTypeSafety
- React-Core
- React-cxxreact
@@ -974,6 +992,7 @@ PODS:
- RCT-Folly
- RCT-Folly/Fabric
- RCTRequired
- RCTSwiftUIWrapper
- RCTTypeSafety
- React-Core
- React-cxxreact
@@ -999,6 +1018,7 @@ PODS:
- RCT-Folly
- RCT-Folly/Fabric
- RCTRequired
- RCTSwiftUIWrapper
- RCTTypeSafety
- React-Core
- React-cxxreact
@@ -1024,6 +1044,7 @@ PODS:
- RCT-Folly
- RCT-Folly/Fabric
- RCTRequired
- RCTSwiftUIWrapper
- RCTTypeSafety
- React-Core
- React-cxxreact
@@ -1050,6 +1071,7 @@ PODS:
- RCT-Folly
- RCT-Folly/Fabric
- RCTRequired
- RCTSwiftUIWrapper
- RCTTypeSafety
- React-Core
- React-cxxreact
@@ -1075,6 +1097,7 @@ PODS:
- RCT-Folly
- RCT-Folly/Fabric
- RCTRequired
- RCTSwiftUIWrapper
- RCTTypeSafety
- React-Core
- React-cxxreact
@@ -1103,6 +1126,7 @@ PODS:
- RCT-Folly
- RCT-Folly/Fabric
- RCTRequired
- RCTSwiftUIWrapper
- RCTTypeSafety
- React-Core
- React-cxxreact
@@ -1128,6 +1152,7 @@ PODS:
- RCT-Folly
- RCT-Folly/Fabric
- RCTRequired
- RCTSwiftUIWrapper
- RCTTypeSafety
- React-Core
- React-cxxreact
@@ -1153,6 +1178,7 @@ PODS:
- RCT-Folly
- RCT-Folly/Fabric
- RCTRequired
- RCTSwiftUIWrapper
- RCTTypeSafety
- React-Core
- React-cxxreact
@@ -1180,6 +1206,7 @@ PODS:
- RCT-Folly
- RCT-Folly/Fabric
- RCTRequired
- RCTSwiftUIWrapper
- RCTTypeSafety
- React-Core
- React-cxxreact
@@ -2436,6 +2463,8 @@ DEPENDENCIES:
- RCT-Folly (from `../react-native/third-party-podspecs/RCT-Folly.podspec`)
- RCTDeprecation (from `../react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation`)
- RCTRequired (from `../react-native/Libraries/Required`)
- RCTSwiftUI (from `../react-native/ReactApple/RCTSwiftUI`)
- RCTSwiftUIWrapper (from `../react-native/ReactApple/RCTSwiftUIWrapper`)
- RCTTypeSafety (from `../react-native/Libraries/TypeSafety`)
- React (from `../react-native/`)
- React-callinvoker (from `../react-native/ReactCommon/callinvoker`)
@@ -2536,6 +2565,10 @@ EXTERNAL SOURCES:
:path: "../react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation"
RCTRequired:
:path: "../react-native/Libraries/Required"
RCTSwiftUI:
:path: "../react-native/ReactApple/RCTSwiftUI"
RCTSwiftUIWrapper:
:path: "../react-native/ReactApple/RCTSwiftUIWrapper"
RCTTypeSafety:
:path: "../react-native/Libraries/TypeSafety"
React:
@@ -10,15 +10,15 @@
0EA618032BE537D3001875EF /* RNTesterBundle.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 0EA618022BE537D3001875EF /* RNTesterBundle.bundle */; };
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
2DDEF0101F84BF7B00DBDF73 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2DDEF00F1F84BF7B00DBDF73 /* Images.xcassets */; };
3584606AB7F8ADF7A07A3E14 /* libPods-RNTesterIntegrationTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DF9F45393190A3F008764D08 /* libPods-RNTesterIntegrationTests.a */; };
383889DA23A7398900D06C3E /* RCTConvert_UIColorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 383889D923A7398900D06C3E /* RCTConvert_UIColorTests.m */; };
3D2AFAF51D646CF80089D1A3 /* legacy_image@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3D2AFAF41D646CF80089D1A3 /* legacy_image@2x.png */; };
3F4D148C63BBF774A25488A6 /* libPods-RNTesterIntegrationTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 93A243F0D4D5C54911E811C4 /* libPods-RNTesterIntegrationTests.a */; };
46C0FD761B0B9B1E8662B759 /* libPods-RNTesterUnitTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2B312B0EEE90BA411618B015 /* libPods-RNTesterUnitTests.a */; };
5C60EB1C226440DB0018C04F /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5C60EB1B226440DB0018C04F /* AppDelegate.mm */; };
8145AE06241172D900A3F8DA /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8145AE05241172D900A3F8DA /* LaunchScreen.storyboard */; };
832F45BB2A8A6E1F0097B4E6 /* SwiftTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 832F45BA2A8A6E1F0097B4E6 /* SwiftTest.swift */; };
A36E4394472D388C2F6BBABA /* libPods-RNTester.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 48A747D61749335D863001E9 /* libPods-RNTester.a */; };
A975CA6C2C05EADF0043F72A /* RCTNetworkTaskTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A975CA6B2C05EADE0043F72A /* RCTNetworkTaskTests.m */; };
BF2C34488C1E5FF62D331DD4 /* libPods-RNTesterUnitTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E89C730A8F64BC35672D4D81 /* libPods-RNTesterUnitTests.a */; };
C175B6D9ED9336FB66637943 /* libPods-RNTester.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C706D402EE4AF9BE838CBA9 /* libPods-RNTester.a */; };
CD10C7A5290BD4EB0033E1ED /* RCTEventEmitterTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CD10C7A4290BD4EB0033E1ED /* RCTEventEmitterTests.m */; };
E62F11832A5C6580000BF1C8 /* FlexibleSizeExampleView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 27F441E81BEBE5030039B79C /* FlexibleSizeExampleView.mm */; };
E62F11842A5C6584000BF1C8 /* UpdatePropertiesExampleView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 272E6B3C1BEA849E001FCF37 /* UpdatePropertiesExampleView.mm */; };
@@ -84,27 +84,28 @@
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = RNTester/AppDelegate.h; sourceTree = "<group>"; };
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = RNTester/Info.plist; sourceTree = "<group>"; };
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = RNTester/main.m; sourceTree = "<group>"; };
20B55D3C33B683598D2A4424 /* Pods-RNTesterIntegrationTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTesterIntegrationTests.debug.xcconfig"; path = "Target Support Files/Pods-RNTesterIntegrationTests/Pods-RNTesterIntegrationTests.debug.xcconfig"; sourceTree = "<group>"; };
272E6B3B1BEA849E001FCF37 /* UpdatePropertiesExampleView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UpdatePropertiesExampleView.h; path = RNTester/NativeExampleViews/UpdatePropertiesExampleView.h; sourceTree = "<group>"; };
272E6B3C1BEA849E001FCF37 /* UpdatePropertiesExampleView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = UpdatePropertiesExampleView.mm; path = RNTester/NativeExampleViews/UpdatePropertiesExampleView.mm; sourceTree = "<group>"; };
2734C5E31C1D7A09BF872585 /* Pods-RNTester.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTester.debug.xcconfig"; path = "Target Support Files/Pods-RNTester/Pods-RNTester.debug.xcconfig"; sourceTree = "<group>"; };
27F441E81BEBE5030039B79C /* FlexibleSizeExampleView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = FlexibleSizeExampleView.mm; path = RNTester/NativeExampleViews/FlexibleSizeExampleView.mm; sourceTree = "<group>"; };
27F441EA1BEBE5030039B79C /* FlexibleSizeExampleView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FlexibleSizeExampleView.h; path = RNTester/NativeExampleViews/FlexibleSizeExampleView.h; sourceTree = "<group>"; };
2B312B0EEE90BA411618B015 /* libPods-RNTesterUnitTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RNTesterUnitTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
2DDEF00F1F84BF7B00DBDF73 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = RNTester/Images.xcassets; sourceTree = "<group>"; };
359825B9A5AE4A3F4AA612DD /* Pods-RNTesterUnitTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTesterUnitTests.debug.xcconfig"; path = "Target Support Files/Pods-RNTesterUnitTests/Pods-RNTesterUnitTests.debug.xcconfig"; sourceTree = "<group>"; };
383889D923A7398900D06C3E /* RCTConvert_UIColorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTConvert_UIColorTests.m; sourceTree = "<group>"; };
3D2AFAF41D646CF80089D1A3 /* legacy_image@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "legacy_image@2x.png"; path = "RNTester/legacy_image@2x.png"; sourceTree = "<group>"; };
48A747D61749335D863001E9 /* libPods-RNTester.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RNTester.a"; sourceTree = BUILT_PRODUCTS_DIR; };
3FF60722627F93D8F62FA1E3 /* Pods-RNTesterUnitTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTesterUnitTests.release.xcconfig"; path = "Target Support Files/Pods-RNTesterUnitTests/Pods-RNTesterUnitTests.release.xcconfig"; sourceTree = "<group>"; };
4C706D402EE4AF9BE838CBA9 /* libPods-RNTester.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RNTester.a"; sourceTree = BUILT_PRODUCTS_DIR; };
51BC9297B6C3163C14532020 /* Pods-RNTester.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTester.release.xcconfig"; path = "Target Support Files/Pods-RNTester/Pods-RNTester.release.xcconfig"; sourceTree = "<group>"; };
5C60EB1B226440DB0018C04F /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = RNTester/AppDelegate.mm; sourceTree = "<group>"; };
66C3087F2D5BF762FE9E6422 /* Pods-RNTesterIntegrationTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTesterIntegrationTests.debug.xcconfig"; path = "Target Support Files/Pods-RNTesterIntegrationTests/Pods-RNTesterIntegrationTests.debug.xcconfig"; sourceTree = "<group>"; };
7CDA7A212644C6BB8C0D00D8 /* Pods-RNTesterIntegrationTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTesterIntegrationTests.release.xcconfig"; path = "Target Support Files/Pods-RNTesterIntegrationTests/Pods-RNTesterIntegrationTests.release.xcconfig"; sourceTree = "<group>"; };
8145AE05241172D900A3F8DA /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = RNTester/LaunchScreen.storyboard; sourceTree = "<group>"; };
832F45BA2A8A6E1F0097B4E6 /* SwiftTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = SwiftTest.swift; path = RNTester/SwiftTest.swift; sourceTree = "<group>"; };
8BFB9C61D7BDE894E24BF24F /* Pods-RNTesterUnitTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTesterUnitTests.release.xcconfig"; path = "Target Support Files/Pods-RNTesterUnitTests/Pods-RNTesterUnitTests.release.xcconfig"; sourceTree = "<group>"; };
9B8542B8C590B51BD0588751 /* Pods-RNTester.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTester.release.xcconfig"; path = "Target Support Files/Pods-RNTester/Pods-RNTester.release.xcconfig"; sourceTree = "<group>"; };
93A243F0D4D5C54911E811C4 /* libPods-RNTesterIntegrationTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RNTesterIntegrationTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
A975CA6B2C05EADE0043F72A /* RCTNetworkTaskTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RCTNetworkTaskTests.m; sourceTree = "<group>"; };
AC474BFB29BBD4A1002BDAED /* RNTester.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; name = RNTester.xctestplan; path = RNTester/RNTester.xctestplan; sourceTree = "<group>"; };
B0E70A8A05E03E868F8703FE /* Pods-RNTesterIntegrationTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTesterIntegrationTests.release.xcconfig"; path = "Target Support Files/Pods-RNTesterIntegrationTests/Pods-RNTesterIntegrationTests.release.xcconfig"; sourceTree = "<group>"; };
CA59C9994B1822826D8983F0 /* Pods-RNTester.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTester.debug.xcconfig"; path = "Target Support Files/Pods-RNTester/Pods-RNTester.debug.xcconfig"; sourceTree = "<group>"; };
CD10C7A4290BD4EB0033E1ED /* RCTEventEmitterTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTEventEmitterTests.m; sourceTree = "<group>"; };
DF9F45393190A3F008764D08 /* libPods-RNTesterIntegrationTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RNTesterIntegrationTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
D134EB89DD98253FCF879A47 /* Pods-RNTesterUnitTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTesterUnitTests.debug.xcconfig"; path = "Target Support Files/Pods-RNTesterUnitTests/Pods-RNTesterUnitTests.debug.xcconfig"; sourceTree = "<group>"; };
E771AEEA22B44E3100EA1189 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = RNTester/Info.plist; sourceTree = "<group>"; };
E7C1241922BEC44B00DA25C0 /* RNTesterIntegrationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNTesterIntegrationTests.m; sourceTree = "<group>"; };
E7DB209F22B2BA84005AC45F /* RNTesterUnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RNTesterUnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -166,7 +167,6 @@
E7DB215E22B2F3EC005AC45F /* RCTLoggingTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTLoggingTests.m; sourceTree = "<group>"; };
E7DB215F22B2F3EC005AC45F /* RCTUIManagerScenarioTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTUIManagerScenarioTests.m; sourceTree = "<group>"; };
E7DB218B22B41FCD005AC45F /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = XCTest.framework; sourceTree = DEVELOPER_DIR; };
E89C730A8F64BC35672D4D81 /* libPods-RNTesterUnitTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RNTesterUnitTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
F0D621C22BBB9E38005960AC /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
/* End PBXFileReference section */
@@ -175,7 +175,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
A36E4394472D388C2F6BBABA /* libPods-RNTester.a in Frameworks */,
C175B6D9ED9336FB66637943 /* libPods-RNTester.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -184,7 +184,7 @@
buildActionMask = 2147483647;
files = (
E7DB213122B2C649005AC45F /* JavaScriptCore.framework in Frameworks */,
BF2C34488C1E5FF62D331DD4 /* libPods-RNTesterUnitTests.a in Frameworks */,
46C0FD761B0B9B1E8662B759 /* libPods-RNTesterUnitTests.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -194,7 +194,7 @@
files = (
E7DB218C22B41FCD005AC45F /* XCTest.framework in Frameworks */,
E7DB216722B2F69F005AC45F /* JavaScriptCore.framework in Frameworks */,
3584606AB7F8ADF7A07A3E14 /* libPods-RNTesterIntegrationTests.a in Frameworks */,
3F4D148C63BBF774A25488A6 /* libPods-RNTesterIntegrationTests.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -265,9 +265,9 @@
E7DB211822B2BD53005AC45F /* libReact-RCTText.a */,
E7DB211A22B2BD53005AC45F /* libReact-RCTVibration.a */,
E7DB212222B2BD53005AC45F /* libyoga.a */,
48A747D61749335D863001E9 /* libPods-RNTester.a */,
DF9F45393190A3F008764D08 /* libPods-RNTesterIntegrationTests.a */,
E89C730A8F64BC35672D4D81 /* libPods-RNTesterUnitTests.a */,
4C706D402EE4AF9BE838CBA9 /* libPods-RNTester.a */,
93A243F0D4D5C54911E811C4 /* libPods-RNTesterIntegrationTests.a */,
2B312B0EEE90BA411618B015 /* libPods-RNTesterUnitTests.a */,
);
name = Frameworks;
sourceTree = "<group>";
@@ -308,12 +308,12 @@
E23BD6487B06BD71F1A86914 /* Pods */ = {
isa = PBXGroup;
children = (
2734C5E31C1D7A09BF872585 /* Pods-RNTester.debug.xcconfig */,
9B8542B8C590B51BD0588751 /* Pods-RNTester.release.xcconfig */,
66C3087F2D5BF762FE9E6422 /* Pods-RNTesterIntegrationTests.debug.xcconfig */,
7CDA7A212644C6BB8C0D00D8 /* Pods-RNTesterIntegrationTests.release.xcconfig */,
359825B9A5AE4A3F4AA612DD /* Pods-RNTesterUnitTests.debug.xcconfig */,
8BFB9C61D7BDE894E24BF24F /* Pods-RNTesterUnitTests.release.xcconfig */,
CA59C9994B1822826D8983F0 /* Pods-RNTester.debug.xcconfig */,
51BC9297B6C3163C14532020 /* Pods-RNTester.release.xcconfig */,
20B55D3C33B683598D2A4424 /* Pods-RNTesterIntegrationTests.debug.xcconfig */,
B0E70A8A05E03E868F8703FE /* Pods-RNTesterIntegrationTests.release.xcconfig */,
D134EB89DD98253FCF879A47 /* Pods-RNTesterUnitTests.debug.xcconfig */,
3FF60722627F93D8F62FA1E3 /* Pods-RNTesterUnitTests.release.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
@@ -378,14 +378,14 @@
isa = PBXNativeTarget;
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "RNTester" */;
buildPhases = (
ABDE2A52ACD1B95E14790B5E /* [CP] Check Pods Manifest.lock */,
F28F13DD10D40D98C0BB7BE8 /* [CP] Check Pods Manifest.lock */,
13B07F871A680F5B00A75B9A /* Sources */,
13B07F8C1A680F5B00A75B9A /* Frameworks */,
13B07F8E1A680F5B00A75B9A /* Resources */,
68CD48B71D2BCB2C007E06A9 /* Build JS Bundle */,
79E8BE2B119D4C5CCD2F04B3 /* [RN] Copy Hermes Framework */,
02B6FEF7E86B613B42F31284 /* [CP] Embed Pods Frameworks */,
5625E703156DD564DE9175B0 /* [CP] Copy Pods Resources */,
17FE348EDF12252D972FFC2F /* [CP] Embed Pods Frameworks */,
DFEE284B22AD5E88BBF1026A /* [CP] Copy Pods Resources */,
);
buildRules = (
);
@@ -400,12 +400,12 @@
isa = PBXNativeTarget;
buildConfigurationList = E7DB20A622B2BA84005AC45F /* Build configuration list for PBXNativeTarget "RNTesterUnitTests" */;
buildPhases = (
4F76596957F7356516B534CE /* [CP] Check Pods Manifest.lock */,
B8A88048D4E22316B9E74600 /* [CP] Check Pods Manifest.lock */,
E7DB209B22B2BA84005AC45F /* Sources */,
E7DB209C22B2BA84005AC45F /* Frameworks */,
E7DB209D22B2BA84005AC45F /* Resources */,
A904658C20543C2EDC217D15 /* [CP] Embed Pods Frameworks */,
01934C30687B8C926E4F59CD /* [CP] Copy Pods Resources */,
FD96BE05C0CECDF7D53C7CC9 /* [CP] Embed Pods Frameworks */,
5ECFFC3767E171859C7610A6 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
@@ -421,12 +421,12 @@
isa = PBXNativeTarget;
buildConfigurationList = E7DB215A22B2F332005AC45F /* Build configuration list for PBXNativeTarget "RNTesterIntegrationTests" */;
buildPhases = (
B7EB74515CDE78D98087DD53 /* [CP] Check Pods Manifest.lock */,
2978D2EE0533828E5DB62B8F /* [CP] Check Pods Manifest.lock */,
E7DB214F22B2F332005AC45F /* Sources */,
E7DB215022B2F332005AC45F /* Frameworks */,
E7DB215122B2F332005AC45F /* Resources */,
4F27ACC9DB890B37D6C267F1 /* [CP] Embed Pods Frameworks */,
E446637427ECD101CAACE52B /* [CP] Copy Pods Resources */,
A27E74B2EEF82EC119BCB5A2 /* [CP] Embed Pods Frameworks */,
48BF6B9FD13CB20F2C71C2A2 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
@@ -510,24 +510,7 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
01934C30687B8C926E4F59CD /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-RNTesterUnitTests/Pods-RNTesterUnitTests-resources-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Copy Pods Resources";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-RNTesterUnitTests/Pods-RNTesterUnitTests-resources-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RNTesterUnitTests/Pods-RNTesterUnitTests-resources.sh\"\n";
showEnvVarsInLog = 0;
};
02B6FEF7E86B613B42F31284 /* [CP] Embed Pods Frameworks */ = {
17FE348EDF12252D972FFC2F /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
@@ -544,24 +527,7 @@
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RNTester/Pods-RNTester-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
4F27ACC9DB890B37D6C267F1 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-RNTesterIntegrationTests/Pods-RNTesterIntegrationTests-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-RNTesterIntegrationTests/Pods-RNTesterIntegrationTests-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RNTesterIntegrationTests/Pods-RNTesterIntegrationTests-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
4F76596957F7356516B534CE /* [CP] Check Pods Manifest.lock */ = {
2978D2EE0533828E5DB62B8F /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
@@ -576,28 +542,45 @@
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-RNTesterUnitTests-checkManifestLockResult.txt",
"$(DERIVED_FILE_DIR)/Pods-RNTesterIntegrationTests-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
5625E703156DD564DE9175B0 /* [CP] Copy Pods Resources */ = {
48BF6B9FD13CB20F2C71C2A2 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-RNTester/Pods-RNTester-resources-${CONFIGURATION}-input-files.xcfilelist",
"${PODS_ROOT}/Target Support Files/Pods-RNTesterIntegrationTests/Pods-RNTesterIntegrationTests-resources-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Copy Pods Resources";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-RNTester/Pods-RNTester-resources-${CONFIGURATION}-output-files.xcfilelist",
"${PODS_ROOT}/Target Support Files/Pods-RNTesterIntegrationTests/Pods-RNTesterIntegrationTests-resources-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RNTester/Pods-RNTester-resources.sh\"\n";
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RNTesterIntegrationTests/Pods-RNTesterIntegrationTests-resources.sh\"\n";
showEnvVarsInLog = 0;
};
5ECFFC3767E171859C7610A6 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-RNTesterUnitTests/Pods-RNTesterUnitTests-resources-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Copy Pods Resources";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-RNTesterUnitTests/Pods-RNTesterUnitTests-resources-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RNTesterUnitTests/Pods-RNTesterUnitTests-resources.sh\"\n";
showEnvVarsInLog = 0;
};
68CD48B71D2BCB2C007E06A9 /* Build JS Bundle */ = {
@@ -634,24 +617,63 @@
shellPath = /bin/sh;
shellScript = ". ../react-native/sdks/hermes-engine/utils/copy-hermes-xcode.sh\n";
};
A904658C20543C2EDC217D15 /* [CP] Embed Pods Frameworks */ = {
A27E74B2EEF82EC119BCB5A2 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-RNTesterUnitTests/Pods-RNTesterUnitTests-frameworks-${CONFIGURATION}-input-files.xcfilelist",
"${PODS_ROOT}/Target Support Files/Pods-RNTesterIntegrationTests/Pods-RNTesterIntegrationTests-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-RNTesterUnitTests/Pods-RNTesterUnitTests-frameworks-${CONFIGURATION}-output-files.xcfilelist",
"${PODS_ROOT}/Target Support Files/Pods-RNTesterIntegrationTests/Pods-RNTesterIntegrationTests-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RNTesterUnitTests/Pods-RNTesterUnitTests-frameworks.sh\"\n";
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RNTesterIntegrationTests/Pods-RNTesterIntegrationTests-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
ABDE2A52ACD1B95E14790B5E /* [CP] Check Pods Manifest.lock */ = {
B8A88048D4E22316B9E74600 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-RNTesterUnitTests-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
DFEE284B22AD5E88BBF1026A /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-RNTester/Pods-RNTester-resources-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Copy Pods Resources";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-RNTester/Pods-RNTester-resources-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RNTester/Pods-RNTester-resources.sh\"\n";
showEnvVarsInLog = 0;
};
F28F13DD10D40D98C0BB7BE8 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
@@ -673,43 +695,21 @@
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
B7EB74515CDE78D98087DD53 /* [CP] Check Pods Manifest.lock */ = {
FD96BE05C0CECDF7D53C7CC9 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-RNTesterUnitTests/Pods-RNTesterUnitTests-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-RNTesterIntegrationTests-checkManifestLockResult.txt",
"${PODS_ROOT}/Target Support Files/Pods-RNTesterUnitTests/Pods-RNTesterUnitTests-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
E446637427ECD101CAACE52B /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-RNTesterIntegrationTests/Pods-RNTesterIntegrationTests-resources-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Copy Pods Resources";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-RNTesterIntegrationTests/Pods-RNTesterIntegrationTests-resources-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RNTesterIntegrationTests/Pods-RNTesterIntegrationTests-resources.sh\"\n";
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RNTesterUnitTests/Pods-RNTesterUnitTests-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
@@ -794,7 +794,7 @@
/* Begin XCBuildConfiguration section */
13B07F941A680F5B00A75B9A /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 2734C5E31C1D7A09BF872585 /* Pods-RNTester.debug.xcconfig */;
baseConfigurationReference = CA59C9994B1822826D8983F0 /* Pods-RNTester.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
@@ -832,7 +832,7 @@
};
13B07F951A680F5B00A75B9A /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9B8542B8C590B51BD0588751 /* Pods-RNTester.release.xcconfig */;
baseConfigurationReference = 51BC9297B6C3163C14532020 /* Pods-RNTester.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
@@ -1063,7 +1063,7 @@
};
E7DB20A722B2BA84005AC45F /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 359825B9A5AE4A3F4AA612DD /* Pods-RNTesterUnitTests.debug.xcconfig */;
baseConfigurationReference = D134EB89DD98253FCF879A47 /* Pods-RNTesterUnitTests.debug.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CLANG_ANALYZER_NONNULL = YES;
@@ -1101,7 +1101,7 @@
};
E7DB20A822B2BA84005AC45F /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 8BFB9C61D7BDE894E24BF24F /* Pods-RNTesterUnitTests.release.xcconfig */;
baseConfigurationReference = 3FF60722627F93D8F62FA1E3 /* Pods-RNTesterUnitTests.release.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CLANG_ANALYZER_NONNULL = YES;
@@ -1139,7 +1139,7 @@
};
E7DB215B22B2F332005AC45F /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 66C3087F2D5BF762FE9E6422 /* Pods-RNTesterIntegrationTests.debug.xcconfig */;
baseConfigurationReference = 20B55D3C33B683598D2A4424 /* Pods-RNTesterIntegrationTests.debug.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
BUNDLE_LOADER = "$(TEST_HOST)";
@@ -1178,7 +1178,7 @@
};
E7DB215C22B2F332005AC45F /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7CDA7A212644C6BB8C0D00D8 /* Pods-RNTesterIntegrationTests.release.xcconfig */;
baseConfigurationReference = B0E70A8A05E03E868F8703FE /* Pods-RNTesterIntegrationTests.release.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
BUNDLE_LOADER = "$(TEST_HOST)";
@@ -15,7 +15,7 @@ import type {ViewStyleProp} from 'react-native/Libraries/StyleSheet/StyleSheet';
import React from 'react';
import {useState} from 'react';
import {Image, StyleSheet, Text, View} from 'react-native';
import {Animated, Button, Image, StyleSheet, Text, View} from 'react-native';
const alphaHotdog = require('../../assets/alpha-hotdog.png');
const hotdog = require('../../assets/hotdog.jpg');
@@ -67,6 +67,14 @@ function StaticViewAndImageWithState(props: Props): React.Node {
}
const styles = StyleSheet.create({
blurWithShadow: {
filter: [{blur: 10}],
boxShadow: '0 0 10px 10px black',
overflow: 'hidden',
backgroundColor: 'pink',
height: 100,
width: 100,
},
commonView: {
width: 150,
height: 150,
@@ -189,7 +197,6 @@ exports.examples = [
title: 'Blur',
description: 'blur(10)',
name: 'blur',
platform: 'android',
render(): React.Node {
return (
<StaticViewAndImageComparison
@@ -199,6 +206,27 @@ exports.examples = [
);
},
},
{
title: 'Blur with boxShadow + overflow hidden + outline',
description: 'This tests container view with blur and outline on iOS',
name: 'blur-with-overflow',
render(): React.Node {
return (
<View
style={styles.blurWithShadow}
testID="filter-test-blur-overflow-hidden"
/>
);
},
},
{
title: 'Animated Blur',
description: 'Animated blur',
name: 'animated-blur',
render(): React.Node {
return <AnimatedBlurExample />;
},
},
{
title: 'Drop Shadow',
description: 'drop-shadow(30px 10px 4px #4444dd)',
@@ -253,3 +281,35 @@ exports.examples = [
},
},
] as Array<RNTesterModuleExample>;
const AnimatedBlurExample = () => {
const animatedValue = React.useRef(new Animated.Value(0)).current;
const [isBlurred, setIsBlurred] = React.useState(false);
const onPress = () => {
Animated.timing(animatedValue, {
toValue: isBlurred ? 0 : 20,
duration: 1000,
useNativeDriver: false,
}).start(() => setIsBlurred(!isBlurred));
};
return (
<View style={{flexDirection: 'column', alignItems: 'center'}}>
<Button
onPress={onPress}
title={isBlurred ? 'Remove Blur' : 'Animate Blur'}
/>
<Animated.View
style={[
{
filter: [{blur: animatedValue}],
backgroundColor: 'pink',
height: 100,
width: 100,
},
]}
/>
</View>
);
};
@@ -577,42 +577,23 @@ const examples = [
description:
('Shows system font families including system-ui/ui-sans-serif, ui-serif, ui-monospace, and ui-rounded': string),
render: function (): React.Node {
const baseTextStyle = {fontSize: 20};
return (
<View testID={'ios-font-families'}>
<Text
style={{
fontFamily: 'system-ui',
fontSize: 32,
marginBottom: 20,
}}>
`fontFamily: system-ui` (same as `ui-sans-serif`)
<View testID={'ios-font-families'} style={{gap: 10}}>
<Text style={{...baseTextStyle, fontFamily: 'system-ui'}}>
system-ui (same as ui-sans-serif)
</Text>
<Text
style={{
fontFamily: 'ui-sans-serif',
fontSize: 32,
marginBottom: 20,
}}>
`fontFamily: ui-sans-serif` (same as `system-ui`)
<Text style={{...baseTextStyle, fontFamily: 'ui-sans-serif'}}>
ui-sans-serif (same as system-ui)
</Text>
<Text
style={{fontFamily: 'ui-serif', fontSize: 32, marginBottom: 20}}>
`fontFamily: ui-serif`
<Text style={{...baseTextStyle, fontFamily: 'ui-serif'}}>
ui-serif
</Text>
<Text
style={{
fontFamily: 'ui-monospace',
fontSize: 32,
marginBottom: 20,
}}>
`fontFamily: ui-monospace`
<Text style={{...baseTextStyle, fontFamily: 'ui-monospace'}}>
ui-monospace
</Text>
<Text
style={{
fontFamily: 'ui-rounded',
fontSize: 32,
}}>
`fontFamily: ui-rounded`
<Text style={{...baseTextStyle, fontFamily: 'ui-rounded'}}>
ui-rounded
</Text>
</View>
);
@@ -767,6 +748,7 @@ const examples = [
}}>
Verdana bold
</Text>
<Text style={{fontFamily: 'SystemCondensed'}}>SystemCondensed</Text>
<Text style={{fontFamily: 'Unknown Font Family'}}>
Unknown Font Family
</Text>
@@ -282,8 +282,6 @@ describe('publish-npm', () => {
code: 0,
}));
process.env.NPM_CONFIG_OTP = 'otp';
await publishNpm('release');
expect(setVersionMock).not.toBeCalled();
@@ -303,7 +301,7 @@ describe('publish-npm', () => {
expect(publishPackageMock.mock.calls).toEqual([
[
path.join(REPO_ROOT, 'packages', 'react-native'),
{otp: process.env.NPM_CONFIG_OTP, tags: ['0.81-stable']},
{tags: ['0.81-stable']},
],
]);
@@ -322,8 +320,6 @@ describe('publish-npm', () => {
code: 0,
}));
process.env.NPM_CONFIG_OTP = 'otp';
await publishNpm('release');
expect(updateReactNativeArtifactsMock).not.toBeCalled();
@@ -341,10 +337,7 @@ describe('publish-npm', () => {
);
expect(publishPackageMock.mock.calls).toEqual([
[
path.join(REPO_ROOT, 'packages', 'react-native'),
{otp: process.env.NPM_CONFIG_OTP, tags: ['latest']},
],
[path.join(REPO_ROOT, 'packages', 'react-native'), {tags: ['latest']}],
]);
expect(consoleLogMock.mock.calls).toEqual([
@@ -365,8 +358,6 @@ describe('publish-npm', () => {
execMock.mockReturnValueOnce({code: 1});
isTaggedLatestMock.mockReturnValueOnce(true);
process.env.NPM_CONFIG_OTP = 'otp';
await expect(async () => {
await publishNpm('release');
}).rejects.toThrow(
@@ -388,10 +379,7 @@ describe('publish-npm', () => {
);
expect(publishPackageMock.mock.calls).toEqual([
[
path.join(REPO_ROOT, 'packages', 'react-native'),
{otp: process.env.NPM_CONFIG_OTP, tags: ['latest']},
],
[path.join(REPO_ROOT, 'packages', 'react-native'), {tags: ['latest']}],
]);
expect(consoleLogMock).not.toHaveBeenCalled();
});
@@ -406,8 +394,6 @@ describe('publish-npm', () => {
code: 0,
}));
process.env.NPM_CONFIG_OTP = 'otp';
await publishNpm('release');
expect(setVersionMock).not.toBeCalled();
@@ -425,10 +411,7 @@ describe('publish-npm', () => {
);
expect(publishPackageMock.mock.calls).toEqual([
[
path.join(REPO_ROOT, 'packages', 'react-native'),
{otp: process.env.NPM_CONFIG_OTP, tags: ['next']},
],
[path.join(REPO_ROOT, 'packages', 'react-native'), {tags: ['next']}],
]);
expect(consoleLogMock.mock.calls).toEqual([
[`Published react-native@${expectedVersion} to npm`],
-2
View File
@@ -76,7 +76,6 @@ async function publishMonorepoPackages(tag /*: ?string */) {
console.log(`Publishing ${packageInfo.name}...`);
const result = publishPackage(packageInfo.path, {
tags: [tag],
otp: process.env.NPM_CONFIG_OTP,
access: 'public',
});
@@ -122,7 +121,6 @@ async function publishNpm(buildType /*: BuildType */) /*: Promise<void> */ {
const packagePath = path.join(REPO_ROOT, 'packages', 'react-native');
const result = publishPackage(packagePath, {
tags: [tag],
otp: process.env.NPM_CONFIG_OTP,
});
if (result.code) {
@@ -14,7 +14,6 @@ const {execSync} = require('child_process');
const {parseArgs} = require('util');
const PUBLISH_PACKAGES_TAG = '#publish-packages-to-npm';
const NPM_CONFIG_OTP = process.env.NPM_CONFIG_OTP;
const config = {
options: {
@@ -139,7 +138,6 @@ function runPublish(
) {
const result = publishPackage(packagePath, {
tags,
otp: NPM_CONFIG_OTP,
});
if (result.code !== 0) {
@@ -33,37 +33,35 @@ describe('npm-utils', () => {
it('should run publish command', () => {
publishPackage(
'path/to/my-package',
{tags: ['latest'], otp: 'otp'},
{tags: ['latest']},
{silent: true, cwd: 'i/expect/this/to/be/overriden'},
);
expect(execMock).toHaveBeenCalledWith(
'npm publish --tag latest --otp otp',
{silent: true, cwd: 'path/to/my-package'},
);
expect(execMock).toHaveBeenCalledWith('npm publish --tag latest', {
silent: true,
cwd: 'path/to/my-package',
});
});
it('should run publish command when no execOptions', () => {
publishPackage('path/to/my-package', {tags: ['latest'], otp: 'otp'});
expect(execMock).toHaveBeenCalledWith(
'npm publish --tag latest --otp otp',
{cwd: 'path/to/my-package'},
);
publishPackage('path/to/my-package', {tags: ['latest']});
expect(execMock).toHaveBeenCalledWith('npm publish --tag latest', {
cwd: 'path/to/my-package',
});
});
it('should handle multiple tags', () => {
publishPackage('path/to/my-package', {
tags: ['next', '0.72-stable'],
otp: 'otp',
});
expect(execMock).toHaveBeenCalledWith(
'npm publish --tag next --tag 0.72-stable --otp otp',
'npm publish --tag next --tag 0.72-stable',
{cwd: 'path/to/my-package'},
);
});
it('should handle -no-tag', () => {
publishPackage('path/to/my-package', {tags: ['--no-tag'], otp: 'otp'});
expect(execMock).toHaveBeenCalledWith('npm publish --no-tag --otp otp', {
publishPackage('path/to/my-package', {tags: ['--no-tag']});
expect(execMock).toHaveBeenCalledWith('npm publish --no-tag', {
cwd: 'path/to/my-package',
});
});
+2 -4
View File
@@ -35,7 +35,6 @@ type PackageJSON = {
}
type NpmPackageOptions = {
tags: ?Array<string> | ?Array<?string>,
otp: ?string,
access?: ?('public' | 'restricted')
}
*/
@@ -130,7 +129,7 @@ function publishPackage(
packageOptions /*: NpmPackageOptions */,
execOptions /*: ?ExecOptsSync */,
) /*: ShellString */ {
const {otp, tags, access} = packageOptions;
const {tags, access} = packageOptions;
let tagsFlag = '';
if (tags != null) {
@@ -142,13 +141,12 @@ function publishPackage(
.join('');
}
const otpFlag = otp != null ? ` --otp ${otp}` : '';
const accessFlag = access != null ? ` --access ${access}` : '';
const options /*: ExecOptsSync */ = execOptions
? {...execOptions, cwd: packagePath}
: {cwd: packagePath};
return exec(`npm publish${tagsFlag}${otpFlag}${accessFlag}`, options);
return exec(`npm publish${tagsFlag}${accessFlag}`, options);
}
/**
+5
View File
@@ -5306,6 +5306,11 @@ hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2:
dependencies:
function-bind "^1.1.2"
hermes-compiler@0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/hermes-compiler/-/hermes-compiler-0.0.0.tgz#8d9f6a0b2740ce34d71258fec684e7b6bfd97efa"
integrity sha512-boVFutx6ME/Km2mB6vvsQcdnazEYYI/jV1pomx1wcFUG/EVqTkr5CU0CW9bKipOA/8Hyu3NYwW3THg2Q1kNCfA==
hermes-eslint@0.32.0:
version "0.32.0"
resolved "https://registry.yarnpkg.com/hermes-eslint/-/hermes-eslint-0.32.0.tgz#a23bcaece522f356cb1b8e990e57117dca13852d"