Compare commits

...
Author SHA1 Message Date
Distiller 972b42016e Release 0.74.0
#publish-packages-to-npm&latest
2024-04-22 11:41:17 +00:00
Alex Hunt 5d1272f9cd Update Podfile.lock
Changelog: [Internal]
2024-04-22 11:44:22 +01:00
Distiller d4a48ce692 Release 0.74.0-rc.9
#publish-packages-to-npm&next
2024-04-15 14:02:09 +00:00
Riccardo Cipolleschi 2b18fdf806 [LOCAL][iOS] Fix RNTester project and remove CCACHE from project when disabled 2024-04-15 12:15:37 +01:00
Phillip PanandAlex Hunt 92c6d22f3c add privacy manifest to pod install
Summary:
Changelog: [iOS][Added]

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

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

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

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

Reviewed By: cipolleschi

Differential Revision: D53687232

fbshipit-source-id: 6dffb1a6013f8f29438a49752e47ed75c13f4a5c

# Conflicts:
#	packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj
2024-04-15 11:30:01 +02:00
Riccardo CipolleschiandAlex Hunt bb5451b425 Fix Open Debugger dev menu item missing from iOS Bridgeless
Summary:
After a [recent change](https://github.com/facebook/react-native/commit/90296be1d4fab09a52e02dd09f34f819136d0a07) we break part of the integration with the debug menu, which is was using the presence/absence of the bridge to decide whether we were in bridge or bridgeless.

For backward compatibility reasosn, the bridge ivar is now populated with the bridgeProxy, so just checking whether is nil or not is not enough to verify whether we are in bridge or in bridgeless mode anymore.

## Changelog:
[iOS][Fixed] - Make sure that the Open Debugger appears in bridgeless mode

Reviewed By: fkgozali

Differential Revision: D56067897

fbshipit-source-id: e2501ed730ff35bc755c24ef400130c551032e28
2024-04-15 11:22:11 +02:00
zhongwuzwandAlex Hunt 0b3ebdfb22 Change bridgeless check in dev menu (#43976)
Summary:
We would set the value of  _bridge ivar to bridgeProxy for turbo module in bridgeless mode in https://github.com/facebook/react-native/issues/43757 , so we need to change the way of bridgeless/bridge check.

## Changelog:

[IOS] [FIXED] - Change bridgeless check in dev menu

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

Test Plan: Dev menu shows bridgeless/bridge mode correctly.

Reviewed By: christophpurrer

Differential Revision: D56056640

Pulled By: cipolleschi

fbshipit-source-id: 1358c3027c1d5f12c70dd4486cc1d5975c7a185a
2024-04-15 11:22:04 +02:00
Arushi KesarwaniandAlex Hunt 26854de04b Implement getJavaScriptContextHolder for BridgelessCatalystInstance (#44054)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/44054

Implement `getJavaScriptContextHolder()` for BridgelessCatalystInstance

Changelog:
[Android][Breaking] Implement `getJavaScriptContextHolder()` for Bridgeless Catalyst Instance

Reviewed By: christophpurrer

Differential Revision: D56046452

fbshipit-source-id: b7fed1da3064608d8ef5fa84f4e53a4f7a84cba7
2024-04-15 11:21:13 +02:00
Arushi KesarwaniandAlex Hunt e7131fadca Implement getRuntimeExecutor for BridgelessCatalystInstance (#44053)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/44053

Implement `getRuntimeExecutor()` for BridgelessCatalystInstance

Changelog:
[Android][Breaking] Implement `getRuntimeExecutor()` for Bridgeless Catalyst Instance

Reviewed By: christophpurrer

Differential Revision: D56046398

fbshipit-source-id: b9f947cf6f83ce7c1d334558a11b76fccab45dbd
2024-04-15 11:21:07 +02:00
Nicola Corti 012a95cf56 Update Podfile.lock
Changelog: [Internal]
2024-04-10 15:45:31 +01:00
Distiller 2a6e156054 Release 0.74.0-rc.8
#publish-packages-to-npm&next
2024-04-10 13:06:30 +00:00
cb2d93ea50 [RN][iOS] Cherry Pick #43757 and #43994 (#44007)
* Support launchOptions in bridgeless mode (#43757)

Summary:
Support launchOptions in bridgeless mode
bypass-github-export-checks

[IOS] [FIXED] - Support launchOptions in bridgeless mode

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

Test Plan:
```
useEffect(() => {
    const processInitialURL = async () => {
      const url = await Linking.getInitialURL();
      if (url !== null) {
        console.log(`Initial url is: ${url}`);
      }
    };

    processInitialURL();
  }, []);
```

Reviewed By: javache

Differential Revision: D55790758

Pulled By: cipolleschi

fbshipit-source-id: 0f6aa6bdcebfc5bc42d632bea9193f122c1eb84f

* Fix Connect to Metro after Reload in Bridgeless mode (#43994)

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

We received [this issue](https://github.com/facebook/react-native/issues/43764) from OSS where an app can't connect to Metro on reloads in the following scenario:

* Start the App when metro does not run.
* Observe the error screen
* Start Metro
* Press Reload
* Observe the error message again

While the desired behavior should be to connect to Metro now that this is running.

The root cause of the problem is that the RCTHost is initialized with a value of the `bundleURL` that is `nil`. Upon reload, the RCTHost is **not** recreated: the instance is restarted, but with the previous `bundleURL`, which is still `nil`.

The solution is to initialize the `RCTHost` with a closure that re-evaluate the `bundleURL` whenever it is invoked and to evaluate it only on `start`, to keep the initialization path light.
This way, when the app is started with Metro not running, the `bundleURL` is `nil`. But when it is reloaded with Metro starting, the `bundleURL` is properly initialized.

Note that the changes in this diff are not breaking as I reimplemented (and deprecated) the old initializer so that they should work in the same way.

[iOS][Fixed] - Let RCTHost be initialized with a function to provide the `bundleURL` so that it can connect to metro on Reload when the url changes.

Reviewed By: dmytrorykun

Differential Revision: D55916135

fbshipit-source-id: 6927b2154870245f28f42d26bd0209b28c9518f2

* Fix badly resolved merge  conflicts

---------

Co-authored-by: zhongwuzw <zhongwuzw@qq.com>
2024-04-10 11:01:24 +01:00
Phillip PanandNicola Corti 2d84d83534 add privacy manifest to hello world template
Summary:
Changelog: [iOS][Added]

this change will be included in the RN CLI. so all new apps running the RN CLI to get created will get this manifest. the reasons have been added for the following APIs:

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

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

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

Reviewed By: cipolleschi

Differential Revision: D53682756

fbshipit-source-id: 0426fe0002a3bc8b45ef24053ac4228c9f61eb85
2024-04-10 08:34:48 +01:00
Nicola Corti 03d526f4d5 Fix bridge mode by constructing ReactDelegate correctly. (#43999)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43999

Currently NewArch-BridgeMode is partially broken when creating views via `ReactDelegate`.
That's because we're using the ctor that doesn't account for `Boolean: fabricEnabled`.

That means that the `RootView` that it will be created are all having setIsFabric(FALSE).
This is causing problems like whitescreens on several reload + multiple warnings such as:
```
                         E  com.facebook.react.bridge.ReactNoCrashSoftException: Cannot get UIManager because the context doesn't contain an active CatalystInstance.
```

Fixes #43692

See for more context on this issues: https://github.com/facebook/react-native/issues/43692

Changelog:
[Android] [Fixed] - Fix bridge mode by constructing ReactDelegate correctly

Reviewed By: cipolleschi

Differential Revision: D55921078

fbshipit-source-id: 2c21d089a49538402d546177bcdb26c8d7d5fbc1
2024-04-09 18:27:53 +01:00
Riccardo CipolleschiandNicola Corti 4eb0534513 Fix Orientation listener in bridgeless mode (#43971)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43971

It turns out that we forgot to add a listener for the orientation change event in Bridgeless.

We used to have `UIApplicationDidChangeStatusBarOrientationNotification` but this is slightly unreliable because there might be use cases where the status bar has been hidden and, therefore, the event is not triggered.

This should fix an issue reported by OSS.

## Changelog:
[iOS][Fixed] - Make sure that the New Architecture listens to orientation change events.

Reviewed By: cortinico

Differential Revision: D55871599

fbshipit-source-id: c9b0634ec2126aa7a6488c2c56c87a9610fa1adf
2024-04-09 18:26:52 +01:00
Riccardo CipolleschiandNicola Corti c2317bf9a5 Fix double metro banner in Bridgeless (#43967)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43967

Following up https://github.com/facebook/react-native/issues/43943, the metro loading banner is presented twice in Bridgeless mode.

This happens because both the RCTInstance and the RCTHost are listening to the Reload Command and issuing the instructions to refetch the JSBundle and to present the banner.

The RCTInstance should not concern itself with lifecycle events, owned by the RCTHost.

## Changelog:
[iOS][Fixed] - Avoid to show Metro Loading banner twice.

Reviewed By: cortinico

Differential Revision: D55870640

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

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

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

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

## Changelog:

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

Pick one each for the category and type tags:

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

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

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

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

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

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

Reviewed By: arushikesarwani94

Differential Revision: D55339059

Pulled By: zeyap

fbshipit-source-id: c067997364fbec734510ce99b9994e89d044384a
2024-04-09 18:25:03 +01:00
Nicola Corti cbfa0a2055 Update Podfile.lock
Changelog: [Internal]
2024-04-08 14:56:24 +01:00
Distiller 40feba6a81 Release 0.74.0-rc.7
#publish-packages-to-npm&next
2024-04-08 12:21:14 +00:00
zhongwuzwandNicola Corti 44159e35ce Remove invalidate observer instead of re-adding observer in DeviceInfo module (#43737)
Summary:
Previous fix brings in https://github.com/facebook/react-native/pull/42396. Seems it's a mistake to re-add observer?
So let's remove it and also not `invalidate` method not be called twice.

## Changelog:

[IOS] [FIXED] - Remove invalidate observer instead of re-adding observer in DeviceInfo module

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

Test Plan: Fix for https://github.com/facebook/react-native/issues/42120 also works.

Reviewed By: javache

Differential Revision: D55692219

Pulled By: cipolleschi

fbshipit-source-id: dba1ddc39a9f2611fc2b84fadf8c23827891379a
2024-04-08 07:52:09 +01:00
Riccardo CipolleschiandNicola Corti 42eebafb81 Fix static linking for Bridgeless mode (#43846)
Summary:
Working with gabrieldonadel, we realized that static frameworks of the React-RendererRuntime are not following the proper folder structure.
When a user tries to import `ReactCommon/RCTHost` in the app delegate, for example, the user ends up with an error and they can't find the files.

These changes fixes this by establishing the right folder structure in the static frameworks

## Changelog:
[Internal] - Make sure that React-RuntimeCore and JSErrorHandler are created with the proper structure for static frameworks

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

Test Plan:
Tested locally on an app with 0.74.
Before: it failed to build.
After: it build successfully.

Reviewed By: cortinico

Differential Revision: D55741581

Pulled By: cipolleschi

fbshipit-source-id: 11ac0882d3feea05ef8904d55856ba5704b7a3b8
2024-04-08 07:51:47 +01:00
Riccardo CipolleschiandNicola Corti 4e9196d433 Fix RCTRCTComposedViewRegistry for Old Arch by adding count and keyEnumerator (#43850)
Summary:
In the Old Architecture and for Swift Libraries, these two methods are used to initialize a new disctionary but their implementation was missing so some libraries like lottie were failig to build.

## Changelog:
[Internal] - Implement missing `count` and `keyEnumerator` methods for RCTComposedViewRegistry

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

Test Plan: Tested locally with the repro provided by SWM

Reviewed By: javache

Differential Revision: D55743648

Pulled By: cipolleschi

fbshipit-source-id: 7bdb92625341cd704b8b09920ab3223a2ca61a54
2024-04-08 07:51:09 +01:00
Vojtech NovakandNicola Corti 57ed1bde01 fix: add missing fields to native errors in new arch (#43649)
Summary:
With 0.74.rc-5 one bug which related to errors was fixed (https://github.com/facebook/react-native/issues/41950). However, the fix introduced another one: the shape of Error objects that come from native modules has changed. This PR attempts to fix that, though it's not (yet) doing it in a way that would be 100% compatible with the old arch.

The problem was observed on iOS, not sure what the situation is on Android but believe it's okay there.

edit: on Android, there are no issues but the `message` field is enumerable, so that part is different from ios (see logs below).

Consider this code, where `error` is produced from a promise rejection inside of a native module.

```ts
  console.log(
    'own properties: ',
    JSON.stringify(Object.getOwnPropertyNames(error), null, 2),
  );
  console.log(
    'own enumerable properties: ',
    JSON.stringify(Object.entries(error), null, 2),
  );
```

These are the results for

<details>
  <summary>Old architecture</summary>

```
 LOG  Running "google-one-tap-example" with {"rootTag":1,"initialProps":{}}
 LOG  own properties:  [
  "stack",
  "code",
  "message",
  "domain",
  "userInfo",
  "nativeStackIOS"
]
 LOG  own enumerable properties:  [
  [
    "code",
    "-5"
  ],
  [
    "message",
    "RNGoogleSignIn: The user canceled the sign in request., Error Domain=com.google.GIDSignIn Code=-5 \"The user canceled the sign-in flow.\" UserInfo={NSLocalizedDescription=The user canceled the sign-in flow.}"
  ],
  [
    "domain",
    "com.google.GIDSignIn"
  ],
  [
    "userInfo",
    {
      "NSLocalizedDescription": "The user canceled the sign-in flow."
    }
  ],
  [
    "nativeStackIOS",
    [
      "0   ReactTestApp                        0x0000000102f4a6d8 RCTJSErrorFromCodeMessageAndNSError + 112",
      "1   ReactTestApp                        0x0000000102eeedd0 __41-[RCTModuleMethod processMethodSignature]_block_invoke_2.73 + 152",
      "2   ReactTestApp                        0x0000000102e2ae24 +[RNGoogleSignin rejectWithSigninError:withRejector:] + 548",
      "3   ReactTestApp                        0x0000000102e2aa8c -[RNGoogleSignin handleCompletion:serverAuthCode:withError:withResolver:withRejector:fromCallsite:] + 184",
      "4   ReactTestApp                        0x0000000102e2a8e0 -[RNGoogleSignin handleCompletion:withError:withResolver:withRejector:fromCallsite:] + 236",
      "5   ReactTestApp                        0x0000000102e28628 __40-[RNGoogleSignin signIn:resolve:reject:]_block_invoke_2 + 100",
      "6   ReactTestApp                        0x0000000102dc9d80 __35-[GIDSignIn addCompletionCallback:]_block_invoke_2 + 132",
...
    ]
  ]
]
```
</details>

<details>
  <summary>RN 74 rc-5 (with bridgeless on)</summary>

```
  (NOBRIDGE) LOG  Bridgeless mode is enabled
 (NOBRIDGE) LOG  Running "google-one-tap-example" with {"rootTag":1,"initialProps":{"concurrentRoot":true},"fabric":true}
 (NOBRIDGE) LOG  own properties:  [
  "stack",
  "message",
  "cause"
]
 (NOBRIDGE) LOG  own enumerable properties:  [
  [
    "cause",
    {
      "code": "-5",
      "message": "RNGoogleSignIn: The user canceled the sign in request., Error Domain=com.google.GIDSignIn Code=-5 \"The user canceled the sign-in flow.\" UserInfo={NSLocalizedDescription=The user canceled the sign-in flow.}",
      "nativeStackIOS": [
        "0   ReactTestApp                        0x00000001023a7b38 RCTJSErrorFromCodeMessageAndNSError + 112",
        "1   ReactTestApp                        0x00000001026cf774 ___ZZN8facebook5react15ObjCTurboModule13createPromiseERNS_3jsi7RuntimeENSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEEU13block_pointerFvU13block_pointerFvP11objc_objectEU13block_pointerFvP8NSStringSH_P7NSErrorEEENK3$_0clES4_RKNS2_5ValueEPSQ_m_block_invoke.57 + 332",
        "2   ReactTestApp                        0x0000000102270958 +[RNGoogleSignin rejectWithSigninError:withRejector:] + 548",
        "3   ReactTestApp                        0x00000001022705c0 -[RNGoogleSignin handleCompletion:serverAuthCode:withError:withResolver:withRejector:fromCallsite:] + 184",
        "4   ReactTestApp                        0x0000000102270414 -[RNGoogleSignin handleCompletion:withError:withResolver:withRejector:fromCallsite:] + 236",
        "5   ReactTestApp                        0x000000010226e15c __40-[RNGoogleSignin signIn:resolve:reject:]_block_invoke_2 + 100",
        "6   ReactTestApp                        0x000000010220f328 __35-[GIDSignIn addCompletionCallback:]_block_invoke_2 + 132",
...
      ],
      "domain": "com.google.GIDSignIn",
      "userInfo": {
        "NSLocalizedDescription": "The user canceled the sign-in flow."
      }
    }
  ]
]
```
</details>

<details>
  <summary>with the diff from this PR</summary>

```
 (NOBRIDGE) LOG  own properties:  [
  "stack",
  "message",
  "code",
  "nativeStackIOS",
  "domain",
  "userInfo"
]
 (NOBRIDGE) LOG  own enumerable properties:  [
  [
    "code",
    "-5"
  ],
  [
    "nativeStackIOS",
    [
      "0   ReactTestApp                        0x000000010083b8f8 RCTJSErrorFromCodeMessageAndNSError + 112",
      "1   ReactTestApp                        0x0000000100b63534 ___ZZN8facebook5react15ObjCTurboModule13createPromiseERNS_3jsi7RuntimeENSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEEU13block_pointerFvU13block_pointerFvP11objc_objectEU13block_pointerFvP8NSStringSH_P7NSErrorEEENK3$_0clES4_RKNS2_5ValueEPSQ_m_block_invoke.57 + 332",
      "2   ReactTestApp                        0x0000000100704718 +[RNGoogleSignin rejectWithSigninError:withRejector:] + 548",
      "3   ReactTestApp                        0x0000000100704380 -[RNGoogleSignin handleCompletion:serverAuthCode:withError:withResolver:withRejector:fromCallsite:] + 184",
      "4   ReactTestApp                        0x00000001007041d4 -[RNGoogleSignin handleCompletion:withError:withResolver:withRejector:fromCallsite:] + 236",
      "5   ReactTestApp                        0x0000000100701f1c __40-[RNGoogleSignin signIn:resolve:reject:]_block_invoke_2 + 100",
      "6   ReactTestApp                        0x00000001006a30e8 __35-[GIDSignIn addCompletionCallback:]_block_invoke_2 + 132",
...
    ]
  ],
  [
    "domain",
    "com.google.GIDSignIn"
  ],
  [
    "userInfo",
    {
      "NSLocalizedDescription": "The user canceled the sign-in flow."
    }
  ]
]

```
</details>

You see there is a change compared to old arch because `message` is no longer own enumerable property. If that needs to change (I guess it should), it'd be nice if someone more familiar with JSI pointed me in the right direction. Even with this inconsistency, the PR is an improvement and would be nice to have this fix included in the next RC.

This is output from Chrome's console for completeness, just to have something to compare to:

```
let err = new Error('hello')
undefined
Object.getOwnPropertyNames(err)
> ['stack', 'message']
Object.entries(err)
> []
```

bypass-github-export-checks

## Changelog:

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

Pick one each for the category and type tags:

[IOS] [FIXED] - add missing fields to native errors in new arch

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

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

Test Plan: Tested locally with an example app running RN 74-rc 5

Reviewed By: cortinico

Differential Revision: D55690184

Pulled By: cipolleschi

fbshipit-source-id: 60a857b9871af888dcd526782b5e6b73c07c051a
2024-04-08 07:50:19 +01:00
Jean-Baptiste LARRIVIEREandNicola Corti 454e576b5b fix: build settings for custom build configuration (#43780)
Summary:
This allows build configuration named like `StagingDebug` to match with settings applied to `Debug` This fixes https://github.com/facebook/react-native/issues/43185

Custom build setting were only applied to `Debug` build configurations, preventing configurations named `StagingDebug` or similar to access the new experimental debugger, as reported in https://github.com/facebook/react-native/issues/43185

This now applies the setting to every configuration ending with `Debug`

## Changelog:

[IOS] [CHANGED] - fix: build settings for custom build configuration

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

Reviewed By: dmytrorykun

Differential Revision: D55688996

Pulled By: cipolleschi

fbshipit-source-id: 1f34cd722f6acfaa08d3377e19a04d08af97ed7c
2024-04-08 07:49:43 +01:00
Dmitry RykunandNicola Corti d0dd48b4c9 Print Hermes build script shell commands only in CI (#43767)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43767

Print Hermes build script shell commands only in CI.

Changelog: [Internal]

Reviewed By: cipolleschi

Differential Revision: D55635527

fbshipit-source-id: f0a901e11c523987e97a28b5238dcc08586516dd
2024-04-08 07:49:43 +01:00
Riccardo CipolleschiandGitHub 0e5dc51bba [Yoga][0.74] Fix archive for MacOS Catalyst (#43900) 2024-04-08 07:49:36 +01:00
Alex Hunt 82643e1a35 Update Podfile.lock
Changelog: [Internal]
2024-04-02 13:48:19 +01:00
Distiller 6abca78895 Release 0.74.0-rc.6
#publish-packages-to-npm&next
2024-04-02 11:04:49 +00:00
Szymon RybczakandGitHub 4f50089da2 Upgrade @react-native-community/cli to 13.6.4 (#43681) 2024-04-02 10:38:55 +01:00
phillipandGitHub 49bb2f37f1 [rn][ios][0.74][RC6] decouple RCTBridge+Private from jsinspector-modern (#43708) 2024-04-02 10:38:27 +01:00
Arushi KesarwaniandAlex Hunt dc851b6b3a React-Native-Restart in release (#43645)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43645

https://github.com/facebook/react-native/pull/43521 & https://github.com/facebook/react-native/pull/43588 aimed to fix `react-native-restart`, however in release `handleReloadJS()` is a no-op in [DisabledDevSupportManager](https://github.com/facebook/react-native/blob/ac714b1c3300d3a169bdcfec05d556e18a7b83ff/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DisabledDevSupportManager.java#L139) which is why this should not work. Fixing it by relying on `ReactHostImpl.reload()` instead for Bridgeless.

Adding implementation of `DisabledDevSupportManager.handleReloadJS()` won't work as it would mean introducing circular dependency `devsupport` -> `runtime`

Reviewed By: cortinico

Differential Revision: D55342296

fbshipit-source-id: ee6fba68586a2bdd1163522f75e6beb1b7736f6c
2024-04-02 10:37:19 +01:00
Ruslan LesiutinandAlex Hunt 9a286d65d1 fix[android]: fix bridgeless configuration to include DebuggingOverlay in react packages (#43661)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43661

# Changelog: [Internal]

1. Remove `BridgelessDebugReactPackage.java`, this was added in D43407534. Technically, its the same as `DebugCorePackage.java`.
2. `ReactInstance` to add `DebugCorePackage`, so `DebuggingOverlay` view manager will be included in the bridgeless build.
3. Fix `RNTesterApplication.kt` to NOT create `MyLegacyViewManager` for every possible viewManagerName, apart from `"RNTMyNativeView"`, return null instead.

Reviewed By: cortinico

Differential Revision: D55375350

fbshipit-source-id: 1d3cb6b5ad3c0248df1def9f37c8c49b308f4473
2024-04-02 10:36:59 +01:00
Ruslan LesiutinandAlex Hunt 1dc11cb2b3 fix: defer ReactDevToolsOverlay import (#43690)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43690

# Changelog: [Internal]

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

The issue is that once `getInspectorDataForViewAtPoint` is imported, it should throw if RDT global hook was not injected. ReactDevTools overlay imports `getInspectorDataForViewAtPoint`, this is why it did throw in testing environment.

ReactDevToolsOverlay JSX-element is already gated with RDT global hook check, adding a deferred import, same as it was already implemented for Inspector.

Still unclear to me how this didn't throw all this time while using the Catalyst / RNTester.

Reviewed By: cortinico

Differential Revision: D55474774

fbshipit-source-id: 759e5e8227cc7534193e5b95616b6099c15f5cb5
2024-04-02 10:36:34 +01:00
Andrew CoatesandAlex Hunt 5d63c85ced Add @types/react as optional peerDependency on packages that use it (#43509)
Summary:
Now that RN is providing TS type information, many of those .d.ts files depend on types from react.  In modern packagemanagers (Ex: pnpm) types/react will not be available to RN since it does not declare it as a dependency.

I also noticed that the types for react-native-popup-menu-android appear to be pointing to the wrong location.

Add types/react as a peerDependency on the packages that have .d.ts files that import from React.
Add types/react to peerDependencyMeta with optional:true to prevent users not using TS from requiring types/react.

[GENERAL] [ADDED] Added types/react as an optional peerDependency

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

Reviewed By: cortinico

Differential Revision: D55225940

Pulled By: NickGerleman

fbshipit-source-id: 4cbab071928cb925baec45f55461559acc9a54e6
2024-04-02 10:35:24 +01:00
CatStudioAppandAlex Hunt 462fbaef0c Update package.json to fix ccache_enabled option, fixes #43633 (#43634)
Summary:
I found in 0.74.0-rc.x, `ccache_enabled` is introduced. However, it is not being delivered via npm.

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

Changelog: [iOS] [Fixed] - Adding ccache_clang wrapper scripts to package.json for distribution

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

Reviewed By: cortinico

Differential Revision: D55308743

Pulled By: blakef

fbshipit-source-id: e89a4bb3a1fbf8562d880b4c9d25dc9083717ba6
2024-04-02 10:34:18 +01:00
Dmitry RykunandAlex Hunt d85f8b7e7a Set HERMES_RELEASE_VERSION correctly (#43699)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43699

This diff initializes `RELEASE_VERSION` with the value that is provided by the `get_react_native_version` job (it stores its output into `/tmp/react-native-version`).

Changelog: [Internal]

Reviewed By: fkgozali

Differential Revision: D55484988

fbshipit-source-id: f0b5bb473096f3691f50152beb3181a454916fdc
2024-04-02 10:33:29 +01:00
Dmitry RykunandAlex Hunt a37ba6f3ff Move IOS_DEPLOYMENT_TARGET and MAC_DEPLOYMENT_TARGET to the command body
Summary:
This diff moves IOS_DEPLOYMENT_TARGET and MAC_DEPLOYMENT_TARGET definitions to the command body.

Changelog: [Internal]

Reviewed By: fkgozali

Differential Revision: D55478563

fbshipit-source-id: bae327edbaf88a9e8b39b304d938389e3fc56f4f
2024-04-02 10:33:26 +01:00
Dmitry RykunandAlex Hunt f4b5bf1e14 Explicitly define IOS_DEPLOYMENT_TARGET and MAC_DEPLOYMENT_TARGET on CircleCI (#43683)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43683

This diff adds explicit definitions of IOS_DEPLOYMENT_TARGET and MAC_DEPLOYMENT_TARGET to `build_apple_slices_hermes` and `build_hermes_macos` jobs on CircleCI.
Eventually this will allow us to stop [interacting](https://github.com/facebook/react-native/blob/main/packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh#L28) with `hermes-engine.podspec` outside of the CocoaPods execution context, and make our CI jobs less error prone.

Changelog: [Internal]

Reviewed By: fkgozali, cortinico

Differential Revision: D55432703

fbshipit-source-id: dc1cc449ba60340d13db9e4d21970e4e3783f2da
2024-04-02 10:30:16 +01:00
Kevin GozaliandAlex Hunt 03237f449a Keep ES6Proxy enabled in bridgeless mode (#43538)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43538

The Hermes RuntimeConfig for bridgeless accidentally force-disabled ES6Proxy, resulting in https://github.com/facebook/react-native/issues/43523

Let's remove the incorrect override.

To test using RNTester, add the following change:

```
 diff --git a/packages/rn-tester/js/RNTesterAppShared.js b/packages/rn-tester/js/RNTesterAppShared.js
index 87cb6b69dfe..f2512d09c5a 100644
 --- a/packages/rn-tester/js/RNTesterAppShared.js
+++ b/packages/rn-tester/js/RNTesterAppShared.js
@@ -50,6 +50,8 @@ const RNTesterApp = ({
   );
   const colorScheme = useColorScheme();
+  new Proxy({}, {});
+
   const {
     activeModuleKey,
     activeModuleTitle,
```

Before this change, RNTester will get an error at start-up. After, the app loads correctly.

Changelog: [General][Fixed] Correctly keep ES6Proxy for bridgeless mode

Reviewed By: cortinico

Differential Revision: D55045780

fbshipit-source-id: 666b99712d35622f87d42f22a4611851df67d905
2024-04-02 10:29:43 +01:00
Alex Hunt d81065a621 [LOCAL] Update RNTester Podfile.lock 2024-04-02 10:29:27 +01:00
Distiller c0c3ac3f13 Release 0.74.0-rc.5
#publish-packages-to-npm&next
2024-03-25 13:57:17 +00:00
Nicola Corti cc6e734fa4 Revert "fix(iOS): add missing forward blocks to RCTRootViewFactory (#43638)"
This reverts commit eed035a3b6.
2024-03-25 12:18:44 +00:00
Arushi KesarwaniandNicola Corti f6757a20c6 Expose ReactDelegate for react-native-restart (#43588)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43588

Supported `reload()` in Bridgeless through ReactDelegate in https://github.com/facebook/react-native/pull/43521 in order to unblock react-native-restart

https://github.com/avishayil/react-native-restart/blob/134cabd5b3f355ffe551e5dd1be1dd46d870fe13/android/src/main/java/com/reactnativerestart/RestartModule.java#L54

which can access React Delegate through :
```
if(currentActivity instanceof ReactActivity) {
    ReactActivity reactActivity = (ReactActivity) currentActivity;
    ReactDelegate reactDelegate = reactActivity.getReactDelegate();
    reactDelegate.reload()
}
```

Changelog:
[Android][Added] Expose ReactDelegate in ReactActivity

Reviewed By: cortinico

Differential Revision: D55166962

fbshipit-source-id: 5d8dfd7ad61edbcb5233014800eb66a538842ca5
2024-03-25 10:45:35 +00:00
Arushi KesarwaniandNicola Corti 0e5ba6db2d Support reload in ReactDelegate (#43521)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43521

Changelog:
[Android] [Added] - Support reload() in ReactDelegate

Reviewed By: cortinico

Differential Revision: D54967602

fbshipit-source-id: adfa200cabcbecf9507775ac38f17c9d01b2671a
2024-03-25 10:45:00 +00:00
Arushi KesarwaniandNicola Corti 36d64312c8 Refactor ReactDelegate to provide DevSupportManager (#43520)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43520

Refactor ReactDelegate to have a private `getDevSupportManager()` that can also be re-used  by `reload()`

This method conditionally provides the correct DevSupportManager in cases of Bridge & Bridgeless

Changelog:
[Internal] internal

Reviewed By: cortinico

Differential Revision: D54967130

fbshipit-source-id: 37d585de33a50b98d01803d3080c5693a8c494b9
2024-03-25 10:44:47 +00:00
Arushi KesarwaniandNicola Corti 4fe26e3b2f Support onKeyLongPress in Bridgeless (#43472)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43472

Implement `onKeyLongPress` in Bridgeless

Changelog:
[Android][Breaking] Implement onKeyLongPress in Bridgeless

Reviewed By: cortinico

Differential Revision: D54876052

fbshipit-source-id: 88d572eab087d913205bdfa02dba96b169066393
2024-03-25 10:43:56 +00:00
Arushi KesarwaniandNicola Corti 8bf509ec44 Support onKeyDown in Bridgeless (#43466)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43466

Implement `onKeyDown` in Bridgeless by adding it to ReactHostImpl

Changelog:
[Android][Breaking] Implement `onKeyDown` in Bridgeless

Reviewed By: cortinico

Differential Revision: D54870966

fbshipit-source-id: 0f8e48b29679f1bca92f6ac7b6ebf1592cdc5dac
2024-03-25 10:43:30 +00:00
Arushi KesarwaniandNicola Corti 76463789fd Support onConfigurationChanged in Bridgeless (#43463)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43463

Implement `onConfigurationChanged` in Bridgeless by adding it to ReactHostImpl

Changelog:
[Android][Breaking] Implement onConfigurationChanged in Bridgeless

Reviewed By: cortinico, RSNara

Differential Revision: D54792399

fbshipit-source-id: 6851daca815f486f4d839e128a1d740d3fec1996
2024-03-25 10:42:52 +00:00
Arushi KesarwaniandNicola Corti dbc83220e0 Support onNewIntent in Bridgeless (#43401)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43401

Implement `onNewIntent` in Bridgeless by adding it to ReactHostImpl

Changelog:
[Android][Breaking] Implement `onNewIntent` in Bridgeless

Reviewed By: fkgozali, RSNara

Differential Revision: D54703159

fbshipit-source-id: fd8589d8131f4fa57188d493331dc68fb38c4520
2024-03-25 10:40:54 +00:00
Arushi KesarwaniandNicola Corti 5eea4cda1b Support onWindowFocusChange in Bridgeless (#43398)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43398

Implement onWindowFocusChange in Bridgeless by adding it to the ReactHostImpl

Changelog:
[Android][Breaking] Implement onWindowFocusChange in Bridgeless

Reviewed By: javache

Differential Revision: D54670119

fbshipit-source-id: 71f560e5a3bf0e853ac06955e67b8035f1ec0468
2024-03-25 10:40:25 +00:00
Nicola CortiandAlex Hunt 0f4234f450 Fix InteropUIBlockListener to support react-native-view-shot on Bridgeless (#43594)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43594

I've been migrating `react-native-view-shot` to Fabric by using the `InteropUiBlockListener`
and I've realized that the interop layer doesn't work well.

1. FabricUIManager needs to implement `UIBlockViewResolver` in order for the interop layer to work correctly.
2. We need to hook `addUIBlock` to the `didDispatchMountItems` callback otherwise the UIBlocks won't be executed at all.

Changelog:
[Android] [Fixed] - Fix InteropUIBlockListener to support react-native-view-shot on Bridgeless

Reviewed By: javache

Differential Revision: D55187939

fbshipit-source-id: d048b4b5eed77fa856fdfac17c0df5f23fd44844
2024-03-25 10:30:26 +00:00
Nick GerlemanandAlex Hunt 396d444e79 Fix Android HorizontalScrollView fling when content length less than ScrollView length (#43563)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43563

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

## Sumary

D9405703 added some custom logic for Flings, to support FlatList scenarios where content is being added on the fly, during Fling animation. This works by allowing start Fling to not have bounds, then correcting/cancelling Fling when overscroll happens over a bound that would normally be allowed.

This has some math to try to determine max content length, and will clamp to this when scrolling over it. This logic is incorrect when content length is less than scrollview length, and we end up snapping to a negative offset.

This change adds clamping, so that we don't snap to negative position in horizontal scroll view. This clamping was already indirectly present on vertical scroll view. https://www.internalfb.com/code/fbsource/[b43cdf9b2fec71f5341ec8ff2d47e28a066f052e]/xplat/js/react-native-github/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java?lines=609

## Test Plan

Above issue no longer reproes. Flinging while content is being added to horizontal FlatList still works correctly.

Changelog:
[Android][Fixed] - Fix Android HorizontalScrollView fling when content length less than ScrollView length

Reviewed By: javache

Differential Revision: D55108818

fbshipit-source-id: 7cf0065f9f92832cc2606d1c7534fc150407b9c9
2024-03-25 10:28:29 +00:00
Nick GerlemanandAlex Hunt 20bcf57ee3 Warn users during "pod install" if XCode is too old (#43583)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43583

Fail during `pod install` if user's version of XCode is too old to avoid cryptic errors (e.g. https://github.com/reactwg/react-native-releases/issues/163).

I reused existing mechanism for version detection, though it may not be reliable for future versions of XCode.

Changelog:
[iOS][Changed] - Warn users during "pod install" if XCode is too old

Reviewed By: dmytrorykun

Differential Revision: D55149636

fbshipit-source-id: 78387ff19a6eb10f3ca0d4aa78e6b934ae3b0711
2024-03-25 10:28:13 +00:00
Gabriel DonadelandAlex Hunt 33e3ec9426 Implement multiple view manager lookup for the interop layer on Android (#43595)
Summary:
When running with the new architurece and using the renderer interop layer on Android, view managers don't work if their names start with `RCT`. This happens because the `RCT` prefix is automatically removed from the component name, and inside the internal `mViewManagers` we store view managers with the `RCT` prefix.

Using the `RCT` pattern as a prefix works fine with the old architecture and is actually used on the [Android Native UI Components](https://reactnative.dev/docs/next/native-components-android) tutorial in the docs, making me believe that this same patterns is used across many community libraries.

This diff adds a secondary lookup logic for view managers:

1. We look for the XXXViewManager.
2. If not found, we look for RCTXXXViewManager.

Quite similar to the iOS implementation introduced in  https://github.com/facebook/react-native/pull/38093

 ---

With this change we can also remove most of the entries from FabricNameComponentMapping (I can address this in a follow up PR)

https://github.com/facebook/react-native/blob/4e6eba7a2dedaa855af0bff5df3bec73a95f0fc4/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/FabricNameComponentMapping.java#L22-L45

## Changelog:

[ANDROID] [ADDED] - Implement multiple view manager lookup for the interop layer

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

Test Plan:
Tested installing a library such as [react-native-fbsdk-next](https://github.com/thebergamo/react-native-fbsdk-next) that names its view managers starting with `RCT`

<table>
<tr>
  <th>Before</th>
  <th>After</th>
</tr>
<tr>
<td>
<img width="519" alt="image" src="https://github.com/facebook/react-native/assets/11707729/123de1d6-f018-424b-b6ce-38221af9d83e">
</td>
<td><img width="519" alt="image" src="https://github.com/facebook/react-native/assets/11707729/0f35b369-e2e4-4bbf-b880-6471fbc05d38">
</td>
</tr>
</table>

Reviewed By: cortinico

Differential Revision: D55208396

Pulled By: arushikesarwani94

fbshipit-source-id: a1fb1f4cee8483cf91ebededd1d7c4ba7021f9d9
2024-03-25 10:27:49 +00:00
Jakub PiaseckiandAlex Hunt 35f6000c66 Include boost headers needed by rrc_text and rrc_textinput (#43608)
Summary:
Updates `PreparePrefabHeadersTask` to copy more headers from `boost`, specifically those required by `rrc_text` and `rrc_textinput`.

## Changelog:

[ANDROID] [CHANGED] - Copy boost headers needed by `rrc_text` and `rrc_textinput`

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

Reviewed By: rshest

Differential Revision: D55241345

Pulled By: cortinico

fbshipit-source-id: e92164676ba78ee15b3678a55c9098b0c6214b69
2024-03-25 10:27:25 +00:00
Jakub PiaseckiandAlex Hunt 1d4b263d3d Fix prefab header paths for rrc_text and rrc_textinput (#43591)
Summary:
- `rrc_textinput` at the moment points to a wrong subdirectory and needlessly adds a prefix path
- `rrc_text` is missing headers for `attributedstring` which it depends on

## Changelog:

[ANDROID] [FIXED] - Fixed prefab header paths for `rrc_text` and `rrc_textinput`

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

Reviewed By: fkgozali

Differential Revision: D55199580

Pulled By: cortinico

fbshipit-source-id: 85126c00943f82e908a52e05587661597761852e
2024-03-25 10:26:24 +00:00
2c62dcabe5 [0.74] Fixes build from source on Android (#43616)
* fix(android): fix `ndkVersion` is unset when building from source (#43131)

Summary:
`ndkVersion` is unset when building from source using this guide: https://reactnative.dev/contributing/how-to-build-from-source

## Changelog:

[ANDROID] [FIXED] - Fix `ndkVersion` is unset when building from source

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

Test Plan:
```
git clone https://github.com/microsoft/react-native-test-app.git
cd react-native-test-app
npm run set-react-version nightly
yarn

# Manually apply the patch in node_modules/react-native/ReactAndroid/build.gradle.kts
# Enable building from source
sed -i '' 's/#react.buildFromSource/react.buildFromSource/' example/android/gradle.properties

# Build
cd example/android
./gradlew assembleDebug
```

Reviewed By: christophpurrer

Differential Revision: D54006425

Pulled By: cortinico

fbshipit-source-id: 9ede64bc14af4cf609b7a4c12c5a1082bbc31f09

* Fix build from source for hermes-engine (#43609)

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

When users are building from source for React Native they don't have an ndkVersion variable specified. So we want to fallback to the global NDK version we set for the whole build here.

Changelog:
[Android] [Fixed] - Fix build from source for hermes-engine

Reviewed By: dmytrorykun

Differential Revision: D55240603

fbshipit-source-id: 3c725a164b40e176548af8ada9fcb13d391ef017

---------

Co-authored-by: Tommy Nguyen <4123478+tido64@users.noreply.github.com>
2024-03-25 10:24:36 +00:00
eed035a3b6 fix(iOS): add missing forward blocks to RCTRootViewFactory (#43638)
* fix(iOS): add missing forward blocks to RCTRootViewFactory (#43526)

Summary:
This PR adds missing forwarding blocks to RCTRootViewFactory, currently when a user tries to override `sourceURLForBridge` in AppDelegate it isn't overridden.

## Changelog:

[IOS] [FIXED] - add missing forward blocks to RCTRootViewFactory

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

Test Plan: Override: `extraModulesForBridge`, `extraLazyModuleClassesForBridge`, `bridge didNotFindModule`,  `sourceURLForBridge:` methods in AppDelegate and check if they are called on old architecture

Reviewed By: philIip

Differential Revision: D55186872

Pulled By: cortinico

fbshipit-source-id: 5988c7bab1439ccc4885b7337336c1e120ba9ea6
(cherry picked from commit 9d79f05e68)

* Follow-up with Review Feedback on RCTAppDelegate from #43526 (#43607)

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

PR #43526 was accidentally merged with several changes excluded. I'm following up on those here.

Changelog:
[Internal] [Changed] - Follow-up with Review Feedback on RCTAppDelegate from #43526

Reviewed By: dmytrorykun

Differential Revision: D55240435

fbshipit-source-id: c296a1e14b7032b211551334ca7b5a6824e8d45c
(cherry picked from commit 84c1c6ea9b)

---------

Co-authored-by: Oskar Kwaśniewski <oskarkwasniewski@icloud.com>
Co-authored-by: Nicola Corti <ncor@meta.com>
2024-03-25 10:24:21 +00:00
Cedric van PuttenandAlex Hunt f3b9226ca0 fix(dev-middleware): create custom message handler for synthetic page (#43559)
Summary:
This is a follow-up bugfix for expo/expo#27425, related to:
 - https://github.com/facebook/react-native/issues/43291
 - https://github.com/facebook/react-native/issues/43307
 - https://github.com/facebook/react-native/issues/43310
 - https://github.com/facebook/react-native/issues/43364

The middleware API works as intended and can run our extended CDP events. Unfortunately, this only applies to an actual `Page` from the device, not for the `React Native Experimental (Improved Chrome Reloads)` synthetic / virtual page.

That's because the middleware instantiation gets aborted when the page can't be found in `this.#pages.get(pageId)`, which always returns `null` for this synthetic page.

## Changelog:

[GENERAL] [FIXED] Create custom message handler for synthetic page

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

Test Plan: See added test case.

Reviewed By: motiz88

Differential Revision: D55129412

Pulled By: huntie

fbshipit-source-id: 9679d8fe68f3cb4104f4a042f93612b995baddc9
2024-03-21 13:28:49 +00:00
Alex HuntandAlex Hunt 0a7dbfd1a2 Adjust version parsing in release scripts, fix release dry runs in CI (#43568)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43568

Fixes to restore passing CI checks on main after D55027120.

- Widen validation checks in version utils to accept `0.x.x` (as opposed to `0.[not-'0'].x`).
- Use `tag: test` instead of `tag: latest` for dry run job params.

Changelog: [Internal]

Reviewed By: cortinico

Differential Revision: D55123739

fbshipit-source-id: 9f76dced4e7aa3ce87d6680cd7687ae443305331
2024-03-20 17:42:06 +00:00
Alex HuntandAlex Hunt d66bb7f853 Remove bump-all-updated-packages script (#43534)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43534

This is no longer used after switching to the new release workflow, which uses the newer and less error-prone `set-version` script.

Changelog: [Internal]

Reviewed By: cortinico

Differential Revision: D55027122

fbshipit-source-id: faa8cfd2af9b54fab611b108df162793c5768695
2024-03-20 14:40:54 +00:00
Alex HuntandAlex Hunt 8b5d650e60 Switch to new release workflow as default (#43533)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43533

Switch to the new unified release workflow by default, now that this has been validated on the `0.74-stable` branch.

- Remove `--use-new-workflow` flag and remove legacy logic.
- Remove legacy `prepare_package_for_release` CI job, and use `run_new_release_workflow` -> `run_release_workflow` as new workflow condition match.

Changelog: [Internal]

Reviewed By: cortinico

Differential Revision: D55027120

fbshipit-source-id: 7c05cdff95ac369ce6cd1201ccfc5718798c4da6

# Conflicts:
#	scripts/releases-ci/prepare-package-for-release.js
2024-03-20 14:40:44 +00:00
Alex Hunt 32deb27219 Update RNTester Podfile.lock 2024-03-18 16:45:51 +00:00
Alex Hunt 24b1da16ea [LOCAL] Fix new release workflow script (4) 2024-03-18 16:02:31 +00:00
Distiller 907bd438ff Release 0.74.0-rc.4
#publish-packages-to-npm&next
2024-03-18 15:20:38 +00:00
Alex Hunt eadf9203bf [LOCAL] Fix new release workflow script (3) 2024-03-18 15:02:09 +00:00
Alex Hunt 8535f496d2 [LOCAL] Fix new release workflow script (2) 2024-03-18 14:31:58 +00:00
Alex Hunt d6ee80959e [LOCAL] Revert Podfile.lock error handling in CI script, remove same step from new workflow
It looks like this always failed (recent example from RC3: https://app.circleci.com/pipelines/github/facebook/react-native/42625/workflows/911813aa-8c1c-4c7f-8382-5d67d3551923/jobs/1396276), but since #43513 this now correctly raises as an error to CircleCI.

To unblock our release:
- Revert.
- Also remove "Updating RNTester Podfile.lock" entirely from `prepare_release_new` job — technically this isn't in the critical path for making a release, but is part of consistent branch state _post release_.

Changelog: [Internal]
2024-03-18 14:21:45 +00:00
Alex Hunt bdb1034e3e [LOCAL] Fix new release workflow script 2024-03-18 13:19:24 +00:00
Kudo ChienandAlex Hunt daf012a958 Add registerCallableModule types (#43366)
Summary:
`registerCallableModule()` was added from 7f549ec7be but no typescript types there. this pr tries to add the corresponding types.

## Changelog:

[GENERAL] [FIXED] - Add missing `registerCallableModule` TypeScript definitions

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

Test Plan: patch locally and try to `import { registerCallableModule } from 'react-native';` in a 0.74.0-rc.2 project

Reviewed By: fabriziocucci

Differential Revision: D54676151

Pulled By: cortinico

fbshipit-source-id: cd01f2ebe2d2516b458fae5b2e83cba3d3794455
2024-03-18 11:09:04 +00:00
Alex HuntandAlex Hunt 40a4df0637 Fix RNTester Podfile.lock update in release workflow (#43513)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43513

The previous `update_podfile_lock.sh` script would fail as executed from the repo root (could not locate RNTester dir). Delete this and replace with direct calls in `prepare-package-for-release.js`, which will fail script on error.

 {F1469216632}

Changelog: [Internal]

Reviewed By: cortinico

Differential Revision: D54949214

fbshipit-source-id: 4f032069e803e84f835c279d01332d16787dfafc
2024-03-18 11:09:04 +00:00
Alex HuntandAlex Hunt ff5d87db3e Fix E2E template install in CI jobs (#43323)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43323

This fixes a seemingly pre-existent misconfiguration within our `test_ios_template` E2E test setup in CircleCI.

**Background**

We call `npx react-native-community/cli init` with the `--skip-install` flag, as part of the bootstrapping logic in `scripts/e2e/init-template-e2e.js`. This is necessary because we later want to explicitly call `npm install` with a custom `--registry` for our locally mirrored packages (via Verdaccio).

For some reason, we were observing unexpected differences when this was run under CircleCI:

1. Runs `yarn init`
2. Runs a `yarn add` (unknown pkg)

 {F1464781818}

https://app.circleci.com/pipelines/github/facebook/react-native/42725/workflows/f648468b-e916-4501-887d-ad293aa6fccf/jobs/1398950

This is causing a Yarn-based install ahead of where we want — ignoring the `--skip-install` flag.

*I'm still unsure on the exact LOC cause in CLI* (but most likely, it's around the Yarn v3 move).

**Impact of this fix**

- The above meant that, when we were bootstrapping `test_ios_template` previously, packages weren't being read from Verdaccio, but **instead from npm** — using the `"0.74.0"` versions from the *previous branch cut* .
- After D54006327, this behaviour became breaking 💀 — since for the 0.74 -> 0.75 cut, we no longer physically published `"0.75.0-main"` (new format) packages to npm.

**This change**

I'm passing `--pm npm` to `npx react-native-community/cli init` to skip around any Yarn behaviour. This appears to have removed the erroneous `yarn` invocations .

Changelog: [Internal]

bypass-github-export-checks

Reviewed By: cortinico, cipolleschi

Differential Revision: D54536848

fbshipit-source-id: 473b11924955f5787c82a6c81d4527d77b810aa5
2024-03-18 11:09:04 +00:00
Alex HuntandAlex Hunt 4e677f021a Update set-version script to version private packages and workspace deps
Summary:
Addresses a gap when using the `set-version` script to update all packages on `main` (i.e. post branch cut):
- Package versions were not being set consistently. It is safe to version all workspace packages, including `"private"`.
    - Our publishing workflow is independent from this, and only considers public packages for submission to npm.
- We also need to update the root `package.json`, which includes `devDependencies` referencing workspace dependencies.

Unblocks https://github.com/facebook/react-native/pull/43132.

Changelog: [Internal]

Reviewed By: lunaleaps

Differential Revision: D54419456

fbshipit-source-id: 93eee669c5cf7c2f16b68a2bf41e9a8ace5521bf
2024-03-18 11:09:04 +00:00
Alex HuntandAlex Hunt 42e62bf963 Refactor remaining forEachPackage call sites (#43112)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43112

Changelog: [Internal]

Reviewed By: cipolleschi

Differential Revision: D53942028

fbshipit-source-id: 335bff3c3a31026bae7140fac1d1a6aae23a0f1e
2024-03-18 10:58:13 +00:00
Alex HuntandAlex Hunt 3b170a0910 Add prepare_release_new workflow, configure via flag (#43518)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43518

This is a minimum approach to achieve a **single-command publish flow** for React Native, unifying the previous `yarn bump-all-updated-packages` and `yarn trigger-react-native-release` workflow entry points.

This diff aims to change as little as possible to achieve the above — introducing a new job that merges operations to create the versioning commit. The triggered publish jobs are unchanged. In future, we may follow this change with further simplifications down the workflow tree.

**Key changes**

- Adds a new CircleCI workflow, `prepare_release_new`, which versions **all packages** and writes a single release commit.
- This replaces `yarn bump-all-updated-packages`, now implemented with the newer `set-version` script.
- Wires this up as an experiment within `trigger-react-native-release.js`, conditionally running the new workflow when `--use-new-workflow` is passed.

**Not changed**

- The single release commit written will continue to trigger both of the existing CI workflows on push (`publish_release` and `publish_bumped_packages`), which are unchanged.
    - The commit summary now includes the `#publish-packages-to-npm` marker, in order to trigger `publish_bumped_packages`.
- Usage: Release Crew members will continue to use the existing local script entry point (as [documented in the releases repo](https://github.com/reactwg/react-native-releases/blob/main/docs/guide-release-process.md#step-7-publish-react-native)), with the opt in flag.
    ```
    yarn trigger-react-native-release --use-new-workflow [...args]
    ```

After we're happy with the E2E behaviour of this workflow in the next 0.74 RC, I will follow up by dropping the `--use-new-workflow` flag and removing the old scripts (T182533699).

Changelog: [Internal]

Reviewed By: cortinico

Differential Revision: D54956345

fbshipit-source-id: 35fd7af8f3e60a39507b5d978ccd97472bf03ddb
2024-03-18 10:41:28 +00:00
Alex HuntandAlex Hunt 680bfafcc2 Remove dangerous "9999" version string default (#43516)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43516

As titled. This seems dangerous — removing with the motivation that we'd prefer this script to fail during execution than to succeed in publishing `9999`.

Changelog: [Internal]

Reviewed By: cortinico

Differential Revision: D54956661

fbshipit-source-id: 23f8d49abd300385dde74871b6d2492ef63f058e
2024-03-18 10:41:16 +00:00
Phillip PanandAlex Hunt ffb93a81b5 support jsCallInvoker in RCTBridgeProxy (#43314)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43314

Changelog: [Internal]

making call invoker a breaking change to runtime executor in 0.74 seems to be causing a lot of discourse. let's simplify things and first add the callinvoker to the backwards compat layer

Reviewed By: cipolleschi

Differential Revision: D54404845

fbshipit-source-id: 983e86829030557033b95625dab9068492739417
2024-03-18 10:39:47 +00:00
Arushi KesarwaniandAlex Hunt 9048c0e0b3 Fix Bridgeless React Context test in OSS (#43424)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43424

https://github.com/facebook/react-native/pull/43400/ caused a `getCatalystInstanceTest` to fail in OSS due to `bridgelessReactContext` not being a Mock object.

Reviewed By: fkgozali

Differential Revision: D54781539

fbshipit-source-id: 1c784804c31d4b57fe438d49f3ee3eb7034dd7a6
2024-03-18 10:37:44 +00:00
Arushi KesarwaniandAlex Hunt bccedff09b Implement getJSCallInvokerHolder for BridgelessCatalystInstance (#43400)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43400

Implement `getJSCallInvokerHolder()` for BridgelessCatalystInstance

Changelog:
[Android][Breaking] Implement `getJSCallInvokerHolder()` for Bridgeless Catalyst Instance

Reviewed By: cortinico

Differential Revision: D54650305

fbshipit-source-id: effac3daaad5173c2fd78ab11bbe3f3156a9c07b
2024-03-18 10:37:27 +00:00
Arushi KesarwaniandAlex Hunt 3e5dd5e2f2 Fix CI by adding explicit visibility modifier to BridgelessCatalystInstance (#43296)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43296

Fix CI by adding explicit visibility modifier to the newly added `BridgelessCatalystInstance` class. In Kotlin, in explicit API mode, which is usually the default mode for Kotlin, we must explicitly specify one of the modifiers for every declaration to make it clear and explicit.

Changelog:
[Internal] internal

Reviewed By: makovkastar

Differential Revision: D54442485

fbshipit-source-id: 4409ff810a09cc4fadcd2ccf21f7fbac3015f413
2024-03-18 10:37:22 +00:00
Arushi KesarwaniandAlex Hunt 8a04e4418a Add BridgelessCatalystInstance as a placeholder for backwards comptability of legacy APIs of CatalystInstance
Summary:
In order to make the legacy APIs of Catalyst Instance backwards compatible, introducing a regular class that implements CatalystInstance so as to make these APIs available for folks in Bridgeless mode as well.

Changelog:
[Internal] internal

Reviewed By: RSNara

Differential Revision: D54093013

fbshipit-source-id: f494c05e79f570883f9b5374cd177862970304c0
2024-03-18 10:37:00 +00:00
Riccardo CipolleschiandAlex Hunt ec48cb6560 Allow the app to control the Activity Indicator in Bridgeless mode (#43195)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43195

Right now, the activity indicator is automatically hidden when the view is ready to be shown in bridgeless mode.
There is no way to prevent that the activity indicator is automatically removed.

In OSS, we have libraries (e.g.: `react-native-bootsplash`) that will allow the app to control when and how dismiss the splashscreen, but due to the current automatic behavior on Bridgeless, they stopped working.

***Note:** In the previous implementation, they were working because instead of using the `loadingView` property, they were adding the splashscreen view on top of the existing one. However, with the lazy behavior of the bridgeless mode, this is not working anymore because the RCTMountingManager [expect not to have any subview](https://www.internalfb.com/code/fbsource/[6962fa457dbc74ab3a760cf6090d9643c6748781]/xplat/js/react-native-github/packages/react-native/React/Fabric/Mounting/RCTMountingManager.mm?lines=176) when the first surface is mounted.*

## Changelog
[iOS][Added] - Allow the activityIndicator to be controlled from JS in bridgeless mode

Reviewed By: philIip

Differential Revision: D54191856

fbshipit-source-id: 14738032f04adf7eaf7d200d889acd752aed0ed3
2024-03-18 10:31:50 +00:00
Cedric van PuttenandAlex Hunt 768cf6e79c feature(dev-middleware): add custom message handlers to extend CDP capabilities (#43291)
Summary:
This is a proposal for the `react-native/dev-middleware` package, to allow implementers to extend the CDP capabilities of the `InspectorProxy`. It's unfortunately needed until we can move to the native Hermes CDP layer.

At Expo, we extend the CDP capabilities of this `InspectorProxy` by injecting functionality on the device level. This proposed API does the same, but without having to overwrite internal functions of both the `InspectorProxy` and `InspectorDevice`.

A good example of this is the network inspector's capabilities. This currently works through the inspection proxy, and roughly like:
- Handle any incoming `Expo(Network.receivedResponseBody)` from the _**device**_, store it, and stop event from propagating
- Handle the incoming `Network.getResponseBody` from the _**debugger**_, return the data, and stop event from propagating.

This API brings back that capability in a more structured way.

## API:

```ts
import { createDevMiddleware } from 'react-native/dev-middleware';

const { middleware, websocketEndpoints } = createDevMiddleware({
  unstable_customInspectorMessageHandler: ({ page, deviceInfo, debuggerInfo }) => {
    // Do not enable handler for page other than "SOMETHING", or for vscode debugging
    // Can also include `page.capabilities` to determine if handler is required
    if (page.title !== 'SOMETHING' || debuggerInfo.userAgent?.includes('vscode')) {
      return null;
    }

    return {
      handleDeviceMessage(message) {
        if (message.type === 'CDP_MESSAGE') {
          // Do something and stop message from propagating with return `true`
          return true;
        }
      },
      handleDebuggerMessage(message) {
        if (message.type === 'CDP_MESSAGE') {
          // Do something and stop message from propagating with return `true`
          return true;
        }
      },
    };
  },
});
```

## Changelog:

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

Pick one each for the category and type tags:

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

[GENERAL] [ADDED] - Add inspector proxy device message middleware API

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

Test Plan: See added tests and code above

Reviewed By: huntie

Differential Revision: D54804503

Pulled By: motiz88

fbshipit-source-id: ae918dcd5b7e76d3fb31db4c84717567ae60fa96
2024-03-18 10:30:57 +00:00
Cedric van PuttenandAlex Hunt bf7f0d57cc feature(dev-middleware): use userAgent query parameter as fallback when header is unset (#43364)
Summary:
At Expo, we use [Expo Tools](https://github.com/expo/vscode-expo/blob/main/src/expoDebuggers.ts) to connect the [built-in vscode-js-debug](https://github.com/microsoft/vscode-js-debug) to Hermes.

Since there are a few differences in vscode vs chrome devtools, we need to enable a couple of modifications through the [`customMessageHandler` API](https://github.com/facebook/react-native/pull/43291). Unfortunately, vscode itself doesn't set the `user-agent` header when connecting to the inspector proxy. Becuase of that, we'd need a fallback to "manually" mark the debugger as being vscode ([we use this query parameter here](https://github.com/expo/vscode-expo/blob/main/src/expoDebuggers.ts#L208)).

This PR supports setting the `user-agent` through `?userAgent=` when the header is not set.

## Changelog:

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

Pick one each for the category and type tags:

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

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

[GENERAL] [ADDED] - Fallback to query parameter based `user-agent` when header is unset

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

Test Plan:
- Install [Expo Tools](https://marketplace.visualstudio.com/items?itemName=expo.vscode-expo-tools)
- Start Metro with this change.
- Connect a device.
- Run the vscode command `"Expo: Debug Expo app ..."`
- Debugger should connect, and have it's user-agent marked as:
    `vscode/1.87.0 vscode-expo-tools/1.3.0`

Reviewed By: huntie

Differential Revision: D54804556

Pulled By: motiz88

fbshipit-source-id: 1ff558ba5350811ad042d08a713438e046759feb
2024-03-18 10:30:42 +00:00
Cedric van PuttenandAlex Hunt 0e0838448a fix(dev-middleware): allow inspector proxy to fetch sourcemaps on lan connections (#43307)
Summary:
The inspector proxy is inlining source maps on `Debugger.scriptParsed` CDP events. The inlining prevents Chrome DevTools from downloading this remotely, as that's not supported in newer versions anymore.

The current implementation locks this inlining mechanism to just `localhost` and/or `127.0.0.1` addresses, making it incompatible with LAN or tunnel device connections.

This PR removes that limitation to allow source map inlining on these LAN and tunnel connections.

## Changelog:

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

Pick one each for the category and type tags:

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

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

[GENERAL][FIXED] Allow Inspector proxy to inline source maps on LAN connections

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

Test Plan:
- See added test
- Start Metro and connect a device over LAN, open the chrome devtools

Reviewed By: huntie

Differential Revision: D54485247

Pulled By: robhogan

fbshipit-source-id: 6fcb0c6dd762d2f0a013497ba0a1126095b9130b
2024-03-18 10:30:25 +00:00
Nicola CortiandAlex Hunt 0f4aedfe82 Properly handle RR and CMD+M in Bridgeless Mode (#43460)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43460

Currently pressing the menu button (or CMD+M) is broken on Bridgeless mode.
Also pressing RR is not reloading the App.
That's because some Bridgeless API haven't been reimplemented correctly on Android. I'm fixing them here.

Fixes #43451

Changelog:
[Android] [Fixed] - Properly handle RR and CMD+M in Bridgeless Mode

Reviewed By: huntie

Differential Revision: D54852959

fbshipit-source-id: 8fbbdab6818da9177e6db40e45d35258c7f5e236
2024-03-18 10:28:40 +00:00
Dmitry RykunandAlex Hunt 407be885fa Bring back the UNSET constant to TextAttributeProps (#43491)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43491

This diff brings back the `UNSET` constant to `TextAttributeProps`.
The removal of this constant was an unnecessary breaking change, that has broken several third-party libraries.

Changelog: [Android][Fixed] - Bring back the UNSET constant to TextAttributeProps.

Reviewed By: fabriziocucci

Differential Revision: D54899524

fbshipit-source-id: 368bde77d43f310fd458537d0191d09174fa5167
2024-03-18 10:28:17 +00:00
zhongwuzwandAlex Hunt aa0670b0ae iOS: Change image source url encode ascii to utf8 (#43502)
Summary:
We should use utf8 to cover more characters.

## Changelog:

[IOS] [FIXED] - [Fabric] iOS: Change image source url encode ascii to utf8

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

Test Plan: Fixes https://github.com/facebook/react-native/issues/43462

Reviewed By: rshest

Differential Revision: D54944653

Pulled By: cortinico

fbshipit-source-id: 0bbd3d46c8e5c04ceffe7e0ebae46dc2ce9507df
2024-03-18 10:27:57 +00:00
Joe VilchesandAlex Hunt 8830ed6bba Fix bug where absolute nodes were not insetted correctly in certain cases (#43417)
Summary:
X-link: https://github.com/facebook/yoga/pull/1593

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

There was a bug where we did not position absolute nodes correctly if the static node had a different main/cross axis from the containing node. This fixes that. The change is somewhat complicated unfortunately but I tried to add sufficient comments to explain what is happening

Reviewed By: NickGerleman

Differential Revision: D54703955

fbshipit-source-id: 096c643f61d4f9bb3ee6278d675ebd69b57350d7
2024-03-18 10:27:38 +00:00
szymonrybczakandAlex Hunt bc745cb6ff Update @react-native-community/cli to 13.6.2 2024-03-12 14:45:49 +00:00
Alex Hunt 24d3251d3f Update Podfile.lock 2024-03-12 10:09:39 +00:00
Distiller 57cc8e7f67 [0.74.0-rc.3] Bump version numbers 2024-03-11 14:59:31 +00:00
Alex Hunt 8a7c718ab3 Bump package versions
#publish-packages-to-npm&0.74-stable
2024-03-11 13:53:12 +00:00
Cedric van PuttenandAlex Hunt 4efab59a1e feature(dev-middleware): add inspector proxy nativeNetworkInspection target capabilty flag (#43310)
Summary:
This adds the `nativeNetworkInspection` target capability flag, to enable/disable the proxy-side network inspection handling.

## Changelog:

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

Pick one each for the category and type tags:

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

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

[GENERAL][ADDED] Add inspector proxy `nativeNetworkInspection` target capability flag

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

Test Plan:
Once this lands, and is published through `react-native/dev-middleware`, we (Expo) can disable the proxy-side network inspection handling.

See https://github.com/expo/expo/pull/27425/commits/1a1b601a29fbc5766628238db7259121689f6cd6 on PR expo/expo#27425

Reviewed By: christophpurrer, motiz88

Differential Revision: D54486516

Pulled By: huntie

fbshipit-source-id: cc151349c816fb3866d3ec07af1a29a5f4ff9b00
2024-03-11 11:01:17 +00:00
Oskar KwaśniewskiandAlex Hunt e3da9b8c0a fix: add compiler conditional to hover style (#43331)
Summary:
Commit https://github.com/facebook/react-native/commit/73664f576aaa472d5c8fb2a02e0ddd017bbb2ea4 broke two jobs in CircleCI that we run using Xcode 14.3.1 because the commit introduced some types that are available only to iOS 17.
The code was wrapped around if(available()) statement, but this does not compile out the code. It is a runtime check and the code needs to build anyway.

This takes effect at compile time as well. However, unlike with #available, the method must type check and compile. The code will always be emitted into your binary: however, it will only be used when the binary is executed on platforms that meet the availability requirements.

source: [forums.swift.org/t/if-vs-available-vs-if-available/40266/2](https://forums.swift.org/t/if-vs-available-vs-if-available/40266/2)

This change should fix it, introducing some compile time pragmas that removes the code if we build with older versions of Xcode

## Changelog:

[IOS] [ADDED] - Compiler conditionals for hover style (cursor: pointer)

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

Test Plan: CI Green

Reviewed By: dmytrorykun

Differential Revision: D54540520

Pulled By: cipolleschi

fbshipit-source-id: 943ac479062e11969efa7645ec0ead26c6866374
2024-03-11 10:59:17 +00:00
Saad NajmiandAlex Hunt 7395765cf8 feat(iOS): Implement cursor style prop (#43078)
Summary:
Implement the cursor style prop for iOS (and consequently, visionOS), as described in this RFC: https://github.com/react-native-community/discussions-and-proposals/pull/750

See related PR in React Native macOS, where we target macOS and visionOS (not running in iPad compatibility mode) with the same change: https://github.com/microsoft/react-native-macos/pull/2080

Docs update: https://github.com/facebook/react-native-website/pull/4033

## Changelog:

[IOS] [ADDED] - Implement cursor style prop

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

Test Plan:
See the added example page, running on iOS with the new architecture enabled. This also runs the same on the old architecture.

https://github.com/facebook/react-native/assets/6722175/2af60a0c-1c1f-45c4-8d66-a20f6d5815df

See the example page running on all three apple platforms. The JS is slightly different because:
1. The "macOS Cursors" example is not part of this PR but the one in React Native macOS.
2. This PR (and exapmple) has went though a bunch of iterations and It got hard taking videos of every change 😅

https://github.com/facebook/react-native/assets/6722175/7775ba7c-8624-4873-a735-7665b94b7233

## Notes

- React Native macOS added the cursor prop to View with https://github.com/microsoft/react-native-macos/pull/760 and Text with https://github.com/microsoft/react-native-macos/pull/1469 . Much of the implementation comes from there.

- Due to an Apple bug, as of iOS 17.4 Beta 4, the shape of the iOS cursor hover effect doesn't render in the correct bounds (but it does on visionOS). I've worked around it with an ifdef. The result is that the hover effect will work on iOS and visionOS, but not iPad apps running in compatibility mode on visionOS.

Reviewed By: NickGerleman

Differential Revision: D54512945

Pulled By: vincentriemer

fbshipit-source-id: 699e3a01a901f55a466a2c1a19f667aede5aab80
2024-03-11 10:58:03 +00:00
Oskar KwaśniewskiandAlex Hunt 66b1cfee97 feat(RCTAppDelegate): Implement RCTRootViewFactory (#42263)
Summary:
This PR implements `RCTRootViewFactory` a utility class (suggested by cipolleschi) that returns proper RCTRootView based on the current environment state (new arch/old arch/bridgeless). This class aims to preserve background compatibility by implementing a configuration class forwarding necessary class to RCTAppDelegate.

This PR leverages the `RCTRootViewFactory` in `RCTAppDelegate` for the default initialization of React Native (greenfield).

Here is an example of creating a Brownfield integration (without RCTAppDelegate) using this class (can be later added to docs):

1. Store reference to `rootViewFactory` and to `UIWindow`

`AppDelegate.h`:
```objc
interface AppDelegate : UIResponder <UIApplicationDelegate>

property(nonatomic, strong) UIWindow* window;
property(nonatomic, strong) RCTRootViewFactory* rootViewFactory;

end
```

2. Create an initial configuration using `RCTRootViewFactoryConfiguration` and initialize `RCTRootViewFactory` using it. Then you can use the factory to create a new `RCTRootView` without worrying about old arch/new arch/bridgeless.

 `AppDelegate.mm`
```objc
implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary<UIApplicationLaunchOptionsKey,id> *)launchOptions {

  // Create configuration
 RCTRootViewFactoryConfiguration *configuration = [[RCTRootViewFactoryConfiguration alloc] initWithBundleURL:self.bundleURL
                                                                                                 newArchEnabled:self.fabricEnabled
                                                                                             turboModuleEnabled:self.turboModuleEnabled
                                                                                              bridgelessEnabled:self.bridgelessEnabled];

  // Initialize RCTRootViewFactory
  self.rootViewFactory = [[RCTRootViewFactory alloc] initWithConfiguration:configuration];

  // Create main root view
  UIView *rootView = [self.rootViewFactory viewWithModuleName:@"RNTesterApp" initialProperties:@{} launchOptions:launchOptions];

  // Set main window as you prefer for your Brownfield integration.
  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  UIViewController *rootViewController = [UIViewController new];
  rootViewController.view = rootView;
  self.window.rootViewController = rootViewController;
  [self.window makeKeyAndVisible];

  // Later in the codebase you can initialize more rootView's using rootViewFactory.

  return YES;
}
end
```
bypass-github-export-checks

[INTERNAL] [ADDED] - Implement RCTRootViewFactory

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

Test Plan: Check if root view is properly created on app initialization

Reviewed By: dmytrorykun

Differential Revision: D53179625

Pulled By: cipolleschi

fbshipit-source-id: 9bc850965ba30d84ad3e67d91dd888f0547c2136
2024-03-11 10:54:06 +00:00
Tomek ZawadzkiandAlex Hunt 6440e35bc7 Expose react_render_textlayoutmanager via prefab (#43381)
Summary:
The `react_render_textlayoutmanager` was not exposed via prefab. I'm adding it to make possible for react-native-live-markdown to integrate on top of React Native via prefab. Based on https://github.com/facebook/react-native/issues/36166.

## Changelog:

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

Pick one each for the category and type tags:

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

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

[ANDROID] [CHANGED] - Expose `react_render_textlayoutmanager` via prefab.

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

Reviewed By: javache

Differential Revision: D54676207

Pulled By: cortinico

fbshipit-source-id: 90e3b90ff842250bf1e3abcc0c54f057b68a82fd
2024-03-11 10:49:09 +00:00
Arushi KesarwaniandAlex Hunt 10d65924ee Support onActivityResult in Bridgeless (#43351)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43351

Implement `onActivityResult` on Bridgeless

Changelog:
[Internal] internal

Reviewed By: cortinico

Differential Revision: D54574139

fbshipit-source-id: f2369077199186ac6ef0187b5dfe7ed95f3b87fc
2024-03-11 10:43:48 +00:00
Rick HanlonandAlex Hunt 31b62ab7f0 Fix component stacks for tsx, ts, and jsx files (#43370)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43370

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

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

Reviewed By: yungsters

Differential Revision: D54638526

fbshipit-source-id: a5271daaa7b687e8e075be3f94ab9b9c03f79b66
2024-03-11 10:41:29 +00:00
Pieter De BaetsandAlex Hunt 1151ea1247 Fix DefaultReactNativeHost assuming lazyViewManagers are always available (#43334)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43334

cortinico flagged that bridge + fabric regressed in 0.74, likely due to D53406841.

Changelog: [Android][Fixed] Fix registration of ViewManagers in new renderer when not using lazyViewManagers.

Reviewed By: fkgozali

Differential Revision: D54551645

fbshipit-source-id: 0783030cd0d2900a3a254ae04c9ea4e51035272a
2024-03-11 10:39:14 +00:00
Oskar KwaśniewskiandAlex Hunt a9ec4203e1 fix(iOS) [0.74]: RCTRedBox not appearing in Bridgeless when metro is not running (#43147)
Summary:
When testing out `0.74.0-rc0` I found that when the metro is not running we are not displaying RedBox which bumps users to start the packager and reload the app. It also fixes the case where users try to reload by clicking the "Reload" button on RedBox.

## Before

https://github.com/facebook/react-native/assets/52801365/086c557f-ea1f-4a97-b4c7-df8a945cc7a0

## After

https://github.com/facebook/react-native/assets/52801365/9f8421b3-5e83-466f-8cdb-38f97981275d

## Changelog:

[IOS] [FIXED] - RCTRedBox not appearing in Bridgeless when metro is not running

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

Test Plan: Build the app without metro running check if RedBox is shown

Reviewed By: javache

Differential Revision: D54632056

Pulled By: dmytrorykun

fbshipit-source-id: fb6742898d3bd82545bfffd9175208e1a5984cb6
2024-03-11 10:37:10 +00:00
Pieter De BaetsandAlex Hunt bd39897abf Fix NullPointerException thrown on startup (#43293)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43293

Was debugging this, and found that this exception was being thrown due to `DefaultBindingsInstaller`, which was an invalid hybrid object. The ReactInstance initializer fully supports this being null, so let's use that as default.

Changelog: [Android][Fixed] NullPointerException is no longer ignored in MessageQueueThreadHandler

Reviewed By: sammy-SC

Differential Revision: D54434417

fbshipit-source-id: 52417b390061eface0f0578e32796d3a85303e03
2024-03-11 10:34:28 +00:00
Tomek ZawadzkiandAlex Hunt 7c2fb7911a Expose rrc_text via prefab (#43275)
Summary:
The `rrc_text` was not exposed via prefab. I'm adding it to make possible for react-native-live-markdown to integrate on top of React Native via prefab. Based on https://github.com/facebook/react-native/issues/36166.

## Changelog:

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

Pick one each for the category and type tags:

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

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

[ANDROID] [CHANGED] - Expose `rrc_text` via prefab.

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

Reviewed By: cipolleschi

Differential Revision: D54536468

Pulled By: cortinico

fbshipit-source-id: 8c4ef983467bfc46930f10bf7bd95761c2d11788
2024-03-11 10:33:39 +00:00
Tomek ZawadzkiandAlex Hunt 4dc9d54447 Expose rrc_textinput via prefab (#43274)
Summary:
The `rrc_textinput` was not exposed via prefab. I'm adding it to make possible for react-native-live-markdown to integrate on top of React Native via prefab. Based on https://github.com/facebook/react-native/issues/36166.

## Changelog:

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

Pick one each for the category and type tags:

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

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

[ANDROID] [CHANGED] - Expose `rrc_textinput` via prefab.

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

Reviewed By: cipolleschi

Differential Revision: D54482657

Pulled By: cortinico

fbshipit-source-id: ca7f4127f1808f841d88925238666e837de75bd0
2024-03-11 10:33:21 +00:00
Luna Wei 27b54bdcff local - podfile.lock update for rntester 2024-03-04 14:13:09 -08:00
Distiller c68669079a [0.74.0-rc.2] Bump version numbers 2024-03-04 19:42:11 +00:00
Luna Wei 1c1b03d6e8 bumped packages versions
#publish-packages-to-npm&0.74-stable
2024-03-04 11:29:35 -08:00
Luna Wei c7e704a0ef bumped packages versions
#publish-packages-to-npm&0.74-stable
2024-03-04 11:29:15 -08:00
Luna Wei 02d38e4eb5 bumped packages versions
#publish-packages-to-npm&0.74-stable
2024-03-04 11:28:55 -08:00
Luna Wei e063a1b0fb bumped packages versions
#publish-packages-to-npm&0.74-stable
2024-03-04 11:27:34 -08:00
Alex Hunt c09e4dacff Bump package versions
#publish-packages-to-npm&0.74-stable
2024-03-04 12:14:00 +00:00
Alex Hunt 011cb3a8d7 Update Podfile.lock 2024-03-04 12:11:28 +00:00
Riccardo CipolleschiandAlex Hunt a5b5f6be78 Rename PopupMenuAndroidNativeComponent.js to PopupMenuAndroidNativeComponent.android.js to fix CI
Summary:
This change renames `PopupMenuAndroidNativeComponent.js` to `PopupMenuAndroidNativeComponent.android.js`.

The reason is that, without the suffix, Codegen was reading the NativeComponent spec also for iOS, generating some invalid specs and making RNTester fail.

## Changelog:
[Android][Changed] - Rename `PopupMenuAndroidNativeComponent.js` to `PopupMenuAndroidNativeComponent.android.js`

Reviewed By: cortinico, dmytrorykun

Differential Revision: D54199736

fbshipit-source-id: 7fd67c4d38a69fe3a84c800c8ee5dcbd8c4f9a6c
2024-03-04 11:02:58 +00:00
Ramanpreet NaraandAlex Hunt 29b34e70e3 Pull PopupMenuAndroid out of React Native core
Summary:
**History:** This component was originally introduced into React Native core in D52712758, to replace UIManagerModule.showPopupMenu().

**Problem:** But, React Native core should be lean. Adding this component to React Native bloats the core.

**Changes:** So, this diff pulls PopupMenuAndroid out into its own package in the react-native GitHub repository.

In the future, this will be migrated to a community package!

Changelog: [Android][Removed] Move PopupMenu out of React Native core

Reviewed By: NickGerleman

Differential Revision: D53328110

fbshipit-source-id: 469d8dc3e756c06040c72e08fa004aafa1bd6e18
2024-03-04 11:02:52 +00:00
Nicola CortiandAlex Hunt 6294453980 Undo moving of TurboModule to internal and expose utility function for TurboModule.class.isAssignableFrom (#43219)
Summary:
After discussing with mdvacca, we prefer to undo the change of `TurboModule` package to `.internal` as this is a quite aggressive breaking change for the ecosystem.

Moreover: users should not invoke `TurboModule.class.isAssignableFrom` because `TurboModule` is `.internal`. Therefore I'm exposing another API to check if a class is a TurboModule as a static field of `ReactModuleInfo`.

## Changelog:

[INTERNAL] - Do not use TurboModule.class.isAssignableFrom

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

Test Plan: Tests are attached

Reviewed By: mdvacca, cipolleschi

Differential Revision: D54280882

Pulled By: cortinico

fbshipit-source-id: 9443c8aa23cf70dd5cfe574fe573d83313134358
2024-03-04 11:02:03 +00:00
Oskar KwaśniewskiandAlex Hunt 7822a7796f fix(iOS) [0.74]: properly warn about createRootViewWithBridge (#43146)
Summary:
This PR fixes an issue that `_logWarnIfCreateRootViewWithBridgeIsOverridden` was called in wrong place.

Assuming user overrides this method and call to `[super]`:

```objc
- (UIView *)createRootViewWithBridge:(RCTBridge *)bridge moduleName:(NSString *)moduleName initProps:(NSDictionary *)initProps {
  UIView *view = [super createRootViewWithBridge:bridge moduleName:moduleName initProps:initProps];
  view.backgroundColor = [UIColor redColor];
  return view;
}
```

This method still wasn't called in bridgeless (and not showing the error).

Checking if user overrides this method in `appDidFinishWithLaunching` works every time

![simulator_screenshot_0E22557C-CE37-4617-A25A-F39A6ED4D3D0](https://github.com/facebook/react-native/assets/52801365/d7865f37-32f0-40ad-a252-74ab7c5b7757)

## Changelog:

[IOS] [FIXED] - Properly warn about `createRootViewWithBridge` being deprecated

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

Test Plan: Check if warning is shown when message is overridden

Reviewed By: huntie

Differential Revision: D54303506

Pulled By: cipolleschi

fbshipit-source-id: cf30555c791493f28b3015a189cf93b60cace8f8
2024-03-04 11:01:37 +00:00
Riccardo CipolleschiandAlex Hunt 1ccc7a3e9e Deprecate getSurfacePresenter and getModuleRegistry in favor of their props
Summary:
This change align the `getSurfacePresenter` and `getModuleRegistry` to the iOS convention for which these should be computed properties with no `get` prefix in their name.

We want to land this change and to pick it in 0.74 so we can remove the `get` versions in 0.75.

## Changelog:
[iOS][Deprecated] - Deprecate `getSurfacePresenter` and `getModuleRegistry` for `surfacePresenter` and moduleRegistry` props.

Reviewed By: javache

Differential Revision: D54253805

fbshipit-source-id: e9ff7db744a73a3bd0f8ae1d87875e54ddd9a1a4
2024-03-04 11:01:15 +00:00
Dmitry RykunandAlex Hunt 987c1f2880 Fix findLibrariesFromReactNativeConfig
Summary:
This diff removes extra argument from the `extractLibrariesFromJSON` call inside `findLibrariesFromReactNativeConfig`.
This should fix the iOS failurte discribed in https://github.com/facebook/react-native/issues/43204
Changelog: [iOS][Fixed] - Codegen correctly handles react-native.config.js.

Reviewed By: cipolleschi

Differential Revision: D54248400

fbshipit-source-id: 2ae5d0d29f49725877559a5b0edd7d59f8bdefaa
2024-03-04 10:56:27 +00:00
Moti ZilbermanandAlex Hunt f6f3b5cb98 Restore Content-Length header in inspector-proxy JSON responses
Summary:
Changelog: [General][Fixed] Re-enable listing Hermes debugger targets in chrome://inspect, broken in 0.74 RC

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

Reverts D52958725 and fixes the original `Content-Length` Unicode bug using a different approach.

Reviewed By: fabriziocucci

Differential Revision: D54409847

fbshipit-source-id: ed5bb464ab67f37535947646b124814d8bbf797c
2024-03-01 10:45:51 +00:00
Riccardo CipolleschiandAlex Hunt f7644be6d4 [RN][iOS]Rename BUILD_FROM_SOURCE to RCT_BUILD_HERMES_FROM_SOURCE 2024-02-29 10:48:01 +00:00
Distiller ad3f6b5274 [0.74.0-rc.1] Bump version numbers 2024-02-27 01:08:06 +00:00
Nicola Corti ba3cf235f5 bumped packages versions
#publish-packages-to-npm&0.74-stable
2024-02-26 16:54:52 -08:00
Cedric van PuttenandNicola Corti d032e35f86 feat(cli): warn underlying command when using npx react-native init (#43127)
Summary:
This adds a new warning for React Native 0.74, implementing the [RFC 0759](https://github.com/react-native-community/discussions-and-proposals/blob/nc/rnf/proposals/0759-react-native-frameworks.md#the-init-command) init command changes.

- It's added inside `react-native/cli.js` to avoid warning users when actually executing `npx react-native-community/cli` commands.
- The check is fairly simple: `process.argv[2] === 'init'`. The first two args are the Node bin and the actual script bin paths.
- The message is sent over `console.warn` to avoid potentially mixing JSON with non-JSON output.

## Changelog:

[GENERAL] [ADDED] - Warn with future command when using `npx react-native init`

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

Test Plan:
Any command other than `init` must not warn.

- `$ node ./path/to/react-native/cli.js init`
- `$ node ./path/to/react-native/cli.js init --help`
  - Should warn with `Running: npx react-native-community/cli init`
    ![image](https://github.com/facebook/react-native/assets/1203991/a3f5e3d2-7b59-41fe-9a53-bc9ce5a21fd1)
- `$ node ./path/to/react-native/cli.js --help`
  - Must not warn
    ![image](https://github.com/facebook/react-native/assets/1203991/97679429-db35-47f8-bdeb-33187bb167cf)

Reviewed By: cipolleschi

Differential Revision: D54063131

Pulled By: cortinico

fbshipit-source-id: c60b8b6034087b584e98b51f5bedf68a46caf44c
2024-02-26 11:47:20 -08:00
Nicola Corti b33b80f51c Bump CLI to 13.6.1 (#43153)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43153

This contains an hotfix for the CLI needed for 0.74

Changelog:
[Internal] [Changed] - Bump CLI to 13.6.1

Reviewed By: huntie

Differential Revision: D54073715

fbshipit-source-id: a5fdf02f47c5e144efc58e6b7fd355669a21e07b
2024-02-26 11:15:57 -08:00
Nicola Corti b3300d77ea Remove accidental files included inside the template.
Summary:
Those files should not stay in the root `/app` folder but inside the `/app/gradle/wrapper` folder.
I've noticed this in the Upgrade Helper UI hence I'm removing them.

Changelog:
[Internal] [Changed] - Remove accidental files included inside the template

Reviewed By: mdvacca

Differential Revision: D54122995

fbshipit-source-id: 8873a91ffbea20f609c7aabd428a815c77a38db5
2024-02-26 11:10:30 -08:00
Nicola Corti fde94ce307 Do not crash on onJSBundleLoadedFromServer when fast-refreshing on bridgeless mode
Summary:
RN-Tester is currently instacrashing on fast-refresh (pressing r on Metro) as it ends up on `onJSBundleLoadedFromServer`
which throws an exception on Bridgeless mode. I'm fixing it by following the same logic as `onReloadWithJSDebugger`.

Changelog:
[Android] [Fixed] - Do not crash on onJSBundleLoadedFromServer when fast-refreshing on bridgeless mode

Reviewed By: huntie

Differential Revision: D54121838

fbshipit-source-id: 82d98ec0c5b2295f5751525368c956574dd7f3a0
2024-02-26 11:10:23 -08:00
Diego SeguraandNicola Corti 1f7ed063c9 fix flatlist props being undefined in ios (#43141)
Summary:
When using Flatlist on iOS and Android its failing because props are undefined

The problem is described on https://github.com/facebook/react-native/issues/34783

![Captura de pantalla 2024-02-22 a las 4 13 11](https://github.com/facebook/react-native/assets/1161455/325738d9-2e49-44a0-bb6a-077b2e02e9cd)

![Captura de pantalla 2024-02-22 a las 4 14 58](https://github.com/facebook/react-native/assets/1161455/118f76e1-a818-428e-938e-123b55536b49)

Fixed by setting constructor before any statement and removing unnecessary props declaration at the top of the class.

## Changelog:

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

Pick one each for the category and type tags:

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

For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests
-->
[GENERAL] [FIXED] - Fix undefined props crash in FlatList

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

Reviewed By: javache

Differential Revision: D54069559

Pulled By: robhogan

fbshipit-source-id: b39cd9a273eb0279ed353f9efcb66a3c4ccf93b4
2024-02-26 11:09:34 -08:00
Nicola CortiandAlex Hunt 4def40ee33 Hook the default-app-setup OnLoad.cpp file with the cxxModuleProvider from RNCLI (#43049)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43049

This connects the OnLoad.cpp file used by OSS apps with the `rncli_cxxModuleProvider`.
This method is created by the CLI and takes care of querying all the TM CXX Modules discovered and returning them.

This PR is currently waiting on https://github.com/react-native-community/cli/pull/2296

Changelog:
[Internal] [Changed] - Hook the default-app-setup OnLoad.cpp file with the cxxModuleProvider from RNCLI

Reviewed By: cipolleschi

Differential Revision: D53812109

fbshipit-source-id: 47bc0ea699516993070cfa0127de97853acf8890
2024-02-22 11:01:50 +00:00
Riccardo CipolleschiandAlex Hunt 341fbe5486 [RN][Release] Fix release testing script 2024-02-21 17:55:37 +00:00
Distiller 898e207bcf [0.74.0-rc.0] Bump version numbers 2024-02-21 16:33:24 +00:00
Alex Hunt 619b8eb4d0 Bump package versions
#publish-packages-to-npm&0.74-stable
2024-02-21 15:20:42 +00:00
Alex Hunt ebca982365 Update Hermes version 2024-02-20 15:24:28 +00:00
243 changed files with 4511 additions and 2731 deletions
+11 -3
View File
@@ -12,15 +12,23 @@ parameters:
default: false
type: boolean
release_latest:
run_nightly_workflow:
default: false
type: boolean
release_version:
default: "9999"
default: ""
type: string
run_nightly_workflow:
release_monorepo_packages_version:
default: ""
type: string
release_tag:
default: ""
type: string
release_dry_run:
default: false
type: boolean
+2 -2
View File
@@ -35,11 +35,11 @@ executors:
xcode: *xcode_version
resource_class: macos.x86.medium.gen2
environment:
- BUILD_FROM_SOURCE: true
- RCT_BUILD_HERMES_FROM_SOURCE: true
reactnativeios-lts:
<<: *defaults
macos:
xcode: '14.3.1'
resource_class: macos.x86.medium.gen2
environment:
- BUILD_FROM_SOURCE: true
- RCT_BUILD_HERMES_FROM_SOURCE: true
+51 -15
View File
@@ -599,7 +599,7 @@ jobs:
environment:
- HERMES_WS_DIR: *hermes_workspace_root
- HERMES_VERSION_FILE: "packages/react-native/sdks/.hermesversion"
- BUILD_FROM_SOURCE: true
- RCT_BUILD_HERMES_FROM_SOURCE: true
steps:
- run:
name: Install dependencies
@@ -813,13 +813,19 @@ jobs:
exit 0
fi
export RELEASE_VERSION=$(cat /tmp/react-native-version)
if [[ "$SLICE" == "macosx" ]]; then
echo "[HERMES] Building Hermes for MacOS"
export MAC_DEPLOYMENT_TARGET=10.13
BUILD_TYPE="<< parameters.flavor >>" ./utils/build-mac-framework.sh
unset MAC_DEPLOYMENT_TARGET
else
echo "[HERMES] Building Hermes for iOS: $SLICE"
export IOS_DEPLOYMENT_TARGET=13.4
BUILD_TYPE="<< parameters.flavor >>" ./utils/build-ios-framework.sh "$SLICE"
unset IOS_DEPLOYMENT_TARGET
fi
unset RELEASE_VERSION
echo "Moving from build_$SLICE to $FINAL_PATH"
mv build_"$SLICE" "$FINAL_PATH"
@@ -898,7 +904,11 @@ jobs:
command: |
cd ./packages/react-native/sdks/hermes || exit 1
echo "[HERMES] Creating the universal framework"
export IOS_DEPLOYMENT_TARGET=13.4
export RELEASE_VERSION=$(cat /tmp/react-native-version)
./utils/build-ios-framework.sh build_framework
unset RELEASE_VERSION
unset IOS_DEPLOYMENT_TARGET
- run:
name: Package the Hermes Apple frameworks
command: |
@@ -1076,14 +1086,20 @@ jobs:
# -------------------------
# JOBS: Releases
# -------------------------
prepare_package_for_release:
# Writes a new commit and tag(s), which will trigger the `publish_release`
# and `publish_bumped_packages` workflows.
prepare_release:
parameters:
version:
type: string
latest:
type: boolean
default: false
dryrun:
# TODO(T182538198): Required for 0.74.x, where workspace packages are out
# of sync with react-native. This will be removed for 0.75+.
monorepo_packages_version:
type: string
tag:
type: string
dry_run:
type: boolean
default: false
executor: reactnativeios
@@ -1096,16 +1112,36 @@ jobs:
- brew_install:
package: cmake
- run:
name: "Set new react-native version and commit changes"
name: Versioning workspace packages
command: |
VERSION=<< parameters.version >>
if [[ -z "$VERSION" ]]; then
VERSION=$(grep '"version"' package.json | cut -d '"' -f 4 | head -1)
echo "Using the version from the package.json: $VERSION"
fi
node ./scripts/releases-ci/prepare-package-for-release.js -v "$VERSION" -l << parameters.latest >> --dry-run << parameters.dryrun >>
node scripts/releases/set-version "<< parameters.monorepo_packages_version >>" --skip-react-native-version
- run:
name: Versioning react-native package
command: |
node scripts/releases/set-rn-version.js -v "<< parameters.version >>" --build-type "release"
- run:
name: Creating release commit
command: |
git commit -a -m "Release << parameters.version >>" -m "#publish-packages-to-npm&<< parameters.tag >>"
git tag -a "v<< parameters.version >>" -m "v<< parameters.version >>"
env GIT_PAGER=cat git show HEAD
- when:
condition:
equal: ["latest", << parameters.tag >>]
steps:
- run:
name: Updating "latest" tag
command: |
git tag -d "latest"
git push origin :latest
git tag -a "latest" -m "latest"
- unless:
condition: << parameters.dry_run >>
steps:
run:
name: Pushing release commit
command: |
git push origin $CIRCLE_BRANCH --follow-tags
build_npm_package:
parameters:
@@ -4,11 +4,12 @@
- equal: [ false, << pipeline.parameters.run_release_workflow >> ]
- equal: [ false, << pipeline.parameters.run_nightly_workflow >> ]
jobs:
- prepare_package_for_release:
name: prepare_package_for_release
version: ''
latest : false
dryrun: true
- prepare_release:
name: "prepare_release (dry run test)"
version: "0.0.0"
monorepo_packages_version: "0.0.0"
tag: test
dry_run: true
- prepare_hermes_workspace
- build_android:
release_type: "dry-run"
@@ -4,11 +4,12 @@
- equal: [ false, << pipeline.parameters.run_release_workflow >> ]
- equal: [ false, << pipeline.parameters.run_nightly_workflow >> ]
jobs:
- prepare_package_for_release:
name: prepare_package_for_release
version: ''
latest : false
dryrun: true
- prepare_release:
name: "prepare_release (dry run test)"
version: "0.0.0"
monorepo_packages_version: "0.0.0"
tag: test
dry_run: true
- prepare_hermes_workspace
- build_android:
release_type: "dry-run"
@@ -4,11 +4,12 @@
- equal: [ false, << pipeline.parameters.run_release_workflow >> ]
- equal: [ false, << pipeline.parameters.run_nightly_workflow >> ]
jobs:
- prepare_package_for_release:
name: prepare_package_for_release
version: ''
latest : false
dryrun: true
- prepare_release:
name: "prepare_release (dry run test)"
version: "0.0.0"
monorepo_packages_version: "0.0.0"
tag: test
dry_run: true
- prepare_hermes_workspace
- build_android:
release_type: "dry-run"
+13 -5
View File
@@ -82,10 +82,10 @@ references:
hermes_windows_cache_key: &hermes_windows_cache_key v2-hermes-{{ .Environment.CIRCLE_JOB }}-windows-{{ checksum "/Users/circleci/project/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
# Hermes iOS
hermesc_apple_cache_key: &hermesc_apple_cache_key v3-hermesc-apple-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
hermes_apple_slices_cache_key: &hermes_apple_slices_cache_key v4-hermes-apple-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}-{{ checksum "packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh" }}
hermes_apple_slices_cache_key: &hermes_apple_slices_cache_key v7-hermes-apple-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}-{{ checksum "packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh" }}
hermes_tarball_debug_cache_key: &hermes_tarball_debug_cache_key v5-hermes-tarball-debug-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}-{{ checksum "packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh" }}
hermes_tarball_release_cache_key: &hermes_tarball_release_cache_key v4-hermes-tarball-release-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}-{{ checksum "packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh" }}
hermes_macosx_bin_release_cache_key: &hermes_macosx_bin_release_cache_key v2-hermes-release-macosx-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
hermes_macosx_bin_release_cache_key: &hermes_macosx_bin_release_cache_key v4-hermes-release-macosx-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
hermes_macosx_bin_debug_cache_key: &hermes_macosx_bin_debug_cache_key v2-hermes-debug-macosx-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
hermes_dsym_debug_cache_key: &hermes_dsym_debug_cache_key v2-hermes-debug-dsym-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
hermes_dsym_release_cache_key: &hermes_dsym_release_cache_key v2-hermes-release-dsym-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
@@ -129,14 +129,22 @@ parameters:
default: false
type: boolean
release_latest:
run_nightly_workflow:
default: false
type: boolean
release_version:
default: "9999"
default: ""
type: string
run_nightly_workflow:
release_monorepo_packages_version:
default: ""
type: string
release_tag:
default: ""
type: string
release_dry_run:
default: false
type: boolean
+7 -6
View File
@@ -15,15 +15,16 @@
workflows:
version: 2
# This workflow should only be triggered by release script
package_release:
# Release workflow, triggered by `yarn trigger-react-native-release`
create_release:
when: << pipeline.parameters.run_release_workflow >>
jobs:
# This job will push a tag that will trigger the publish_release workflow
- prepare_package_for_release:
name: prepare_package_for_release
- prepare_release:
name: prepare_release
version: << pipeline.parameters.release_version >>
latest : << pipeline.parameters.release_latest >>
monorepo_packages_version: << pipeline.parameters.release_monorepo_packages_version >>
tag: << pipeline.parameters.release_tag >>
dry_run: << pipeline.parameters.release_dry_run >>
# This job will run only when a tag is published due to all the jobs being filtered.
publish_release:
+1
View File
@@ -42,6 +42,7 @@ project.xcworkspace
/packages/react-native/ReactAndroid/hermes-engine/.cxx/
/packages/react-native/template/android/app/build/
/packages/react-native/template/android/build/
/packages/react-native-popup-menu-android/android/build/
# Buck
.buckd
+3 -4
View File
@@ -14,7 +14,6 @@
"android": "cd packages/rn-tester && npm run android",
"build-android": "./gradlew :packages:react-native:ReactAndroid:build",
"build": "node ./scripts/build/build.js",
"bump-all-updated-packages": "node ./scripts/monorepo/bump-all-updated-packages",
"clang-format": "clang-format -i --glob=*/**/*.{h,cpp,m,mm}",
"clean": "node ./scripts/build/clean.js",
"flow-check": "flow check",
@@ -59,10 +58,10 @@
"@definitelytyped/dtslint": "^0.0.127",
"@jest/create-cache-key-function": "^29.6.3",
"@pkgjs/parseargs": "^0.11.0",
"@react-native/metro-babel-transformer": "0.74.0",
"@react-native/metro-config": "0.74.0",
"@react-native/metro-babel-transformer": "0.74.81",
"@react-native/metro-config": "0.74.81",
"@tsconfig/node18": "1.0.1",
"@types/react": "^18.0.18",
"@types/react": "^18.2.6",
"@typescript-eslint/parser": "^6.7.4",
"ansi-styles": "^4.2.1",
"async": "^3.2.2",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/assets-registry",
"version": "0.74.0",
"version": "0.74.81",
"description": "Asset support code for React Native.",
"license": "MIT",
"repository": {
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/babel-plugin-codegen",
"version": "0.74.0",
"version": "0.74.81",
"description": "Babel plugin to generate native module and view manager code for React Native.",
"license": "MIT",
"repository": {
@@ -25,7 +25,7 @@
"index.js"
],
"dependencies": {
"@react-native/codegen": "0.74.0"
"@react-native/codegen": "0.74.81"
},
"devDependencies": {
"@babel/core": "^7.20.0"
+5 -5
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/community-cli-plugin",
"version": "0.74.0",
"version": "0.74.81",
"description": "Core CLI commands for React Native",
"keywords": [
"react-native",
@@ -22,10 +22,10 @@
"dist"
],
"dependencies": {
"@react-native-community/cli-server-api": "13.6.0",
"@react-native-community/cli-tools": "13.6.0",
"@react-native/dev-middleware": "0.74.0",
"@react-native/metro-babel-transformer": "0.74.0",
"@react-native-community/cli-server-api": "13.6.4",
"@react-native-community/cli-tools": "13.6.4",
"@react-native/dev-middleware": "0.74.81",
"@react-native/metro-babel-transformer": "0.74.81",
"chalk": "^4.0.0",
"execa": "^5.1.1",
"metro": "^0.80.3",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/debugger-frontend",
"version": "0.74.0",
"version": "0.74.81",
"description": "Debugger frontend for React Native based on Chrome DevTools",
"keywords": [
"react-native",
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/dev-middleware",
"version": "0.74.0",
"version": "0.74.81",
"description": "Dev server middleware for React Native",
"keywords": [
"react-native",
@@ -23,7 +23,7 @@
],
"dependencies": {
"@isaacs/ttlcache": "^1.4.1",
"@react-native/debugger-frontend": "0.74.0",
"@react-native/debugger-frontend": "0.74.81",
"@rnx-kit/chromium-edge-launcher": "^1.0.0",
"chrome-launcher": "^0.15.2",
"connect": "^3.6.5",
@@ -0,0 +1,394 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
* @oncall react_native
*/
import {fetchJson} from './FetchUtils';
import {createDebuggerMock} from './InspectorDebuggerUtils';
import {createDeviceMock} from './InspectorDeviceUtils';
import {createAndConnectTarget} from './InspectorProtocolUtils';
import {withAbortSignalForEachTest} from './ResourceUtils';
import {baseUrlForServer, createServer} from './ServerUtils';
import invariant from 'invariant';
import until from 'wait-for-expect';
// WebSocket is unreliable when using fake timers.
jest.useRealTimers();
jest.setTimeout(10000);
describe('inspector proxy device message middleware', () => {
const autoCleanup = withAbortSignalForEachTest();
const page = {
id: 'page1',
app: 'bar-app',
title: 'bar-title',
vm: 'bar-vm',
};
afterEach(() => {
jest.clearAllMocks();
});
test('middleware is created with device, debugger, and page information', async () => {
const createCustomMessageHandler = jest.fn().mockImplementation(() => null);
const {server} = await createServer({
logger: undefined,
projectRoot: '',
unstable_customInspectorMessageHandler: createCustomMessageHandler,
});
let device, debugger_;
try {
({device, debugger_} = await createAndConnectTarget(
serverRefUrls(server),
autoCleanup.signal,
page,
));
// Ensure the middleware was created with the device information
await until(() =>
expect(createCustomMessageHandler).toBeCalledWith(
expect.objectContaining({
page: expect.objectContaining({
...page,
capabilities: expect.any(Object),
}),
device: expect.objectContaining({
appId: expect.any(String),
id: expect.any(String),
name: expect.any(String),
sendMessage: expect.any(Function),
}),
debugger: expect.objectContaining({
userAgent: null,
sendMessage: expect.any(Function),
}),
}),
),
);
} finally {
device?.close();
debugger_?.close();
await closeServer(server);
}
});
test('middleware is created with device, debugger, and page information for synthetic reloadable page', async () => {
const createCustomMessageHandler = jest.fn().mockImplementation(() => null);
const {server} = await createServer({
logger: undefined,
projectRoot: '',
unstable_customInspectorMessageHandler: createCustomMessageHandler,
});
const {serverBaseUrl, serverBaseWsUrl} = serverRefUrls(server);
let device, debugger_;
try {
device = await createDeviceMock(
`${serverBaseWsUrl}/inspector/device?device=device1&name=foo&app=bar`,
autoCleanup.signal,
);
// Mock the device to return a normal React (Native) page
device.getPages.mockImplementation(() => [
{
...page,
// NOTE: 'React' is a magic string used to detect React Native pages.
title: 'React Native (mock)',
},
]);
// Retrieve the full page list from device
let pageList;
await until(async () => {
pageList = (await fetchJson(
`${serverBaseUrl}/json`,
// $FlowIgnore[unclear-type]
): any);
expect(pageList.length).toBeGreaterThan(0);
});
invariant(pageList != null, '');
// Find the synthetic page
const syntheticPage = pageList.find(
({title}) =>
// NOTE: Magic string used for the synthetic page that has a stable ID
title === 'React Native Experimental (Improved Chrome Reloads)',
);
expect(syntheticPage).not.toBeUndefined();
// Connect the debugger to this synthetic page
debugger_ = await createDebuggerMock(
syntheticPage.webSocketDebuggerUrl,
autoCleanup.signal,
);
// Ensure the middleware was created with the device information
await until(() =>
expect(createCustomMessageHandler).toBeCalledWith(
expect.objectContaining({
page: expect.objectContaining({
id: expect.any(String),
title: syntheticPage.title,
vm: syntheticPage.vm,
app: expect.any(String),
capabilities: expect.any(Object),
}),
device: expect.objectContaining({
appId: expect.any(String),
id: expect.any(String),
name: expect.any(String),
sendMessage: expect.any(Function),
}),
debugger: expect.objectContaining({
userAgent: null,
sendMessage: expect.any(Function),
}),
}),
),
);
} finally {
device?.close();
debugger_?.close();
await closeServer(server);
}
});
test('send message functions are passing messages to sockets', async () => {
const handleDebuggerMessage = jest.fn();
const handleDeviceMessage = jest.fn();
const createCustomMessageHandler = jest.fn().mockImplementation(() => ({
handleDebuggerMessage,
handleDeviceMessage,
}));
const {server} = await createServer({
logger: undefined,
projectRoot: '',
unstable_customInspectorMessageHandler: createCustomMessageHandler,
});
let device, debugger_;
try {
({device, debugger_} = await createAndConnectTarget(
serverRefUrls(server),
autoCleanup.signal,
page,
));
// Ensure the middleware was created with the send message methods
await until(() =>
expect(createCustomMessageHandler).toBeCalledWith(
expect.objectContaining({
device: expect.objectContaining({
sendMessage: expect.any(Function),
}),
debugger: expect.objectContaining({
sendMessage: expect.any(Function),
}),
}),
),
);
// Send a message to the device
createCustomMessageHandler.mock.calls[0][0].device.sendMessage({
id: 1,
});
// Ensure the device received the message
await until(() =>
expect(device.wrappedEvent).toBeCalledWith({
event: 'wrappedEvent',
payload: {
pageId: page.id,
wrappedEvent: JSON.stringify({id: 1}),
},
}),
);
// Send a message to the debugger
createCustomMessageHandler.mock.calls[0][0].debugger.sendMessage({
id: 2,
});
// Ensure the debugger received the message
await until(() =>
expect(debugger_.handle).toBeCalledWith({
id: 2,
}),
);
} finally {
device?.close();
debugger_?.close();
await closeServer(server);
}
});
test('device message is passed to message middleware', async () => {
const handleDeviceMessage = jest.fn();
const {server} = await createServer({
logger: undefined,
projectRoot: '',
unstable_customInspectorMessageHandler: () => ({
handleDeviceMessage,
handleDebuggerMessage() {},
}),
});
let device, debugger_;
try {
({device, debugger_} = await createAndConnectTarget(
serverRefUrls(server),
autoCleanup.signal,
page,
));
// Send a message from the device, and ensure the middleware received it
device.sendWrappedEvent(page.id, {id: 1337});
// Ensure the debugger received the message
await until(() => expect(debugger_.handle).toBeCalledWith({id: 1337}));
// Ensure the middleware received the message
await until(() => expect(handleDeviceMessage).toBeCalled());
} finally {
device?.close();
debugger_?.close();
await closeServer(server);
}
});
test('device message stops propagating when handled by middleware', async () => {
const handleDeviceMessage = jest.fn();
const {server} = await createServer({
logger: undefined,
projectRoot: '',
unstable_customInspectorMessageHandler: () => ({
handleDeviceMessage,
handleDebuggerMessage() {},
}),
});
let device, debugger_;
try {
({device, debugger_} = await createAndConnectTarget(
serverRefUrls(server),
autoCleanup.signal,
page,
));
// Stop the first message from propagating by returning true (once) from middleware
handleDeviceMessage.mockReturnValueOnce(true);
// Send the first message which should NOT be received by the debugger
device.sendWrappedEvent(page.id, {id: -1});
await until(() => expect(handleDeviceMessage).toBeCalled());
// Send the second message which should be received by the debugger
device.sendWrappedEvent(page.id, {id: 1337});
// Ensure only the last message was received by the debugger
await until(() => expect(debugger_.handle).toBeCalledWith({id: 1337}));
// Ensure the first message was not received by the debugger
expect(debugger_.handle).not.toBeCalledWith({id: -1});
} finally {
device?.close();
debugger_?.close();
await closeServer(server);
}
});
test('debugger message is passed to message middleware', async () => {
const handleDebuggerMessage = jest.fn();
const {server} = await createServer({
logger: undefined,
projectRoot: '',
unstable_customInspectorMessageHandler: () => ({
handleDeviceMessage() {},
handleDebuggerMessage,
}),
});
let device, debugger_;
try {
({device, debugger_} = await createAndConnectTarget(
serverRefUrls(server),
autoCleanup.signal,
page,
));
// Send a message from the debugger
const message = {
method: 'Runtime.enable',
id: 1337,
};
debugger_.send(message);
// Ensure the device received the message
await until(() => expect(device.wrappedEvent).toBeCalled());
// Ensure the middleware received the message
await until(() => expect(handleDebuggerMessage).toBeCalledWith(message));
} finally {
device?.close();
debugger_?.close();
await closeServer(server);
}
});
test('debugger message stops propagating when handled by middleware', async () => {
const handleDebuggerMessage = jest.fn();
const {server} = await createServer({
logger: undefined,
projectRoot: '',
unstable_customInspectorMessageHandler: () => ({
handleDeviceMessage() {},
handleDebuggerMessage,
}),
});
let device, debugger_;
try {
({device, debugger_} = await createAndConnectTarget(
serverRefUrls(server),
autoCleanup.signal,
page,
));
// Stop the first message from propagating by returning true (once) from middleware
handleDebuggerMessage.mockReturnValueOnce(true);
// Send the first emssage which should not be received by the device
debugger_.send({id: -1});
// Send the second message which should be received by the device
debugger_.send({id: 1337});
// Ensure only the last message was received by the device
await until(() =>
expect(device.wrappedEvent).toBeCalledWith({
event: 'wrappedEvent',
payload: {pageId: page.id, wrappedEvent: JSON.stringify({id: 1337})},
}),
);
// Ensure the first message was not received by the device
expect(device.wrappedEvent).not.toBeCalledWith({id: -1});
} finally {
device?.close();
debugger_?.close();
await closeServer(server);
}
});
});
function serverRefUrls(server: http$Server | https$Server) {
return {
serverBaseUrl: baseUrlForServer(server, 'http'),
serverBaseWsUrl: baseUrlForServer(server, 'ws'),
};
}
async function closeServer(server: http$Server | https$Server): Promise<void> {
return new Promise(resolve => server.close(() => resolve()));
}
@@ -14,11 +14,13 @@ import type {
JsonVersionResponse,
} from '../inspector-proxy/types';
import {fetchJson} from './FetchUtils';
import {fetchJson, fetchLocal} from './FetchUtils';
import {createDeviceMock} from './InspectorDeviceUtils';
import {withAbortSignalForEachTest} from './ResourceUtils';
import {withServerForEachTest} from './ServerUtils';
import nullthrows from 'nullthrows';
// Must be greater than or equal to PAGES_POLLING_INTERVAL in `InspectorProxy.js`.
const PAGES_POLLING_DELAY = 1000;
@@ -309,5 +311,67 @@ describe('inspector proxy HTTP API', () => {
}
});
});
test('handles Unicode data safely', async () => {
const device = await createDeviceMock(
`${serverRef.serverBaseWsUrl}/inspector/device?device=device1&name=foo&app=bar`,
autoCleanup.signal,
);
try {
device.getPages.mockImplementation(() => [
{
app: 'bar-app 📱',
id: 'page1 🛂',
title: 'bar-title 📰',
vm: 'bar-vm 🤖',
},
]);
jest.advanceTimersByTime(PAGES_POLLING_DELAY);
const json = await fetchJson<JsonPagesListResponse>(
`${serverRef.serverBaseUrl}${endpoint}`,
);
expect(json).toEqual([
expect.objectContaining({
description: 'bar-app 📱',
deviceName: 'foo',
id: 'device1-page1 🛂',
title: 'bar-title 📰',
vm: 'bar-vm 🤖',
}),
]);
} finally {
device.close();
}
});
test('includes a valid Content-Length header', async () => {
// NOTE: This test is needed because chrome://inspect's HTTP client is picky
// and doesn't accept responses without a Content-Length header.
const device = await createDeviceMock(
`${serverRef.serverBaseWsUrl}/inspector/device?device=device1&name=foo&app=bar`,
autoCleanup.signal,
);
try {
device.getPages.mockImplementation(() => [
{
app: 'bar-app',
id: 'page1',
title: 'bar-title',
vm: 'bar-vm',
},
]);
jest.advanceTimersByTime(PAGES_POLLING_DELAY);
const response = await fetchLocal(
`${serverRef.serverBaseUrl}${endpoint}`,
);
expect(response.headers.get('Content-Length')).not.toBeNull();
} finally {
device.close();
}
});
});
});
@@ -9,6 +9,7 @@
* @oncall react_native
*/
import type {CreateCustomMessageHandlerFn} from './inspector-proxy/CustomMessageHandler';
import type {BrowserLauncher} from './types/BrowserLauncher';
import type {EventReporter} from './types/EventReporter';
import type {Experiments, ExperimentsConfig} from './types/Experiments';
@@ -61,11 +62,12 @@ type Options = $ReadOnly<{
unstable_experiments?: ExperimentsConfig,
/**
* An interface for using a modified inspector proxy implementation.
* Create custom handler to add support for unsupported CDP events, or debuggers.
* This handler is instantiated per logical device and debugger pair.
*
* This is an unstable API with no semver guarantees.
*/
unstable_InspectorProxy?: Class<InspectorProxy>,
unstable_customInspectorMessageHandler?: CreateCustomMessageHandlerFn,
}>;
type DevMiddlewareAPI = $ReadOnly<{
@@ -80,16 +82,16 @@ export default function createDevMiddleware({
unstable_browserLauncher = DefaultBrowserLauncher,
unstable_eventReporter,
unstable_experiments: experimentConfig = {},
unstable_InspectorProxy,
unstable_customInspectorMessageHandler,
}: Options): DevMiddlewareAPI {
const experiments = getExperiments(experimentConfig);
const InspectorProxyClass = unstable_InspectorProxy ?? InspectorProxy;
const inspectorProxy = new InspectorProxyClass(
const inspectorProxy = new InspectorProxy(
projectRoot,
serverBaseUrl,
unstable_eventReporter,
experiments,
unstable_customInspectorMessageHandler,
);
const middleware = connect()
+5 -3
View File
@@ -13,6 +13,8 @@ export {default as createDevMiddleware} from './createDevMiddleware';
export type {BrowserLauncher, LaunchedBrowser} from './types/BrowserLauncher';
export type {EventReporter, ReportableEvent} from './types/EventReporter';
export {default as unstable_InspectorProxy} from './inspector-proxy/InspectorProxy';
export {default as unstable_Device} from './inspector-proxy/Device';
export type {
CustomMessageHandler,
CustomMessageHandlerConnection,
CreateCustomMessageHandlerFn,
} from './inspector-proxy/CustomMessageHandler';
@@ -0,0 +1,54 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
import type {JSONSerializable, Page} from './types';
type ExposedDevice = $ReadOnly<{
appId: string,
id: string,
name: string,
sendMessage: (message: JSONSerializable) => void,
}>;
type ExposedDebugger = $ReadOnly<{
userAgent: string | null,
sendMessage: (message: JSONSerializable) => void,
}>;
export type CustomMessageHandlerConnection = $ReadOnly<{
page: Page,
device: ExposedDevice,
debugger: ExposedDebugger,
}>;
export type CreateCustomMessageHandlerFn = (
connection: CustomMessageHandlerConnection,
) => ?CustomMessageHandler;
/**
* The device message middleware allows implementers to handle unsupported CDP messages.
* It is instantiated per device and may contain state that is specific to that device.
* The middleware can also mark messages from the device or debugger as handled, which stops propagating.
*/
export interface CustomMessageHandler {
/**
* Handle a CDP message coming from the device.
* This is invoked before the message is sent to the debugger.
* When returning true, the message is considered handled and will not be sent to the debugger.
*/
handleDeviceMessage(message: JSONSerializable): true | void;
/**
* Handle a CDP message coming from the debugger.
* This is invoked before the message is sent to the device.
* When returning true, the message is considered handled and will not be sent to the device.
*/
handleDebuggerMessage(message: JSONSerializable): true | void;
}
@@ -16,6 +16,10 @@ import type {
CDPResponse,
CDPServerMessage,
} from './cdp-types/messages';
import type {
CreateCustomMessageHandlerFn,
CustomMessageHandler,
} from './CustomMessageHandler';
import type {
MessageFromDevice,
MessageToDevice,
@@ -51,6 +55,11 @@ type DebuggerInfo = {
userAgent: string | null,
};
type DebuggerConnection = {
...DebuggerInfo,
customHandler: ?CustomMessageHandler,
};
const REACT_NATIVE_RELOADABLE_PAGE_ID = '-1';
/**
@@ -74,7 +83,7 @@ export default class Device {
#pages: $ReadOnlyMap<string, Page>;
// Stores information about currently connected debugger (if any).
#debuggerConnection: ?DebuggerInfo = null;
#debuggerConnection: ?DebuggerConnection = null;
// Last known Page ID of the React Native page.
// This is used by debugger connections that don't have PageID specified
@@ -97,6 +106,9 @@ export default class Device {
#pagesPollingIntervalId: ReturnType<typeof setInterval>;
// The device message middleware factory function allowing implementers to handle unsupported CDP messages.
#createCustomMessageHandler: ?CreateCustomMessageHandlerFn;
constructor(
id: string,
name: string,
@@ -104,6 +116,7 @@ export default class Device {
socket: WS,
projectRoot: string,
eventReporter: ?EventReporter,
createMessageMiddleware: ?CreateCustomMessageHandlerFn,
) {
this.#id = id;
this.#name = name;
@@ -118,6 +131,7 @@ export default class Device {
appId: app,
})
: null;
this.#createCustomMessageHandler = createMessageMiddleware;
// $FlowFixMe[incompatible-call]
this.#deviceSocket.on('message', (message: string) => {
@@ -162,14 +176,7 @@ export default class Device {
getPagesList(): $ReadOnlyArray<Page> {
if (this.#lastConnectedLegacyReactNativePage) {
const reactNativeReloadablePage = {
id: REACT_NATIVE_RELOADABLE_PAGE_ID,
title: 'React Native Experimental (Improved Chrome Reloads)',
vm: "don't use",
app: this.#app,
capabilities: {},
};
return [...this.#pages.values(), reactNativeReloadablePage];
return [...this.#pages.values(), this.#createSyntheticPage()];
} else {
return [...this.#pages.values()];
}
@@ -205,16 +212,64 @@ export default class Device {
prependedFilePrefix: false,
pageId,
userAgent: metadata.userAgent,
customHandler: null,
};
// TODO(moti): Handle null case explicitly, e.g. refuse to connect to
// unknown pages.
const page: ?Page = this.#pages.get(pageId);
const page: ?Page =
pageId === REACT_NATIVE_RELOADABLE_PAGE_ID
? this.#createSyntheticPage()
: this.#pages.get(pageId);
this.#debuggerConnection = debuggerInfo;
debug(`Got new debugger connection for page ${pageId} of ${this.#name}`);
if (page && this.#debuggerConnection && this.#createCustomMessageHandler) {
this.#debuggerConnection.customHandler = this.#createCustomMessageHandler(
{
page,
debugger: {
userAgent: debuggerInfo.userAgent,
sendMessage: message => {
try {
const payload = JSON.stringify(message);
debug('(Debugger) <- (Proxy) (Device): ' + payload);
socket.send(payload);
} catch {}
},
},
device: {
appId: this.#app,
id: this.#id,
name: this.#name,
sendMessage: message => {
try {
const payload = JSON.stringify({
event: 'wrappedEvent',
payload: {
pageId: this.#mapToDevicePageId(pageId),
wrappedEvent: JSON.stringify(message),
},
});
debug('(Debugger) -> (Proxy) (Device): ' + payload);
this.#deviceSocket.send(payload);
} catch {}
},
},
},
);
if (this.#debuggerConnection.customHandler) {
debug('Created new custom message handler for debugger connection');
} else {
debug(
'Skipping new custom message handler for debugger connection, factory function returned null',
);
}
}
this.#sendMessageToDevice({
event: 'connect',
payload: {
@@ -231,6 +286,15 @@ export default class Device {
frontendUserAgent: metadata.userAgent,
});
let processedReq = debuggerRequest;
if (
this.#debuggerConnection?.customHandler?.handleDebuggerMessage(
debuggerRequest,
) === true
) {
return;
}
if (!page || !this.#pageHasCapability(page, 'nativeSourceCodeFetching')) {
processedReq = this.#interceptClientMessageForSourceFetching(
debuggerRequest,
@@ -311,6 +375,19 @@ export default class Device {
return page.capabilities[flag] === true;
}
/**
* Returns the synthetic "React Native Experimental (Improved Chrome Reloads)" page.
*/
#createSyntheticPage(): Page {
return {
id: REACT_NATIVE_RELOADABLE_PAGE_ID,
title: 'React Native Experimental (Improved Chrome Reloads)',
vm: "don't use",
app: this.#app,
capabilities: {},
};
}
// Handles messages received from device:
// 1. For getPages responses updates local #pages list.
// 2. All other messages are forwarded to debugger as wrappedEvent.
@@ -411,12 +488,21 @@ export default class Device {
});
}
if (this.#debuggerConnection != null) {
const debuggerConnection = this.#debuggerConnection;
if (debuggerConnection != null) {
if (
debuggerConnection.customHandler?.handleDeviceMessage(
parsedPayload,
) === true
) {
return;
}
// Wrapping just to make flow happy :)
// $FlowFixMe[unused-promise]
this.#processMessageFromDeviceLegacy(
parsedPayload,
this.#debuggerConnection,
debuggerConnection,
pageId,
).then(() => {
const messageToSend = JSON.stringify(parsedPayload);
@@ -499,7 +585,7 @@ export default class Device {
// Allows to make changes in incoming message from device.
async #processMessageFromDeviceLegacy(
payload: CDPServerMessage,
debuggerInfo: DebuggerInfo,
debuggerInfo: DebuggerConnection,
pageId: ?string,
) {
// TODO(moti): Handle null case explicitly, or ideally associate a copy
@@ -616,7 +702,7 @@ export default class Device {
*/
#interceptClientMessageForSourceFetching(
req: CDPClientMessage,
debuggerInfo: DebuggerInfo,
debuggerInfo: DebuggerConnection,
socket: WS,
): CDPClientMessage | null {
switch (req.method) {
@@ -633,7 +719,7 @@ export default class Device {
#processDebuggerSetBreakpointByUrl(
req: CDPRequest<'Debugger.setBreakpointByUrl'>,
debuggerInfo: DebuggerInfo,
debuggerInfo: DebuggerConnection,
): CDPRequest<'Debugger.setBreakpointByUrl'> {
// If we replaced Android emulator's address to localhost we need to change it back.
if (debuggerInfo.originalSourceURLAddress != null) {
@@ -758,10 +844,6 @@ export default class Device {
// Fetch text, raising an exception if the text could not be fetched,
// or is too large.
async #fetchText(url: URL): Promise<string> {
if (!['localhost', '127.0.0.1'].includes(url.hostname)) {
throw new Error('remote fetches not permitted');
}
// $FlowFixMe[incompatible-call] Suppress arvr node-fetch flow error
const response = await fetch(url);
if (!response.ok) {
@@ -11,6 +11,7 @@
import type {EventReporter} from '../types/EventReporter';
import type {Experiments} from '../types/Experiments';
import type {CreateCustomMessageHandlerFn} from './CustomMessageHandler';
import type {
JsonPagesListResponse,
JsonVersionResponse,
@@ -58,17 +59,22 @@ export default class InspectorProxy implements InspectorProxyQueries {
#experiments: Experiments;
// custom message handler factory allowing implementers to handle unsupported CDP messages.
#customMessageHandler: ?CreateCustomMessageHandlerFn;
constructor(
projectRoot: string,
serverBaseUrl: string,
eventReporter: ?EventReporter,
experiments: Experiments,
customMessageHandler: ?CreateCustomMessageHandlerFn,
) {
this.#projectRoot = projectRoot;
this.#serverBaseUrl = serverBaseUrl;
this.#devices = new Map();
this.#eventReporter = eventReporter;
this.#experiments = experiments;
this.#customMessageHandler = customMessageHandler;
}
getPageDescriptions(): Array<PageDescription> {
@@ -167,6 +173,7 @@ export default class InspectorProxy implements InspectorProxyQueries {
response.writeHead(200, {
'Content-Type': 'application/json; charset=UTF-8',
'Cache-Control': 'no-cache',
'Content-Length': Buffer.byteLength(data).toString(),
Connection: 'close',
});
response.end(data);
@@ -203,6 +210,7 @@ export default class InspectorProxy implements InspectorProxyQueries {
socket,
this.#projectRoot,
this.#eventReporter,
this.#customMessageHandler,
);
if (oldDevice) {
@@ -257,7 +265,7 @@ export default class InspectorProxy implements InspectorProxyQueries {
}
device.handleDebuggerConnection(socket, pageId, {
userAgent: req.headers['user-agent'] ?? null,
userAgent: req.headers['user-agent'] ?? query.userAgent ?? null,
});
} catch (e) {
console.error(e);
@@ -30,6 +30,13 @@ export type TargetCapabilityFlags = $ReadOnly<{
* In the proxy, this disables source fetching emulation and host rewrites.
*/
nativeSourceCodeFetching?: boolean,
/**
* The target supports native network inspection.
*
* In the proxy, this disables intercepting and storing network requests.
*/
nativeNetworkInspection?: boolean,
}>;
// Page information received from the device. New page is created for
@@ -1,6 +1,6 @@
{
"name": "@react-native/eslint-config",
"version": "0.74.0",
"version": "0.74.81",
"description": "ESLint config for React Native",
"license": "MIT",
"repository": {
@@ -22,7 +22,7 @@
"dependencies": {
"@babel/core": "^7.20.0",
"@babel/eslint-parser": "^7.20.0",
"@react-native/eslint-plugin": "0.74.0",
"@react-native/eslint-plugin": "0.74.81",
"@typescript-eslint/eslint-plugin": "^6.7.4",
"@typescript-eslint/parser": "^6.7.4",
"eslint-config-prettier": "^8.5.0",
@@ -1,6 +1,6 @@
{
"name": "@react-native/eslint-plugin",
"version": "0.74.0",
"version": "0.74.81",
"description": "ESLint rules for @react-native/eslint-config",
"license": "MIT",
"repository": {
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/eslint-plugin-specs",
"version": "0.74.0",
"version": "0.74.81",
"description": "ESLint rules to validate NativeModule and Component Specs",
"license": "MIT",
"repository": {
@@ -31,7 +31,7 @@
"@babel/eslint-parser": "^7.20.0",
"@babel/plugin-transform-flow-strip-types": "^7.20.0",
"@babel/preset-flow": "^7.20.0",
"@react-native/codegen": "0.74.0",
"@react-native/codegen": "0.74.81",
"make-dir": "^2.1.0",
"pirates": "^4.0.1",
"source-map-support": "0.5.0"
@@ -1,6 +1,6 @@
{
"name": "@react-native/hermes-inspector-msggen",
"version": "0.72.0",
"version": "0.74.81",
"private": true,
"description": "Hermes Inspector Message Generator for React Native",
"license": "MIT",
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/metro-config",
"version": "0.74.0",
"version": "0.74.81",
"description": "Metro configuration for React Native.",
"license": "MIT",
"repository": {
@@ -26,8 +26,8 @@
"dist"
],
"dependencies": {
"@react-native/js-polyfills": "0.74.0",
"@react-native/metro-babel-transformer": "0.74.0",
"@react-native/js-polyfills": "0.74.81",
"@react-native/metro-babel-transformer": "0.74.81",
"metro-config": "^0.80.3",
"metro-runtime": "^0.80.3"
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/normalize-colors",
"version": "0.74.1",
"version": "0.74.81",
"description": "Color normalization for React Native.",
"license": "MIT",
"repository": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/js-polyfills",
"version": "0.74.0",
"version": "0.74.81",
"description": "Polyfills for React Native.",
"license": "MIT",
"repository": {
@@ -1,6 +1,6 @@
{
"name": "@react-native/babel-preset",
"version": "0.74.0",
"version": "0.74.81",
"description": "Babel preset for React Native applications",
"main": "src/index.js",
"repository": {
@@ -54,7 +54,7 @@
"@babel/plugin-transform-typescript": "^7.5.0",
"@babel/plugin-transform-unicode-regex": "^7.0.0",
"@babel/template": "^7.0.0",
"@react-native/babel-plugin-codegen": "0.74.0",
"@react-native/babel-plugin-codegen": "0.74.81",
"babel-plugin-transform-flow-enums": "^0.0.2",
"react-refresh": "^0.14.0"
},
@@ -1,6 +1,6 @@
{
"name": "@react-native/metro-babel-transformer",
"version": "0.74.0",
"version": "0.74.81",
"description": "Babel transformer for React Native applications.",
"main": "src/index.js",
"repository": {
@@ -16,7 +16,7 @@
"license": "MIT",
"dependencies": {
"@babel/core": "^7.20.0",
"@react-native/babel-preset": "0.74.0",
"@react-native/babel-preset": "0.74.81",
"hermes-parser": "0.19.1",
"nullthrows": "^1.1.1"
},
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@react-native/bots",
"description": "React Native Bots",
"version": "0.0.0",
"version": "0.74.81",
"private": true,
"license": "MIT",
"repository": {
@@ -1,6 +1,6 @@
{
"name": "@react-native/codegen-typescript-test",
"version": "0.0.1",
"version": "0.74.81",
"private": true,
"description": "TypeScript related unit test for @react-native/codegen",
"license": "MIT",
@@ -19,7 +19,7 @@
"prepare": "yarn run build"
},
"dependencies": {
"@react-native/codegen": "0.74.0"
"@react-native/codegen": "0.74.81"
},
"devDependencies": {
"@babel/core": "^7.20.0",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/codegen",
"version": "0.74.0",
"version": "0.74.81",
"description": "Code generation tools for React Native",
"license": "MIT",
"repository": {
@@ -462,7 +462,7 @@ module.exports = {
'com.facebook.react.bridge.ReactApplicationContext',
'com.facebook.react.bridge.ReactContextBaseJavaModule',
'com.facebook.react.bridge.ReactMethod',
'com.facebook.react.internal.turbomodule.core.interfaces.TurboModule',
'com.facebook.react.turbomodule.core.interfaces.TurboModule',
'com.facebook.proguard.annotations.DoNotStrip',
'javax.annotation.Nonnull',
]);
@@ -20,7 +20,7 @@ import com.facebook.proguard.annotations.DoNotStrip;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.internal.turbomodule.core.interfaces.TurboModule;
import com.facebook.react.turbomodule.core.interfaces.TurboModule;
import javax.annotation.Nonnull;
public abstract class NativeSampleTurboModuleSpec extends ReactContextBaseJavaModule implements TurboModule {
@@ -66,7 +66,7 @@ import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.internal.turbomodule.core.interfaces.TurboModule;
import com.facebook.react.turbomodule.core.interfaces.TurboModule;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -136,7 +136,7 @@ import com.facebook.proguard.annotations.DoNotStrip;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.internal.turbomodule.core.interfaces.TurboModule;
import com.facebook.react.turbomodule.core.interfaces.TurboModule;
import javax.annotation.Nonnull;
public abstract class NativeSampleTurboModuleSpec extends ReactContextBaseJavaModule implements TurboModule {
@@ -178,7 +178,7 @@ import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.internal.turbomodule.core.interfaces.TurboModule;
import com.facebook.react.turbomodule.core.interfaces.TurboModule;
import javax.annotation.Nonnull;
public abstract class AliasTurboModuleSpec extends ReactContextBaseJavaModule implements TurboModule {
@@ -224,7 +224,7 @@ import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.internal.turbomodule.core.interfaces.TurboModule;
import com.facebook.react.turbomodule.core.interfaces.TurboModule;
import javax.annotation.Nonnull;
public abstract class NativeCameraRollManagerSpec extends ReactContextBaseJavaModule implements TurboModule {
@@ -272,7 +272,7 @@ import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.internal.turbomodule.core.interfaces.TurboModule;
import com.facebook.react.turbomodule.core.interfaces.TurboModule;
import javax.annotation.Nonnull;
public abstract class NativeExceptionsManagerSpec extends ReactContextBaseJavaModule implements TurboModule {
@@ -338,7 +338,7 @@ import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.common.build.ReactBuildConfig;
import com.facebook.react.internal.turbomodule.core.interfaces.TurboModule;
import com.facebook.react.turbomodule.core.interfaces.TurboModule;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
@@ -462,7 +462,7 @@ import com.facebook.proguard.annotations.DoNotStrip;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.internal.turbomodule.core.interfaces.TurboModule;
import com.facebook.react.turbomodule.core.interfaces.TurboModule;
import javax.annotation.Nonnull;
public abstract class NativeSampleTurboModuleSpec extends ReactContextBaseJavaModule implements TurboModule {
@@ -500,7 +500,7 @@ import com.facebook.proguard.annotations.DoNotStrip;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.internal.turbomodule.core.interfaces.TurboModule;
import com.facebook.react.turbomodule.core.interfaces.TurboModule;
import javax.annotation.Nonnull;
public abstract class NativeSampleTurboModule2Spec extends ReactContextBaseJavaModule implements TurboModule {
@@ -1,6 +1,6 @@
{
"name": "@react-native/gradle-plugin",
"version": "0.74.0",
"version": "0.74.81",
"description": "Gradle Plugin for React Native",
"license": "MIT",
"repository": {
@@ -54,6 +54,26 @@ abstract class PreparePrefabHeadersTask : DefaultTask() {
it.include("boost/detail/workaround.hpp")
it.include("boost/operators.hpp")
it.include("boost/preprocessor/**/*.hpp")
// Headers needed for exposing rrc_text and rrc_textinput
it.include("boost/container_hash/**/*.hpp")
it.include("boost/detail/**/*.hpp")
it.include("boost/intrusive/**/*.hpp")
it.include("boost/iterator/**/*.hpp")
it.include("boost/move/**/*.hpp")
it.include("boost/mpl/**/*.hpp")
it.include("boost/mp11/**/*.hpp")
it.include("boost/describe/**/*.hpp")
it.include("boost/preprocessor/**/*.hpp")
it.include("boost/type_traits/**/*.hpp")
it.include("boost/utility/**/*.hpp")
it.include("boost/detail/workaround.hpp")
it.include("boost/assert.hpp")
it.include("boost/static_assert.hpp")
it.include("boost/cstdint.hpp")
it.include("boost/operators.hpp")
it.include("boost/config.hpp")
it.include("boost/utility.hpp")
it.include("boost/version.hpp")
it.into(File(outputFolder.asFile, headerPrefix))
}
}
@@ -0,0 +1,35 @@
/*
* 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.
*/
plugins {
id("com.facebook.react")
alias(libs.plugins.android.library)
alias(libs.plugins.kotlin.android)
}
android {
compileSdk = libs.versions.compileSdk.get().toInt()
buildToolsVersion = libs.versions.buildTools.get()
namespace = "com.facebook.react.popupmenu"
defaultConfig {
minSdk = libs.versions.minSdk.get().toInt()
targetSdk = libs.versions.targetSdk.get().toInt()
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions { jvmTarget = "17" }
}
dependencies {
// Build React Native from source
implementation(project(":packages:react-native:ReactAndroid"))
}
@@ -0,0 +1,3 @@
# We want to have more fine grained control on the Java version for
# ReactAndroid, therefore we disable RGNP Java version alignment mechanism
react.internal.disableJavaVersionAlignment=true
@@ -0,0 +1,20 @@
/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*
* @generated by codegen project: GenerateComponentDescriptorH.js
*/
#pragma once
#include "ShadowNodes.h"
#include <react/renderer/core/ConcreteComponentDescriptor.h>
namespace facebook::react {
using AndroidPopupMenuComponentDescriptor = ConcreteComponentDescriptor<AndroidPopupMenuShadowNode>;
} // namespace facebook::react
@@ -0,0 +1,24 @@
/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*
* @generated by codegen project: GenerateEventEmitterCpp.js
*/
#include "EventEmitters.h"
namespace facebook::react {
void AndroidPopupMenuEventEmitter::onSelectionChange(OnSelectionChange $event) const {
dispatchEvent("selectionChange", [$event=std::move($event)](jsi::Runtime &runtime) {
auto $payload = jsi::Object(runtime);
$payload.setProperty(runtime, "item", $event.item);
return $payload;
});
}
} // namespace facebook::react
@@ -0,0 +1,25 @@
/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*
* @generated by codegen project: GenerateEventEmitterH.js
*/
#pragma once
#include <react/renderer/components/view/ViewEventEmitter.h>
namespace facebook::react {
class AndroidPopupMenuEventEmitter : public ViewEventEmitter {
public:
using ViewEventEmitter::ViewEventEmitter;
struct OnSelectionChange {
int item;
};
void onSelectionChange(OnSelectionChange value) const;
};
} // namespace facebook::react
@@ -0,0 +1,25 @@
/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*
* @generated by codegen project: GeneratePropsCpp.js
*/
#include "Props.h"
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/core/propsConversions.h>
namespace facebook::react {
AndroidPopupMenuProps::AndroidPopupMenuProps(
const PropsParserContext &context,
const AndroidPopupMenuProps &sourceProps,
const RawProps &rawProps): ViewProps(context, sourceProps, rawProps),
menuItems(convertRawProp(context, rawProps, "menuItems", sourceProps.menuItems, {}))
{}
} // namespace facebook::react
@@ -0,0 +1,28 @@
/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*
* @generated by codegen project: GeneratePropsH.js
*/
#pragma once
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <vector>
namespace facebook::react {
class AndroidPopupMenuProps final : public ViewProps {
public:
AndroidPopupMenuProps() = default;
AndroidPopupMenuProps(const PropsParserContext& context, const AndroidPopupMenuProps &sourceProps, const RawProps &rawProps);
#pragma mark - Props
std::vector<std::string> menuItems{};
};
} // namespace facebook::react
@@ -0,0 +1,17 @@
/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*
* @generated by codegen project: GenerateShadowNodeCpp.js
*/
#include "ShadowNodes.h"
namespace facebook::react {
extern const char AndroidPopupMenuComponentName[] = "AndroidPopupMenu";
} // namespace facebook::react
@@ -0,0 +1,32 @@
/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*
* @generated by codegen project: GenerateShadowNodeH.js
*/
#pragma once
#include "EventEmitters.h"
#include "Props.h"
#include "States.h"
#include <react/renderer/components/view/ConcreteViewShadowNode.h>
#include <jsi/jsi.h>
namespace facebook::react {
JSI_EXPORT extern const char AndroidPopupMenuComponentName[];
/*
* `ShadowNode` for <AndroidPopupMenu> component.
*/
using AndroidPopupMenuShadowNode = ConcreteViewShadowNode<
AndroidPopupMenuComponentName,
AndroidPopupMenuProps,
AndroidPopupMenuEventEmitter,
AndroidPopupMenuState>;
} // namespace facebook::react
@@ -0,0 +1,16 @@
/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*
* @generated by codegen project: GenerateStateCpp.js
*/
#include "States.h"
namespace facebook::react {
} // namespace facebook::react
@@ -0,0 +1,34 @@
/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*
* @generated by codegen project: GenerateStateH.js
*/
#pragma once
#ifdef ANDROID
#include <folly/dynamic.h>
#include <react/renderer/mapbuffer/MapBuffer.h>
#include <react/renderer/mapbuffer/MapBufferBuilder.h>
#endif
namespace facebook::react {
class AndroidPopupMenuState {
public:
AndroidPopupMenuState() = default;
#ifdef ANDROID
AndroidPopupMenuState(AndroidPopupMenuState const &previousState, folly::dynamic data){};
folly::dynamic getDynamic() const {
return {};
};
MapBuffer getMapBuffer() const {
return MapBufferBuilder::EMPTY();
};
#endif
};
} // namespace facebook::react
@@ -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.
*/
package com.facebook.react.popupmenu
import com.facebook.react.BaseReactPackage
import com.facebook.react.ViewManagerOnDemandReactPackage
import com.facebook.react.bridge.ModuleSpec
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.module.annotations.ReactModuleList
import com.facebook.react.module.model.ReactModuleInfoProvider
import com.facebook.react.uimanager.ViewManager
@ReactModuleList(nativeModules = arrayOf())
class PopupMenuPackage() : BaseReactPackage(), ViewManagerOnDemandReactPackage {
private var viewManagersMap: Map<String, ModuleSpec>? = null
override fun getModule(name: String, context: ReactApplicationContext): NativeModule? {
return null
}
private fun getViewManagersMap(): Map<String, ModuleSpec> {
val viewManagers =
viewManagersMap
?: mapOf(
ReactPopupMenuManager.REACT_CLASS to
ModuleSpec.viewManagerSpec({ ReactPopupMenuManager() }))
viewManagersMap = viewManagers
return viewManagers
}
protected override fun getViewManagers(context: ReactApplicationContext): List<ModuleSpec> {
return ArrayList(getViewManagersMap().values)
}
override fun getViewManagerNames(context: ReactApplicationContext): Collection<String> {
return getViewManagersMap().keys
}
override fun createViewManager(
reactContext: ReactApplicationContext,
viewManagerName: String
): ViewManager<*, *>? {
val spec: ModuleSpec? = getViewManagersMap().get(viewManagerName)
return if (spec != null) (spec.getProvider().get() as ViewManager<*, *>) else null
}
override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
return ReactModuleInfoProvider { emptyMap() }
}
}
@@ -5,9 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION") // We want to use RCTEventEmitter for interop purposes
package com.facebook.react.views.popupmenu
package com.facebook.react.popupmenu
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.WritableMap
@@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.react.views.popupmenu
package com.facebook.react.popupmenu
import android.content.Context
import android.os.Build
@@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.react.views.popupmenu
package com.facebook.react.popupmenu
import com.facebook.react.bridge.ReadableArray
import com.facebook.react.module.annotations.ReactModule
@@ -0,0 +1,41 @@
/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*
* @generated by codegen project: GeneratePropsJavaDelegate.js
*/
package com.facebook.react.viewmanagers;
import android.view.View;
import androidx.annotation.Nullable;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.BaseViewManagerInterface;
public class AndroidPopupMenuManagerDelegate<T extends View, U extends BaseViewManagerInterface<T> & AndroidPopupMenuManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public AndroidPopupMenuManagerDelegate(U viewManager) {
super(viewManager);
}
@Override
public void setProperty(T view, String propName, @Nullable Object value) {
switch (propName) {
case "menuItems":
mViewManager.setMenuItems(view, (ReadableArray) value);
break;
default:
super.setProperty(view, propName, value);
}
}
@Override
public void receiveCommand(T view, String commandName, ReadableArray args) {
switch (commandName) {
case "show":
mViewManager.show(view);
break;
}
}
}
@@ -0,0 +1,19 @@
/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*
* @generated by codegen project: GeneratePropsJavaInterface.js
*/
package com.facebook.react.viewmanagers;
import android.view.View;
import androidx.annotation.Nullable;
import com.facebook.react.bridge.ReadableArray;
public interface AndroidPopupMenuManagerInterface<T extends View> {
void setMenuItems(T view, @Nullable ReadableArray value);
void show(T view);
}
+11
View File
@@ -0,0 +1,11 @@
/**
* 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.
*
* @format
*/
export type {default} from './js/PopupMenuAndroid';
export type {PopupMenuAndroidInstance} from './js/PopupMenuAndroid';
+12
View File
@@ -0,0 +1,12 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
export {default} from './js/PopupMenuAndroid';
export type {PopupMenuAndroidInstance} from './js/PopupMenuAndroid';
@@ -8,13 +8,13 @@
* @flow strict-local
*/
import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes';
import type {SyntheticEvent} from '../../Types/CoreEventTypes';
import type {RefObject} from 'react';
import type {HostComponent} from 'react-native';
import type {SyntheticEvent} from 'react-native/Libraries/Types/CoreEventTypes';
import PopupMenuAndroidNativeComponent, {
Commands,
} from './PopupMenuAndroidNativeComponent';
} from './PopupMenuAndroidNativeComponent.android';
import nullthrows from 'nullthrows';
import * as React from 'react';
import {useCallback, useImperativeHandle, useRef} from 'react';
@@ -8,7 +8,7 @@
*/
import type * as React from 'react';
import {HostComponent} from '../../../types/public/ReactNativeTypes';
import {HostComponent} from 'react-native';
type PopupMenuAndroidInstance = {
show: () => void;
@@ -12,8 +12,29 @@ import type {RefObject} from 'react';
import type {Node} from 'react';
import * as React from 'react';
import {StyleSheet, View} from 'react-native';
const UnimplementedView = require('../UnimplementedViews/UnimplementedView');
/**
* Common implementation for a simple stubbed view. Simply applies the view's styles to the inner
* View component and renders its children.
*/
class UnimplementedView extends React.Component<{children: Node}> {
render(): React.Node {
return (
<View style={[styles.unimplementedView]}>{this.props.children}</View>
);
}
}
const styles = StyleSheet.create({
unimplementedView: __DEV__
? {
alignSelf: 'flex-start',
borderColor: 'red',
borderWidth: 1,
}
: {},
});
export type PopupMenuAndroidInstance = {
+show: () => void,
@@ -27,7 +48,7 @@ type Props = {
};
function PopupMenuAndroid(props: Props): Node {
return <UnimplementedView />;
return <UnimplementedView>{props.children}</UnimplementedView>;
}
export default PopupMenuAndroid;
@@ -8,16 +8,16 @@
* @format
*/
import type {ViewProps} from '../../../../Libraries/Components/View/ViewPropTypes';
import type {HostComponent} from '../../../../Libraries/Renderer/shims/ReactNativeTypes';
import type {ViewProps} from 'react-native/Libraries/Components/View/ViewPropTypes';
import type {HostComponent} from 'react-native/Libraries/Renderer/shims/ReactNativeTypes';
import type {
DirectEventHandler,
Int32,
} from '../../../../Libraries/Types/CodegenTypes';
} from 'react-native/Libraries/Types/CodegenTypes';
import codegenNativeCommands from '../../../../Libraries/Utilities/codegenNativeCommands';
import codegenNativeComponent from '../../../../Libraries/Utilities/codegenNativeComponent';
import * as React from 'react';
import codegenNativeCommands from 'react-native/Libraries/Utilities/codegenNativeCommands';
import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
type PopupMenuSelectionEvent = $ReadOnly<{
item: Int32,
@@ -0,0 +1,47 @@
{
"name": "@react-native/popup-menu-android",
"version": "0.74.81",
"description": "PopupMenu for the Android platform",
"main": "index.js",
"files": [
"js",
"android",
"!android/build",
"!**/__tests__",
"!**/__fixtures__",
"!**/__mocks__"
],
"keywords": [
"react-native",
"android"
],
"license": "MIT",
"devDependencies": {
"@react-native/codegen": "0.74.81"
},
"peerDependencies": {
"@types/react": "^18.2.6",
"react": "*",
"react-native": "*"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
},
"dependencies": {
"nullthrows": "^1.1.1"
},
"codegenConfig": {
"name": "ReactPopupMenuAndroidSpecs",
"type": "components",
"jsSrcsDir": "js",
"outputDir": {
"android": "android"
},
"includesGeneratedCode": true,
"android": {
"javaPackageName": "com.facebook.react.viewmanagers"
}
}
}
@@ -1,16 +1,18 @@
{
"name": "@react-native/test-renderer",
"private": true,
"version": "0.0.0",
"description": "A Test rendering library for React Native",
"license": "MIT",
"devDependencies": {
"@babel/core": "^7.20.0",
"@babel/plugin-transform-react-jsx": "^7.0.0",
"@babel/preset-env": "^7.20.0",
"@babel/preset-flow": "^7.20.0"
},
"dependencies": {},
"main": "src/index.js",
"peerDependencies": { "jest": "^29.7.0" }
"name": "@react-native/test-renderer",
"private": true,
"version": "0.74.81",
"description": "A Test rendering library for React Native",
"license": "MIT",
"devDependencies": {
"@babel/core": "^7.20.0",
"@babel/plugin-transform-react-jsx": "^7.0.0",
"@babel/preset-env": "^7.20.0",
"@babel/preset-flow": "^7.20.0"
},
"dependencies": {},
"main": "src/index.js",
"peerDependencies": {
"jest": "^29.7.0"
}
}
@@ -7,6 +7,7 @@
#import <React/RCTBridgeDelegate.h>
#import <UIKit/UIKit.h>
#import "RCTRootViewFactory.h"
@class RCTBridge;
@protocol RCTBridgeDelegate;
@@ -57,9 +58,12 @@ NS_ASSUME_NONNULL_BEGIN
/// The window object, used to render the UViewControllers
@property (nonatomic, strong, nonnull) UIWindow *window;
@property (nonatomic, strong, nullable) RCTBridge *bridge;
@property (nonatomic, nullable) RCTBridge *bridge;
@property (nonatomic, strong, nullable) NSString *moduleName;
@property (nonatomic, strong, nullable) NSDictionary *initialProps;
@property (nonatomic, strong, nonnull) RCTRootViewFactory *rootViewFactory;
@property (nonatomic, nullable) RCTSurfacePresenterBridgeAdapter *bridgeAdapter;
/**
* It creates a `RCTBridge` using a delegate and some launch options.
@@ -126,13 +130,6 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (void)setRootView:(UIView *)rootView toRootViewController:(UIViewController *)rootViewController;
/// This method controls whether the App will use RuntimeScheduler. Only applicable in the legacy architecture.
///
/// @return: `YES` to use RuntimeScheduler, `NO` to use JavaScript scheduler. The default value is `YES`.
- (BOOL)runtimeSchedulerEnabled;
@property (nonatomic, strong) RCTSurfacePresenterBridgeAdapter *bridgeAdapter;
/// This method returns a map of Component Descriptors and Components classes that needs to be registered in the
/// new renderer. The Component Descriptor is a string which represent the name used in JS to refer to the native
/// component. The default implementation returns an empty dictionary. Subclasses can override this method to register
@@ -39,84 +39,28 @@
#import <react/renderer/runtimescheduler/RuntimeSchedulerCallInvoker.h>
#import <react/runtime/JSRuntimeFactory.h>
@interface RCTAppDelegate () <
RCTTurboModuleManagerDelegate,
RCTComponentViewFactoryComponentProvider,
RCTContextContainerHandling> {
std::shared_ptr<const facebook::react::ReactNativeConfig> _reactNativeConfig;
facebook::react::ContextContainer::Shared _contextContainer;
}
@interface RCTAppDelegate () <RCTComponentViewFactoryComponentProvider, RCTTurboModuleManagerDelegate>
@end
static NSDictionary *updateInitialProps(NSDictionary *initialProps, BOOL isFabricEnabled)
{
NSMutableDictionary *mutableProps = [initialProps mutableCopy] ?: [NSMutableDictionary new];
return mutableProps;
}
@interface RCTAppDelegate () <RCTCxxBridgeDelegate> {
std::shared_ptr<facebook::react::RuntimeScheduler> _runtimeScheduler;
}
@end
@implementation RCTAppDelegate {
RCTHost *_reactHost;
}
- (instancetype)init
{
if (self = [super init]) {
_contextContainer = std::make_shared<facebook::react::ContextContainer const>();
_reactNativeConfig = std::make_shared<facebook::react::EmptyReactNativeConfig const>();
_contextContainer->insert("ReactNativeConfig", _reactNativeConfig);
}
return self;
}
@implementation RCTAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
RCTSetNewArchEnabled([self newArchEnabled]);
BOOL enableTM = self.turboModuleEnabled;
BOOL fabricEnabled = self.fabricEnabled;
BOOL enableBridgeless = self.bridgelessEnabled;
RCTAppSetupPrepareApp(application, self.turboModuleEnabled);
NSDictionary *initProps = updateInitialProps([self prepareInitialProps], fabricEnabled);
self.rootViewFactory = [self createRCTRootViewFactory];
RCTAppSetupPrepareApp(application, enableTM);
UIView *rootView = [self.rootViewFactory viewWithModuleName:self.moduleName
initialProperties:self.initialProps
launchOptions:launchOptions];
UIView *rootView;
if (enableBridgeless) {
// Enable native view config interop only if both bridgeless mode and Fabric is enabled.
RCTSetUseNativeViewConfigsInBridgelessMode(fabricEnabled);
// Enable TurboModule interop by default in Bridgeless mode
RCTEnableTurboModuleInterop(YES);
RCTEnableTurboModuleInteropBridgeProxy(YES);
[self createReactHost];
if (self.newArchEnabled || self.fabricEnabled) {
[RCTComponentViewFactory currentComponentViewFactory].thirdPartyFabricComponentsProvider = self;
RCTFabricSurface *surface = [_reactHost createSurfaceWithModuleName:self.moduleName initialProperties:initProps];
RCTSurfaceHostingProxyRootView *surfaceHostingProxyRootView = [[RCTSurfaceHostingProxyRootView alloc]
initWithSurface:surface
sizeMeasureMode:RCTSurfaceSizeMeasureModeWidthExact | RCTSurfaceSizeMeasureModeHeightExact];
rootView = (RCTRootView *)surfaceHostingProxyRootView;
rootView.backgroundColor = [UIColor systemBackgroundColor];
} else {
if (!self.bridge) {
self.bridge = [self createBridgeWithDelegate:self launchOptions:launchOptions];
}
if ([self newArchEnabled]) {
self.bridgeAdapter = [[RCTSurfacePresenterBridgeAdapter alloc] initWithBridge:self.bridge
contextContainer:_contextContainer];
self.bridge.surfacePresenter = self.bridgeAdapter.surfacePresenter;
[RCTComponentViewFactory currentComponentViewFactory].thirdPartyFabricComponentsProvider = self;
}
rootView = [self createRootViewWithBridge:self.bridge moduleName:self.moduleName initProps:initProps];
}
[self _logWarnIfCreateRootViewWithBridgeIsOverridden];
[self customizeRootView:(RCTRootView *)rootView];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [self createRootViewController];
[self setRootView:rootView toRootViewController:rootViewController];
@@ -139,26 +83,15 @@ static NSDictionary *updateInitialProps(NSDictionary *initialProps, BOOL isFabri
return nil;
}
- (NSDictionary *)prepareInitialProps
{
return self.initialProps;
}
- (RCTBridge *)createBridgeWithDelegate:(id<RCTBridgeDelegate>)delegate launchOptions:(NSDictionary *)launchOptions
{
return [[RCTBridge alloc] initWithDelegate:delegate launchOptions:launchOptions];
}
- (void)customizeRootView:(RCTRootView *)rootView
{
// Override point for customization after application launch.
}
- (UIView *)createRootViewWithBridge:(RCTBridge *)bridge
moduleName:(NSString *)moduleName
initProps:(NSDictionary *)initProps
{
[self _logWarnIfCreateRootViewWithBridgeIsOverridden];
BOOL enableFabric = self.fabricEnabled;
UIView *rootView = RCTAppSetupDefaultRootView(bridge, moduleName, initProps, enableFabric);
@@ -192,9 +125,9 @@ static NSDictionary *updateInitialProps(NSDictionary *initialProps, BOOL isFabri
rootViewController.view = rootView;
}
- (BOOL)runtimeSchedulerEnabled
- (void)customizeRootView:(RCTRootView *)rootView
{
return YES;
// Override point for customization after application launch.
}
#pragma mark - UISceneDelegate
@@ -207,25 +140,6 @@ static NSDictionary *updateInitialProps(NSDictionary *initialProps, BOOL isFabri
[[NSNotificationCenter defaultCenter] postNotificationName:RCTWindowFrameDidChangeNotification object:self];
}
#pragma mark - RCTCxxBridgeDelegate
- (std::unique_ptr<facebook::react::JSExecutorFactory>)jsExecutorFactoryForBridge:(RCTBridge *)bridge
{
_runtimeScheduler = std::make_shared<facebook::react::RuntimeScheduler>(RCTRuntimeExecutorFromBridge(bridge));
if ([self newArchEnabled]) {
std::shared_ptr<facebook::react::CallInvoker> callInvoker =
std::make_shared<facebook::react::RuntimeSchedulerCallInvoker>(_runtimeScheduler);
RCTTurboModuleManager *turboModuleManager = [[RCTTurboModuleManager alloc] initWithBridge:bridge
delegate:self
jsInvoker:callInvoker];
_contextContainer->erase("RuntimeScheduler");
_contextContainer->insert("RuntimeScheduler", _runtimeScheduler);
return RCTAppSetupDefaultJsExecutorFactory(bridge, turboModuleManager, _runtimeScheduler);
} else {
return RCTAppSetupJsExecutorFactoryForOldArch(bridge, _runtimeScheduler);
}
}
#pragma mark - New Arch Enabled settings
- (BOOL)newArchEnabled
@@ -252,11 +166,33 @@ static NSDictionary *updateInitialProps(NSDictionary *initialProps, BOOL isFabri
return [self newArchEnabled];
}
#pragma mark - RCTComponentViewFactoryComponentProvider
- (NSDictionary<NSString *, Class<RCTComponentViewProtocol>> *)thirdPartyFabricComponents
- (NSURL *)bundleURL
{
return @{};
[NSException raise:@"RCTAppDelegate::bundleURL not implemented"
format:@"Subclasses must implement a valid getBundleURL method"];
return nullptr;
}
#pragma mark - Bridge and Bridge Adapter properties
- (RCTBridge *)bridge
{
return self.rootViewFactory.bridge;
}
- (RCTSurfacePresenterBridgeAdapter *)bridgeAdapter
{
return self.rootViewFactory.bridgeAdapter;
}
- (void)setBridge:(RCTBridge *)bridge
{
self.rootViewFactory.bridge = bridge;
}
- (void)setBridgeAdapter:(RCTSurfacePresenterBridgeAdapter *)bridgeAdapter
{
self.rootViewFactory.bridgeAdapter = bridgeAdapter;
}
#pragma mark - RCTTurboModuleManagerDelegate
@@ -288,43 +224,38 @@ static NSDictionary *updateInitialProps(NSDictionary *initialProps, BOOL isFabri
return RCTAppSetupDefaultModuleFromClass(moduleClass);
}
#pragma mark - New Arch Utilities
#pragma mark - RCTComponentViewFactoryComponentProvider
- (void)createReactHost
- (NSDictionary<NSString *, Class<RCTComponentViewProtocol>> *)thirdPartyFabricComponents
{
return @{};
}
- (RCTRootViewFactory *)createRCTRootViewFactory
{
__weak __typeof(self) weakSelf = self;
_reactHost = [[RCTHost alloc] initWithBundleURL:[self bundleURL]
hostDelegate:nil
turboModuleManagerDelegate:self
jsEngineProvider:^std::shared_ptr<facebook::react::JSRuntimeFactory>() {
return [weakSelf createJSRuntimeFactory];
}];
[_reactHost setBundleURLProvider:^NSURL *() {
return [weakSelf bundleURL];
}];
[_reactHost setContextContainerHandler:self];
[_reactHost start];
}
RCTBundleURLBlock bundleUrlBlock = ^{
RCTAppDelegate *strongSelf = weakSelf;
return strongSelf.bundleURL;
};
- (std::shared_ptr<facebook::react::JSRuntimeFactory>)createJSRuntimeFactory
{
#if USE_HERMES
return std::make_shared<facebook::react::RCTHermesInstance>(_reactNativeConfig, nullptr);
#else
return std::make_shared<facebook::react::RCTJscInstance>();
#endif
}
RCTRootViewFactoryConfiguration *configuration =
[[RCTRootViewFactoryConfiguration alloc] initWithBundleURLBlock:bundleUrlBlock
newArchEnabled:self.fabricEnabled
turboModuleEnabled:self.turboModuleEnabled
bridgelessEnabled:self.bridgelessEnabled];
- (void)didCreateContextContainer:(std::shared_ptr<facebook::react::ContextContainer>)contextContainer
{
contextContainer->insert("ReactNativeConfig", _reactNativeConfig);
}
configuration.createRootViewWithBridge = ^UIView *(RCTBridge *bridge, NSString *moduleName, NSDictionary *initProps)
{
return [weakSelf createRootViewWithBridge:bridge moduleName:moduleName initProps:initProps];
};
- (NSURL *)bundleURL
{
[NSException raise:@"RCTAppDelegate::bundleURL not implemented"
format:@"Subclasses must implement a valid getBundleURL method"];
return nullptr;
configuration.createBridgeWithDelegate = ^RCTBridge *(id<RCTBridgeDelegate> delegate, NSDictionary *launchOptions)
{
return [weakSelf createBridgeWithDelegate:delegate launchOptions:launchOptions];
};
return [[RCTRootViewFactory alloc] initWithConfiguration:configuration andTurboModuleManagerDelegate:self];
}
@end
@@ -0,0 +1,133 @@
/*
* 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 <React/RCTBridge.h>
#import <React/RCTRootView.h>
#import <React/RCTUtils.h>
@protocol RCTCxxBridgeDelegate;
@protocol RCTComponentViewFactoryComponentProvider;
@protocol RCTTurboModuleManagerDelegate;
@class RCTBridge;
@class RCTRootView;
@class RCTSurfacePresenterBridgeAdapter;
NS_ASSUME_NONNULL_BEGIN
#pragma mark - Blocks' definitions
typedef UIView *_Nonnull (
^RCTCreateRootViewWithBridgeBlock)(RCTBridge *bridge, NSString *moduleName, NSDictionary *initProps);
typedef RCTBridge *_Nonnull (
^RCTCreateBridgeWithDelegateBlock)(id<RCTBridgeDelegate> delegate, NSDictionary *launchOptions);
typedef NSURL *_Nullable (^RCTSourceURLForBridgeBlock)(RCTBridge *bridge);
typedef NSURL *_Nullable (^RCTBundleURLBlock)(void);
typedef NSArray<id<RCTBridgeModule>> *_Nonnull (^RCTExtraModulesForBridgeBlock)(RCTBridge *bridge);
typedef NSDictionary<NSString *, Class> *_Nonnull (^RCTExtraLazyModuleClassesForBridge)(RCTBridge *bridge);
typedef BOOL (^RCTBridgeDidNotFindModuleBlock)(RCTBridge *bridge, NSString *moduleName);
#pragma mark - RCTRootViewFactory Configuration
@interface RCTRootViewFactoryConfiguration : NSObject
/// This property controls whether the App will use the Fabric renderer of the New Architecture or not.
@property (nonatomic, assign, readonly) BOOL fabricEnabled;
/// This property controls whether React Native's new initialization layer is enabled.
@property (nonatomic, assign, readonly) BOOL bridgelessEnabled;
/// This method controls whether the `turboModules` feature of the New Architecture is turned on or off
@property (nonatomic, assign, readonly) BOOL turboModuleEnabled;
/// Return the bundle URL for the main bundle.
@property (nonatomic, nonnull) RCTBundleURLBlock bundleURLBlock;
/**
* Use this method to initialize a new instance of `RCTRootViewFactoryConfiguration` by passing a `bundleURL`
*
* Which is the location of the JavaScript source file. When running from the packager
* this should be an absolute URL, e.g. `http://localhost:8081/index.ios.bundle`.
* When running from a locally bundled JS file, this should be a `file://` url
* pointing to a path inside the app resources, e.g. `file://.../main.jsbundle`.
*
*/
- (instancetype)initWithBundleURLBlock:(RCTBundleURLBlock)bundleURLBlock
newArchEnabled:(BOOL)newArchEnabled
turboModuleEnabled:(BOOL)turboModuleEnabled
bridgelessEnabled:(BOOL)bridgelessEnabled NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithBundleURL:(NSURL *)bundleURL
newArchEnabled:(BOOL)newArchEnabled
turboModuleEnabled:(BOOL)turboModuleEnabled
bridgelessEnabled:(BOOL)bridgelessEnabled __deprecated;
/**
* Block that allows to override logic of creating root view instance.
* It creates a `UIView` starting from a bridge, a module name and a set of initial properties.
* By default, it is invoked using the bridge created by `RCTCreateBridgeWithDelegateBlock` (or the default
* implementation) and the `moduleName` variable comes from `viewWithModuleName:initialProperties:launchOptions` of
* `RCTRootViewFactory`.
*
* @parameter: bridge - an instance of the `RCTBridge` object.
* @parameter: moduleName - the name of the app, used by Metro to resolve the module.
* @parameter: initProps - a set of initial properties.
*
* @returns: a UIView properly configured with a bridge for React Native.
*/
@property (nonatomic, nullable) RCTCreateRootViewWithBridgeBlock createRootViewWithBridge;
/**
* Block that allows to override default behavior of creating bridge.
* It should return `RCTBridge` using a delegate and some launch options.
*
* By default, it is invoked passing `self` as a delegate.
*
* @parameter: delegate - an object that implements the `RCTBridgeDelegate` protocol.
* @parameter: launchOptions - a dictionary with a set of options.
*
* @returns: a newly created instance of RCTBridge.
*/
@property (nonatomic, nullable) RCTCreateBridgeWithDelegateBlock createBridgeWithDelegate;
@end
#pragma mark - RCTRootViewFactory
/**
* The RCTRootViewFactory is an utility class that encapsulates the logic of creating a new RCTRootView based on the
* current state of the environment. It allows you to initialize your app root view for old architecture, new
* architecture and bridgless mode.
*
* This class is used to initalize rootView in RCTAppDelegate, but you can also use it separately.
*
* Create a new instance of this class (make sure to retain it) and call the
* `viewWithModuleName:initialProperties:launchOptions` method to create new RCTRootView.
*/
@interface RCTRootViewFactory : NSObject
@property (nonatomic, strong, nullable) RCTBridge *bridge;
@property (nonatomic, strong, nullable) RCTSurfacePresenterBridgeAdapter *bridgeAdapter;
- (instancetype)initWithConfiguration:(RCTRootViewFactoryConfiguration *)configuration
andTurboModuleManagerDelegate:(id<RCTTurboModuleManagerDelegate>)turboModuleManagerDelegate;
/**
* This method can be used to create new RCTRootViews on demand.
*
* @parameter: moduleName - the name of the app, used by Metro to resolve the module.
* @parameter: initialProperties - a set of initial properties.
* @parameter: launchOptions - a dictionary with a set of options.
*/
- (UIView *_Nonnull)viewWithModuleName:(NSString *)moduleName
initialProperties:(NSDictionary *__nullable)initialProperties
launchOptions:(NSDictionary *__nullable)launchOptions;
- (UIView *_Nonnull)viewWithModuleName:(NSString *)moduleName
initialProperties:(NSDictionary *__nullable)initialProperties;
- (UIView *_Nonnull)viewWithModuleName:(NSString *)moduleName;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,268 @@
/*
* 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 "RCTRootViewFactory.h"
#import <React/RCTCxxBridgeDelegate.h>
#import <React/RCTLog.h>
#import <React/RCTRootView.h>
#import <React/RCTSurfacePresenterBridgeAdapter.h>
#import <React/RCTUtils.h>
#import <react/renderer/runtimescheduler/RuntimeScheduler.h>
#import "RCTAppDelegate.h"
#import "RCTAppSetupUtils.h"
#if RN_DISABLE_OSS_PLUGIN_HEADER
#import <RCTTurboModulePlugin/RCTTurboModulePlugin.h>
#else
#import <React/CoreModulesPlugins.h>
#endif
#import <React/RCTBundleURLProvider.h>
#import <React/RCTComponentViewFactory.h>
#import <React/RCTComponentViewProtocol.h>
#import <React/RCTFabricSurface.h>
#import <React/RCTSurfaceHostingProxyRootView.h>
#import <React/RCTSurfacePresenter.h>
#import <ReactCommon/RCTContextContainerHandling.h>
#if USE_HERMES
#import <ReactCommon/RCTHermesInstance.h>
#else
#import <ReactCommon/RCTJscInstance.h>
#endif
#import <ReactCommon/RCTHost+Internal.h>
#import <ReactCommon/RCTHost.h>
#import <ReactCommon/RCTTurboModuleManager.h>
#import <react/config/ReactNativeConfig.h>
#import <react/renderer/runtimescheduler/RuntimeScheduler.h>
#import <react/renderer/runtimescheduler/RuntimeSchedulerCallInvoker.h>
#import <react/runtime/JSRuntimeFactory.h>
static NSString *const kRNConcurrentRoot = @"concurrentRoot";
static NSDictionary *updateInitialProps(NSDictionary *initialProps, BOOL isFabricEnabled)
{
NSMutableDictionary *mutableProps = initialProps != NULL ? [initialProps mutableCopy] : [NSMutableDictionary new];
// Hardcoding the Concurrent Root as it it not recommended to
// have the concurrentRoot turned off when Fabric is enabled.
mutableProps[kRNConcurrentRoot] = @(isFabricEnabled);
return mutableProps;
}
@implementation RCTRootViewFactoryConfiguration
- (instancetype)initWithBundleURL:(NSURL *)bundleURL
newArchEnabled:(BOOL)newArchEnabled
turboModuleEnabled:(BOOL)turboModuleEnabled
bridgelessEnabled:(BOOL)bridgelessEnabled
{
return [self
initWithBundleURLBlock:^{
return bundleURL;
}
newArchEnabled:newArchEnabled
turboModuleEnabled:turboModuleEnabled
bridgelessEnabled:bridgelessEnabled];
}
- (instancetype)initWithBundleURLBlock:(RCTBundleURLBlock)bundleURLBlock
newArchEnabled:(BOOL)newArchEnabled
turboModuleEnabled:(BOOL)turboModuleEnabled
bridgelessEnabled:(BOOL)bridgelessEnabled
{
if (self = [super init]) {
_bundleURLBlock = bundleURLBlock;
_fabricEnabled = newArchEnabled;
_turboModuleEnabled = turboModuleEnabled;
_bridgelessEnabled = bridgelessEnabled;
}
return self;
}
@end
@interface RCTRootViewFactory () <RCTContextContainerHandling> {
std::shared_ptr<const facebook::react::ReactNativeConfig> _reactNativeConfig;
facebook::react::ContextContainer::Shared _contextContainer;
}
@end
@interface RCTRootViewFactory () <RCTCxxBridgeDelegate> {
std::shared_ptr<facebook::react::RuntimeScheduler> _runtimeScheduler;
}
@end
@implementation RCTRootViewFactory {
RCTHost *_reactHost;
RCTRootViewFactoryConfiguration *_configuration;
__weak id<RCTTurboModuleManagerDelegate> _turboModuleManagerDelegate;
}
- (instancetype)initWithConfiguration:(RCTRootViewFactoryConfiguration *)configuration
andTurboModuleManagerDelegate:(id<RCTTurboModuleManagerDelegate>)turboModuleManagerDelegate
{
if (self = [super init]) {
_configuration = configuration;
_contextContainer = std::make_shared<facebook::react::ContextContainer const>();
_reactNativeConfig = std::make_shared<facebook::react::EmptyReactNativeConfig const>();
_contextContainer->insert("ReactNativeConfig", _reactNativeConfig);
_turboModuleManagerDelegate = turboModuleManagerDelegate;
}
return self;
}
- (UIView *)viewWithModuleName:(NSString *)moduleName initialProperties:(NSDictionary *)initialProperties
{
return [self viewWithModuleName:moduleName initialProperties:initialProperties launchOptions:nil];
}
- (UIView *)viewWithModuleName:(NSString *)moduleName
{
return [self viewWithModuleName:moduleName initialProperties:nil launchOptions:nil];
}
- (UIView *)viewWithModuleName:(NSString *)moduleName
initialProperties:(NSDictionary *)initialProperties
launchOptions:(NSDictionary *)launchOptions
{
NSDictionary *initProps = updateInitialProps(initialProperties, self->_configuration.fabricEnabled);
if (self->_configuration.bridgelessEnabled) {
// Enable native view config interop only if both bridgeless mode and Fabric is enabled.
RCTSetUseNativeViewConfigsInBridgelessMode(self->_configuration.fabricEnabled);
// Enable TurboModule interop by default in Bridgeless mode
RCTEnableTurboModuleInterop(YES);
RCTEnableTurboModuleInteropBridgeProxy(YES);
[self createReactHostIfNeeded:launchOptions];
RCTFabricSurface *surface = [_reactHost createSurfaceWithModuleName:moduleName initialProperties:initProps];
RCTSurfaceHostingProxyRootView *surfaceHostingProxyRootView = [[RCTSurfaceHostingProxyRootView alloc]
initWithSurface:surface
sizeMeasureMode:RCTSurfaceSizeMeasureModeWidthExact | RCTSurfaceSizeMeasureModeHeightExact];
return surfaceHostingProxyRootView;
}
[self createBridgeIfNeeded:launchOptions];
[self createBridgeAdapterIfNeeded];
if (self->_configuration.createRootViewWithBridge != nil) {
return self->_configuration.createRootViewWithBridge(self.bridge, moduleName, initProps);
}
return [self createRootViewWithBridge:self.bridge moduleName:moduleName initProps:initProps];
}
- (RCTBridge *)createBridgeWithDelegate:(id<RCTBridgeDelegate>)delegate launchOptions:(NSDictionary *)launchOptions
{
return [[RCTBridge alloc] initWithDelegate:delegate launchOptions:launchOptions];
}
- (UIView *)createRootViewWithBridge:(RCTBridge *)bridge
moduleName:(NSString *)moduleName
initProps:(NSDictionary *)initProps
{
BOOL enableFabric = self->_configuration.fabricEnabled;
UIView *rootView = RCTAppSetupDefaultRootView(bridge, moduleName, initProps, enableFabric);
rootView.backgroundColor = [UIColor systemBackgroundColor];
return rootView;
}
#pragma mark - RCTCxxBridgeDelegate
- (std::unique_ptr<facebook::react::JSExecutorFactory>)jsExecutorFactoryForBridge:(RCTBridge *)bridge
{
_runtimeScheduler = std::make_shared<facebook::react::RuntimeScheduler>(RCTRuntimeExecutorFromBridge(bridge));
if (RCTIsNewArchEnabled()) {
std::shared_ptr<facebook::react::CallInvoker> callInvoker =
std::make_shared<facebook::react::RuntimeSchedulerCallInvoker>(_runtimeScheduler);
RCTTurboModuleManager *turboModuleManager =
[[RCTTurboModuleManager alloc] initWithBridge:bridge
delegate:_turboModuleManagerDelegate
jsInvoker:callInvoker];
_contextContainer->erase("RuntimeScheduler");
_contextContainer->insert("RuntimeScheduler", _runtimeScheduler);
return RCTAppSetupDefaultJsExecutorFactory(bridge, turboModuleManager, _runtimeScheduler);
} else {
return RCTAppSetupJsExecutorFactoryForOldArch(bridge, _runtimeScheduler);
}
}
- (void)createBridgeIfNeeded:(NSDictionary *)launchOptions
{
if (self.bridge != nil) {
return;
}
if (self->_configuration.createBridgeWithDelegate != nil) {
self.bridge = self->_configuration.createBridgeWithDelegate(self, launchOptions);
} else {
self.bridge = [self createBridgeWithDelegate:self launchOptions:launchOptions];
}
}
- (void)createBridgeAdapterIfNeeded
{
if (!self->_configuration.fabricEnabled || self.bridgeAdapter) {
return;
}
self.bridgeAdapter = [[RCTSurfacePresenterBridgeAdapter alloc] initWithBridge:self.bridge
contextContainer:_contextContainer];
self.bridge.surfacePresenter = self.bridgeAdapter.surfacePresenter;
}
#pragma mark - New Arch Utilities
- (void)createReactHostIfNeeded:(NSDictionary *)launchOptions
{
if (_reactHost) {
return;
}
__weak __typeof(self) weakSelf = self;
_reactHost = [[RCTHost alloc] initWithBundleURLProvider:self->_configuration.bundleURLBlock
hostDelegate:nil
turboModuleManagerDelegate:_turboModuleManagerDelegate
jsEngineProvider:^std::shared_ptr<facebook::react::JSRuntimeFactory>() {
return [weakSelf createJSRuntimeFactory];
}
launchOptions:launchOptions];
[_reactHost setBundleURLProvider:^NSURL *() {
return [weakSelf bundleURL];
}];
[_reactHost setContextContainerHandler:self];
[_reactHost start];
}
- (std::shared_ptr<facebook::react::JSRuntimeFactory>)createJSRuntimeFactory
{
#if USE_HERMES
return std::make_shared<facebook::react::RCTHermesInstance>(_reactNativeConfig, nullptr);
#else
return std::make_shared<facebook::react::RCTJscInstance>();
#endif
}
- (void)didCreateContextContainer:(std::shared_ptr<facebook::react::ContextContainer>)contextContainer
{
contextContainer->insert("ReactNativeConfig", _reactNativeConfig);
}
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
return [self bundleURL];
}
- (NSURL *)bundleURL
{
return self->_configuration.bundleURLBlock();
}
@end
@@ -1,13 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @flow strict-local
*/
export * from '../../../src/private/specs/components/PopupMenuAndroidNativeComponent';
import PopupMenuAndroidNativeComponent from '../../../src/private/specs/components/PopupMenuAndroidNativeComponent';
export default PopupMenuAndroidNativeComponent;
@@ -144,6 +144,7 @@ const ReactNativeStyleAttributes: {[string]: AnyAttributeType, ...} = {
borderTopLeftRadius: true,
borderTopRightRadius: true,
borderTopStartRadius: true,
cursor: true,
opacity: true,
pointerEvents: true,
+2 -2
View File
@@ -14,8 +14,8 @@ const version: $ReadOnly<{
patch: number,
prerelease: string | null,
}> = {
major: 1000,
minor: 0,
major: 0,
minor: 74,
patch: 0,
prerelease: null,
};
@@ -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.
*
* @format
*/
type Module = Object;
type RegisterCallableModule = (
name: string,
moduleOrFactory: Module | (() => Module),
) => void;
export const registerCallableModule: RegisterCallableModule;
-1
View File
@@ -308,7 +308,6 @@ export type Props<ItemT> = {
* Also inherits [ScrollView Props](docs/scrollview.html#props), unless it is nested in another FlatList of same orientation.
*/
class FlatList<ItemT> extends React.PureComponent<Props<ItemT>, void> {
props: Props<ItemT>;
/**
* Scrolls to the end of the content. May be janky without `getItemLayout` prop.
*/
@@ -1020,6 +1020,54 @@ Please follow the instructions at: fburl.com/rn-remote-assets`,
});
});
it('detects a component stack for ts, tsx, jsx, and js files', () => {
expect(
parseLogBoxLog([
'Some kind of message\n in MyTSComponent (at MyTSXComponent.ts:1)\n in MyTSXComponent (at MyTSCComponent.tsx:1)\n in MyJSXComponent (at MyJSXComponent.jsx:1)\n in MyJSComponent (at MyJSComponent.js:1)',
]),
).toEqual({
componentStack: [
{
content: 'MyTSComponent',
fileName: 'MyTSXComponent.ts',
location: {
column: -1,
row: 1,
},
},
{
content: 'MyTSXComponent',
fileName: 'MyTSCComponent.tsx',
location: {
column: -1,
row: 1,
},
},
{
content: 'MyJSXComponent',
fileName: 'MyJSXComponent.jsx',
location: {
column: -1,
row: 1,
},
},
{
content: 'MyJSComponent',
fileName: 'MyJSComponent.js',
location: {
column: -1,
row: 1,
},
},
],
category: 'Some kind of message',
message: {
content: 'Some kind of message',
substitutions: [],
},
});
});
it('detects a component stack in the first argument (JSC)', () => {
expect(
parseLogBoxLog([
@@ -192,7 +192,7 @@ export function parseComponentStack(message: string): ComponentStack {
if (!s) {
return null;
}
const match = s.match(/(.*) \(at (.*\.js):([\d]+)\)/);
const match = s.match(/(.*) \(at (.*\.(?:js|jsx|ts|tsx)):([\d]+)\)/);
if (!match) {
return null;
}
@@ -20,7 +20,6 @@ import View from '../Components/View/View';
import DebuggingOverlay from '../Debugging/DebuggingOverlay';
import useSubscribeToDebuggingOverlayRegistry from '../Debugging/useSubscribeToDebuggingOverlayRegistry';
import RCTDeviceEventEmitter from '../EventEmitter/RCTDeviceEventEmitter';
import ReactDevToolsOverlay from '../Inspector/ReactDevToolsOverlay';
import LogBoxNotificationContainer from '../LogBox/LogBoxNotificationContainer';
import StyleSheet from '../StyleSheet/StyleSheet';
import {RootTagContext, createRootTag} from './RootTag';
@@ -64,6 +63,26 @@ const InspectorDeferred = ({
);
};
type ReactDevToolsOverlayDeferredProps = {
inspectedViewRef: InspectedViewRef,
reactDevToolsAgent: ReactDevToolsAgent,
};
const ReactDevToolsOverlayDeferred = ({
inspectedViewRef,
reactDevToolsAgent,
}: ReactDevToolsOverlayDeferredProps) => {
const ReactDevToolsOverlay =
require('../Inspector/ReactDevToolsOverlay').default;
return (
<ReactDevToolsOverlay
inspectedViewRef={inspectedViewRef}
reactDevToolsAgent={reactDevToolsAgent}
/>
);
};
const AppContainer = ({
children,
fabric,
@@ -155,7 +174,7 @@ const AppContainer = ({
<DebuggingOverlay ref={debuggingOverlayRef} />
{reactDevToolsAgent != null && (
<ReactDevToolsOverlay
<ReactDevToolsOverlayDeferred
inspectedViewRef={innerViewRef}
reactDevToolsAgent={reactDevToolsAgent}
/>
@@ -27,6 +27,8 @@ export type DimensionValue =
type AnimatableNumericValue = number | Animated.AnimatedNode;
type AnimatableStringValue = string | Animated.AnimatedNode;
export type CursorValue = 'auto' | 'pointer';
/**
* Flex Prop Types
* @see https://reactnative.dev/docs/flexbox
@@ -274,6 +276,7 @@ export interface ViewStyle extends FlexStyle, ShadowStyleIOS, TransformsStyle {
* Controls whether the View can be the target of touch events.
*/
pointerEvents?: 'box-none' | 'none' | 'box-only' | 'auto' | undefined;
cursor?: CursorValue | undefined;
}
export type FontVariant =
@@ -403,4 +406,5 @@ export interface ImageStyle extends FlexStyle, ShadowStyleIOS, TransformsStyle {
tintColor?: ColorValue | undefined;
opacity?: AnimatableNumericValue | undefined;
objectFit?: 'cover' | 'contain' | 'fill' | 'scale-down' | undefined;
cursor?: CursorValue | undefined;
}
@@ -37,6 +37,8 @@ export type EdgeInsetsValue = {
export type DimensionValue = number | string | 'auto' | AnimatedNode | null;
export type AnimatableNumericValue = number | AnimatedNode;
export type CursorValue = 'auto' | 'pointer';
/**
* React Native's layout system is based on Flexbox and is powered both
* on iOS and Android by an open source project called `Yoga`:
@@ -729,6 +731,7 @@ export type ____ViewStyle_InternalCore = $ReadOnly<{
opacity?: AnimatableNumericValue,
elevation?: number,
pointerEvents?: 'auto' | 'none' | 'box-none' | 'box-only',
cursor?: CursorValue,
}>;
export type ____ViewStyle_Internal = $ReadOnly<{
@@ -1773,41 +1773,6 @@ declare export default typeof NativeKeyboardObserver;
"
`;
exports[`public API should not change unintentionally Libraries/Components/PopupMenuAndroid/PopupMenuAndroid.android.js 1`] = `
"export type PopupMenuAndroidInstance = {
+show: () => void,
};
type Props = {
menuItems: $ReadOnlyArray<string>,
onSelectionChange: (number) => void,
children: React.Node,
instanceRef: RefObject<?PopupMenuAndroidInstance>,
};
declare export default function PopupMenuAndroid(Props): React.Node;
"
`;
exports[`public API should not change unintentionally Libraries/Components/PopupMenuAndroid/PopupMenuAndroid.js 1`] = `
"export type PopupMenuAndroidInstance = {
+show: () => void,
};
type Props = {
menuItems: $ReadOnlyArray<string>,
onSelectionChange: (number) => void,
children: Node,
instanceRef: RefObject<?PopupMenuAndroidInstance>,
};
declare function PopupMenuAndroid(props: Props): Node;
declare export default typeof PopupMenuAndroid;
"
`;
exports[`public API should not change unintentionally Libraries/Components/PopupMenuAndroid/PopupMenuAndroidNativeComponent.js 1`] = `
"export * from \\"../../../src/private/specs/components/PopupMenuAndroidNativeComponent\\";
declare export default typeof PopupMenuAndroidNativeComponent;
"
`;
exports[`public API should not change unintentionally Libraries/Components/Pressable/Pressable.js 1`] = `
"type ViewStyleProp = $ElementType<React.ElementConfig<typeof View>, \\"style\\">;
export type StateCallbackType = $ReadOnly<{|
@@ -7458,6 +7423,7 @@ export type EdgeInsetsValue = {
};
export type DimensionValue = number | string | \\"auto\\" | AnimatedNode | null;
export type AnimatableNumericValue = number | AnimatedNode;
export type CursorValue = \\"auto\\" | \\"pointer\\";
type ____LayoutStyle_Internal = $ReadOnly<{
display?: \\"none\\" | \\"flex\\",
width?: DimensionValue,
@@ -7608,6 +7574,7 @@ export type ____ViewStyle_InternalCore = $ReadOnly<{
opacity?: AnimatableNumericValue,
elevation?: number,
pointerEvents?: \\"auto\\" | \\"none\\" | \\"box-none\\" | \\"box-only\\",
cursor?: CursorValue,
}>;
export type ____ViewStyle_Internal = $ReadOnly<{
...____ViewStyle_InternalCore,
@@ -9026,7 +8993,6 @@ declare module.exports: {
get ImageBackground(): ImageBackground,
get InputAccessoryView(): InputAccessoryView,
get KeyboardAvoidingView(): KeyboardAvoidingView,
get PopupMenuAndroid(): PopupMenuAndroid,
get Modal(): Modal,
get Pressable(): Pressable,
get ProgressBarAndroid(): ProgressBarAndroid,
@@ -0,0 +1,30 @@
/*
* 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 <React/RCTBridge.h>
#ifdef __cplusplus
#import <jsinspector-modern/ReactCdp.h>
#endif
@interface RCTBridge (Inspector)
/**
* The HostTarget for this bridge, if one has been created. Exposed for RCTCxxBridge only.
*/
@property (nonatomic, assign, readonly)
#ifdef __cplusplus
facebook::react::jsinspector_modern::PageTarget *
#else
// The inspector infrastructure cannot be used in C or Swift code.
void *
#endif
inspectorTarget;
@property (nonatomic, readonly, getter=isInspectable) BOOL inspectable;
@end
@@ -6,9 +6,6 @@
*/
#import <React/RCTBridge.h>
#ifdef __cplusplus
#import <jsinspector-modern/ReactCdp.h>
#endif
@class RCTModuleRegistry;
@class RCTModuleData;
@@ -73,17 +70,6 @@ RCT_EXTERN void RCTRegisterModule(Class);
*/
@property (nonatomic, strong, readonly) RCTModuleRegistry *moduleRegistry;
/**
* The page target for this bridge, if one has been created. Exposed for RCTCxxBridge only.
*/
@property (nonatomic, assign, readonly)
#ifdef __cplusplus
facebook::react::jsinspector_modern::PageTarget *
#else
// The inspector infrastructure cannot be used in C code.
void *
#endif
inspectorTarget;
@end
@interface RCTBridge (RCTCxxBridge)
@@ -155,12 +141,6 @@ RCT_EXTERN void RCTRegisterModule(Class);
@end
@interface RCTBridge (Inspector)
@property (nonatomic, readonly, getter=isInspectable) BOOL inspectable;
@end
@interface RCTCxxBridge : RCTBridge
// TODO(cjhopman): this seems unsafe unless we require that it is only called on the main js queue.
@@ -6,6 +6,7 @@
*/
#import "RCTBridge.h"
#import "RCTBridge+Inspector.h"
#import "RCTBridge+Private.h"
#import <objc/runtime.h>
@@ -0,0 +1,20 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#ifdef __cplusplus
#import <ReactCommon/CallInvoker.h>
#endif
#import "RCTBridgeProxy.h"
@interface RCTBridgeProxy (Cxx)
#ifdef __cplusplus
@property (nonatomic, readwrite) std::shared_ptr<facebook::react::CallInvoker> jsCallInvoker;
#endif
@end
@@ -9,19 +9,23 @@
#import "RCTBridgeModule.h"
NS_ASSUME_NONNULL_BEGIN
@class RCTBundleManager;
@class RCTCallableJSModules;
@class RCTModuleRegistry;
@class RCTViewRegistry;
@interface RCTBridgeProxy : NSProxy
- (instancetype)initWithViewRegistry:(RCTViewRegistry *)viewRegistry
moduleRegistry:(RCTModuleRegistry *)moduleRegistry
bundleManager:(RCTBundleManager *)bundleManager
callableJSModules:(RCTCallableJSModules *)callableJSModules
dispatchToJSThread:(void (^)(dispatch_block_t))dispatchToJSThread
registerSegmentWithId:(void (^)(NSNumber *, NSString *))registerSegmentWithId
runtime:(void *)runtime NS_DESIGNATED_INITIALIZER;
runtime:(void *)runtime
launchOptions:(nullable NSDictionary *)launchOptions NS_DESIGNATED_INITIALIZER;
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel;
- (void)forwardInvocation:(NSInvocation *)invocation;
@@ -34,4 +38,7 @@
*/
- (id)moduleForClass:(Class)moduleClass;
- (id)moduleForName:(NSString *)moduleName lazilyLoadIfNecessary:(BOOL)lazilyLoad;
@end
NS_ASSUME_NONNULL_END
@@ -6,10 +6,13 @@
*/
#import "RCTBridgeProxy.h"
#import "RCTBridgeProxy+Cxx.h"
#import <React/RCTBridge+Private.h>
#import <React/RCTBridge.h>
#import <React/RCTLog.h>
#import <React/RCTUIManager.h>
#import <ReactCommon/CallInvoker.h>
#import <jsi/jsi.h>
using namespace facebook;
@@ -21,11 +24,18 @@ using namespace facebook;
- (void)forwardInvocation:(NSInvocation *)invocation;
@end
@interface RCTBridgeProxy ()
@property (nonatomic, readwrite) std::shared_ptr<facebook::react::CallInvoker> jsCallInvoker;
@end
@implementation RCTBridgeProxy {
RCTUIManagerProxy *_uiManagerProxy;
RCTModuleRegistry *_moduleRegistry;
RCTBundleManager *_bundleManager;
RCTCallableJSModules *_callableJSModules;
NSDictionary *_launchOptions;
void (^_dispatchToJSThread)(dispatch_block_t);
void (^_registerSegmentWithId)(NSNumber *, NSString *);
void *_runtime;
@@ -38,6 +48,7 @@ using namespace facebook;
dispatchToJSThread:(void (^)(dispatch_block_t))dispatchToJSThread
registerSegmentWithId:(void (^)(NSNumber *, NSString *))registerSegmentWithId
runtime:(void *)runtime
launchOptions:(nullable NSDictionary *)launchOptions
{
self = [super self];
if (self) {
@@ -48,6 +59,7 @@ using namespace facebook;
_dispatchToJSThread = dispatchToJSThread;
_registerSegmentWithId = registerSegmentWithId;
_runtime = runtime;
_launchOptions = [launchOptions copy];
}
return self;
}
@@ -84,6 +96,12 @@ using namespace facebook;
return _runtime;
}
- (std::shared_ptr<facebook::react::CallInvoker>)jsCallInvoker
{
[self logWarning:@"Please migrate to RuntimeExecutor" cmd:_cmd];
return _jsCallInvoker;
}
/**
* RCTModuleRegistry
*/
@@ -176,8 +194,7 @@ using namespace facebook;
- (NSDictionary *)launchOptions
{
[self logError:@"This method is not supported. Returning nil." cmd:_cmd];
return nil;
return _launchOptions;
}
- (BOOL)loading
@@ -11,6 +11,7 @@
#import <React/RCTAnimationType.h>
#import <React/RCTBorderCurve.h>
#import <React/RCTBorderStyle.h>
#import <React/RCTCursor.h>
#import <React/RCTDefines.h>
#import <React/RCTLog.h>
#import <React/RCTPointerEvents.h>
@@ -80,6 +81,8 @@ typedef NSURL RCTFileURL;
+ (UIBarStyle)UIBarStyle:(id)json __deprecated;
#endif
+ (RCTCursor)RCTCursor:(id)json;
+ (CGFloat)CGFloat:(id)json;
+ (CGPoint)CGPoint:(id)json;
+ (CGSize)CGSize:(id)json;
@@ -545,6 +545,15 @@ RCT_ENUM_CONVERTER(
UIBarStyleDefault,
integerValue)
RCT_ENUM_CONVERTER(
RCTCursor,
(@{
@"auto" : @(RCTCursorAuto),
@"pointer" : @(RCTCursorPointer),
}),
RCTCursorAuto,
integerValue)
static void convertCGStruct(const char *type, NSArray *fields, CGFloat *result, id json)
{
NSUInteger count = fields.count;
@@ -21,8 +21,8 @@ NSDictionary* RCTGetReactNativeVersion(void)
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^(void){
__rnVersion = @{
RCTVersionMajor: @(1000),
RCTVersionMinor: @(0),
RCTVersionMajor: @(0),
RCTVersionMinor: @(74),
RCTVersionPatch: @(0),
RCTVersionPrerelease: [NSNull null],
};
@@ -56,6 +56,13 @@ NS_ASSUME_NONNULL_BEGIN
*/
@property (nonatomic, copy, nullable) RCTSurfaceHostingViewActivityIndicatorViewFactory activityIndicatorViewFactory;
/**
* When set to `YES`, the activity indicator is not automatically hidden when the Surface stage changes.
* In this scenario, users should invoke `hideActivityIndicator` to remove it.
*
* @param disabled: if `YES`, the auto-hide is disabled. Otherwise the loading view will be hidden automatically
*/
- (void)disableActivityIndicatorAutoHide:(BOOL)disabled;
@end
NS_ASSUME_NONNULL_END
@@ -24,6 +24,7 @@
UIView *_Nullable _activityIndicatorView;
UIView *_Nullable _surfaceView;
RCTSurfaceStage _stage;
BOOL _autoHideDisabled;
}
RCT_NOT_IMPLEMENTED(-(instancetype)init)
@@ -36,6 +37,7 @@ RCT_NOT_IMPLEMENTED(-(nullable instancetype)initWithCoder : (NSCoder *)coder)
if (self = [super initWithFrame:CGRectZero]) {
_surface = surface;
_sizeMeasureMode = sizeMeasureMode;
_autoHideDisabled = NO;
_surface.delegate = self;
_stage = surface.stage;
@@ -124,6 +126,10 @@ RCT_NOT_IMPLEMENTED(-(nullable instancetype)initWithCoder : (NSCoder *)coder)
_sizeMeasureMode = sizeMeasureMode;
[self _invalidateLayout];
}
- (void)disableActivityIndicatorAutoHide:(BOOL)disabled
{
_autoHideDisabled = disabled;
}
#pragma mark - isActivityIndicatorViewVisible
@@ -162,7 +168,16 @@ RCT_NOT_IMPLEMENTED(-(nullable instancetype)initWithCoder : (NSCoder *)coder)
_surfaceView = _surface.view;
_surfaceView.frame = self.bounds;
_surfaceView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self addSubview:_surfaceView];
if (_activityIndicatorView && _autoHideDisabled) {
// The activity indicator is still showing and the surface is set to
// prevent the auto hide. This means that the application will take care of
// hiding it when it's ready.
// Let's add the surfaceView below the activity indicator so it's ready once
// the activity indicator is hidden.
[self insertSubview:_surfaceView belowSubview:_activityIndicatorView];
} else {
[self addSubview:_surfaceView];
}
} else {
[_surfaceView removeFromSuperview];
_surfaceView = nil;
@@ -204,7 +219,7 @@ RCT_NOT_IMPLEMENTED(-(nullable instancetype)initWithCoder : (NSCoder *)coder)
- (void)_updateViews
{
self.isSurfaceViewVisible = RCTSurfaceStageIsRunning(_stage);
self.isActivityIndicatorViewVisible = RCTSurfaceStageIsPreparing(_stage);
self.isActivityIndicatorViewVisible = _autoHideDisabled || RCTSurfaceStageIsPreparing(_stage);
}
- (void)didMoveToWindow
@@ -396,7 +396,7 @@ RCT_EXPORT_METHOD(show)
? UIAlertControllerStyleActionSheet
: UIAlertControllerStyleAlert;
NSString *devMenuType = self.bridge ? @"Bridge" : @"Bridgeless";
NSString *devMenuType = [self.bridge isKindOfClass:RCTBridge.class] ? @"Bridge" : @"Bridgeless";
NSString *devMenuTitle = [NSString stringWithFormat:@"React Native Dev Menu (%@)", devMenuType];
_actionSheet = [UIAlertController alertControllerWithTitle:devMenuTitle message:description preferredStyle:style];
@@ -10,6 +10,7 @@
#import <objc/runtime.h>
#import <FBReactNativeSpec/FBReactNativeSpec.h>
#import <React/RCTBridge+Inspector.h>
#import <React/RCTBridge+Private.h>
#import <React/RCTBridgeModule.h>
#import <React/RCTConstants.h>
@@ -157,6 +158,11 @@ RCT_EXPORT_MODULE()
return NO;
}
- (BOOL)_isBridgeMode
{
return [self.bridge isKindOfClass:[RCTBridge class]];
}
- (instancetype)initWithDataSource:(id<RCTDevSettingsDataSource>)dataSource
{
if (self = [super init]) {
@@ -177,7 +183,7 @@ RCT_EXPORT_MODULE()
- (void)initialize
{
#if RCT_DEV_SETTINGS_ENABLE_PACKAGER_CONNECTION
if (self.bridge) {
if ([self _isBridgeMode]) {
RCTBridge *__weak weakBridge = self.bridge;
_bridgeExecutorOverrideToken = [[RCTPackagerConnection sharedPackagerConnection]
addNotificationHandler:^(id params) {
@@ -208,7 +214,7 @@ RCT_EXPORT_MODULE()
#endif
#if RCT_ENABLE_INSPECTOR
if (self.bridge) {
if ([self _isBridgeMode]) {
// We need this dispatch to the main thread because the bridge is not yet
// finished with its initialisation. By the time it relinquishes control of
// the main thread, this operation can be performed.
@@ -249,7 +255,7 @@ RCT_EXPORT_MODULE()
{
[super invalidate];
#if RCT_DEV_SETTINGS_ENABLE_PACKAGER_CONNECTION
if (self.bridge) {
if ([self _isBridgeMode]) {
[[RCTPackagerConnection sharedPackagerConnection] removeHandler:_bridgeExecutorOverrideToken];
}
@@ -280,7 +286,7 @@ RCT_EXPORT_MODULE()
- (BOOL)isDeviceDebuggingAvailable
{
#if RCT_ENABLE_INSPECTOR
if (self.bridge) {
if ([self _isBridgeMode]) {
return self.bridge.isInspectable;
} else {
return self.isInspectable;
@@ -54,11 +54,6 @@ RCT_EXPORT_MODULE()
_currentInterfaceOrientation = [RCTSharedApplication() statusBarOrientation];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(interfaceOrientationDidChange)
name:UIApplicationDidChangeStatusBarOrientationNotification
object:nil];
_currentInterfaceDimensions = [self _exportedDimensions];
[[NSNotificationCenter defaultCenter] addObserver:self
@@ -75,6 +70,10 @@ RCT_EXPORT_MODULE()
selector:@selector(interfaceFrameDidChange)
name:RCTWindowFrameDidChangeNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(interfaceFrameDidChange)
name:UIDeviceOrientationDidChangeNotification
object:nil];
// TODO T175901725 - Registering the RCTDeviceInfo module to the notification is a short-term fix to unblock 0.73
// The actual behavior should be that the module is properly registered in the TurboModule/Bridge infrastructure
@@ -89,6 +88,9 @@ RCT_EXPORT_MODULE()
- (void)invalidate
{
if (_invalidated) {
return;
}
_invalidated = YES;
[self _cleanupObservers];
}
@@ -99,20 +101,15 @@ RCT_EXPORT_MODULE()
name:RCTAccessibilityManagerDidUpdateMultiplierNotification
object:[_moduleRegistry moduleForName:"AccessibilityManager"]];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIApplicationDidChangeStatusBarOrientationNotification
object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:RCTUserInterfaceStyleDidChangeNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:RCTWindowFrameDidChangeNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(invalidate)
name:RCTBridgeWillInvalidateModulesNotification
object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:RCTBridgeWillInvalidateModulesNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil];
}
static BOOL RCTIsIPhoneNotched()
@@ -274,7 +274,13 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : (NSCoder *)aDecoder)
- (void)reload
{
[_actionDelegate reloadFromRedBoxController:self];
if (_actionDelegate != nil) {
[_actionDelegate reloadFromRedBoxController:self];
} else {
// In bridgeless mode `RCTRedBox` gets deallocated, we need to notify listeners anyway.
RCTTriggerReloadCommandListeners(@"Redbox");
[self dismiss];
}
}
- (void)showExtraDataViewController
@@ -9,6 +9,7 @@
#include <future>
#import <React/RCTAssert.h>
#import <React/RCTBridge+Inspector.h>
#import <React/RCTBridge+Private.h>
#import <React/RCTBridge.h>
#import <React/RCTBridgeMethod.h>
@@ -257,6 +257,11 @@ using namespace facebook::react;
self.layer.doubleSided = newViewProps.backfaceVisibility == BackfaceVisibility::Visible;
}
// `cursor`
if (oldViewProps.cursor != newViewProps.cursor) {
needsInvalidateLayer = YES;
}
// `shouldRasterize`
if (oldViewProps.shouldRasterize != newViewProps.shouldRasterize) {
self.layer.shouldRasterize = newViewProps.shouldRasterize;
@@ -592,6 +597,33 @@ static RCTBorderStyle RCTBorderStyleFromBorderStyle(BorderStyle borderStyle)
layer.shadowPath = nil;
}
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 170000 /* __IPHONE_17_0 */
// Stage 1.5. Cursor / Hover Effects
if (@available(iOS 17.0, *)) {
UIHoverStyle *hoverStyle = nil;
if (_props->cursor == Cursor::Pointer) {
const RCTCornerInsets cornerInsets =
RCTGetCornerInsets(RCTCornerRadiiFromBorderRadii(borderMetrics.borderRadii), UIEdgeInsetsZero);
#if TARGET_OS_IOS
// Due to an Apple bug, it seems on iOS, UIShapes made with `[UIShape shapeWithBezierPath:]`
// evaluate their shape on the superviews' coordinate space. This leads to the hover shape
// rendering incorrectly on iOS, iOS apps in compatibility mode on visionOS, but not on visionOS.
// To work around this, for iOS, we can calculate the border path based on `view.frame` (the
// superview's coordinate space) instead of view.bounds.
CGPathRef borderPath = RCTPathCreateWithRoundedRect(self.frame, cornerInsets, NULL);
#else // TARGET_OS_VISION
CGPathRef borderPath = RCTPathCreateWithRoundedRect(self.bounds, cornerInsets, NULL);
#endif
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithCGPath:borderPath];
CGPathRelease(borderPath);
UIShape *shape = [UIShape shapeWithBezierPath:bezierPath];
hoverStyle = [UIHoverStyle styleWithEffect:[UIHoverAutomaticEffect effect] shape:shape];
}
[self setHoverStyle:hoverStyle];
}
#endif
// Stage 2. Border Rendering
const bool useCoreAnimationBorderRendering =
borderMetrics.borderColors.isUniform() && borderMetrics.borderWidths.isUniform() &&
@@ -1680,6 +1680,16 @@ static UIView *_jsResponder;
return self;
}
- (NSUInteger)count
{
return self->_registry.count;
}
- (NSEnumerator *)keyEnumerator
{
return self->_registry.keyEnumerator;
}
- (id)objectForKey:(id)key
{
if (![key isKindOfClass:[NSNumber class]]) {
@@ -0,0 +1,13 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <Foundation/Foundation.h>
typedef NS_ENUM(NSInteger, RCTCursor) {
RCTCursorAuto,
RCTCursorPointer,
};
@@ -10,6 +10,7 @@
#import <React/RCTBorderCurve.h>
#import <React/RCTBorderStyle.h>
#import <React/RCTComponent.h>
#import <React/RCTCursor.h>
#import <React/RCTPointerEvents.h>
extern const UIAccessibilityTraits SwitchAccessibilityTrait;
@@ -120,6 +121,8 @@ extern const UIAccessibilityTraits SwitchAccessibilityTrait;
*/
@property (nonatomic, assign) UIEdgeInsets hitTestEdgeInsets;
@property (nonatomic, assign) RCTCursor cursor;
/**
* (Experimental and unused for Paper) Pointer event handlers.
*/
@@ -136,6 +136,7 @@ static NSString *RCTRecursiveAccessibilityLabel(UIView *view)
_borderCurve = RCTBorderCurveCircular;
_borderStyle = RCTBorderStyleSolid;
_hitTestEdgeInsets = UIEdgeInsetsZero;
_cursor = RCTCursorAuto;
_backgroundColor = super.backgroundColor;
}
@@ -796,6 +797,8 @@ static CGFloat RCTDefaultIfNegativeTo(CGFloat defaultValue, CGFloat x)
RCTUpdateShadowPathForView(self);
RCTUpdateHoverStyleForView(self);
const RCTCornerRadii cornerRadii = [self cornerRadii];
const UIEdgeInsets borderInsets = [self bordersAsInsets];
const RCTBorderColors borderColors = [self borderColorsWithTraitCollection:self.traitCollection];
@@ -891,6 +894,33 @@ static void RCTUpdateShadowPathForView(RCTView *view)
}
}
static void RCTUpdateHoverStyleForView(RCTView *view)
{
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 170000 /* __IPHONE_17_0 */
if (@available(iOS 17.0, *)) {
UIHoverStyle *hoverStyle = nil;
if ([view cursor] == RCTCursorPointer) {
const RCTCornerRadii cornerRadii = [view cornerRadii];
const RCTCornerInsets cornerInsets = RCTGetCornerInsets(cornerRadii, UIEdgeInsetsZero);
#if TARGET_OS_IOS
// Due to an Apple bug, it seems on iOS, `[UIShape shapeWithBezierPath:]` needs to
// be calculated in the superviews' coordinate space (view.frame). This is not true
// on other platforms like visionOS.
CGPathRef borderPath = RCTPathCreateWithRoundedRect(view.frame, cornerInsets, NULL);
#else // TARGET_OS_VISION
CGPathRef borderPath = RCTPathCreateWithRoundedRect(view.bounds, cornerInsets, NULL);
#endif
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithCGPath:borderPath];
CGPathRelease(borderPath);
UIShape *shape = [UIShape shapeWithBezierPath:bezierPath];
hoverStyle = [UIHoverStyle styleWithEffect:[UIHoverHighlightEffect effect] shape:shape];
}
[view setHoverStyle:hoverStyle];
}
#endif
}
- (void)updateClippingForLayer:(CALayer *)layer
{
CALayer *mask = nil;

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