Compare commits

...
Author SHA1 Message Date
Nicola Corti 31b399f4a8 Use absolute path when compiling appmodules.so sources 2024-11-04 17:24:32 +00:00
Mateo Guzmán dc9db01665 feat(image): [android] adding only-if-cached cache control option (#47348)
Summary:
Following up from https://github.com/facebook/react-native/issues/47182, as basic caching control is already in place in Android, it can be extended to include the `only-if-cached` option.

We check whether the image is in the cache. If it is, we proceed to load it. Otherwise, we do nothing.

## Changelog:

[ANDROID] [ADDED] - Image `only-if-cached` cache control option

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

Test Plan:
In the `rn-tester`, I added a third example for Android where the third image will never be loaded as the cache policy is set to `only-if-cached` and the image has not been loaded before.

<details>
<summary>Video demonstrating how the `only-if-cached` options behaves</summary>

https://github.com/user-attachments/assets/45669e81-5414-4103-8931-138bffa81447

</details>

<details>
<summary>Error from image not found in cache example</summary>

<img width="807" alt="image" src="https://github.com/user-attachments/assets/6b79d811-1809-437c-b2fe-c86d3da7c58d">

</details>

Reviewed By: rshest

Differential Revision: D65384639

Pulled By: Abbondanzo

fbshipit-source-id: f4a72694f45eb3d7097c350f4a4008a0abf0a1ab
2024-11-04 08:37:59 -08:00
Samuel Susla 91df5a4a0f surface setup issues in EventBeat and Scheduler (#47355)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47355

changelog: [internal]

Reviewed By: rshest

Differential Revision: D65333695

fbshipit-source-id: 854dbc3ae52db0093961cbeb81f1f96934eca40d
2024-11-04 08:15:12 -08:00
Parsa Nasirimehr 4da586ead9 chore(Android): Migrate DebugOverlayTag and ReactDebugOverlayTag to Kotlin (#47362)
Summary:
I believe these two were the last items under `com.facebook.debug` that were still Java.

I thought about making DebugOverlayTag a Data class, but i will leave it up to the reviewer to decide if it would be needed or not.

## Changelog:

[INTERNAL] [FIXED] - Migrate DebugOverlayTag and ReactDebugOverlayTag to Kotlin

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

Test Plan:
`./gradlew test`:
<img width="1265" alt="Screenshot 2024-11-02 at 18 45 45" src="https://github.com/user-attachments/assets/405e77bc-1287-4329-b230-9f46eadb3580">

Reviewed By: javache

Differential Revision: D65417984

Pulled By: cortinico

fbshipit-source-id: e39224e40bde281498fdbed1609a03b264967396
2024-11-04 06:57:47 -08:00
Marc Rousavy de3c1ee097 feat: Trigger Java GC on reload (#43813)
Summary:
While we (Margelo) were developing a new C++ 3D library for react-native, we noticed that Java often keeps a lot of dead instances in memory, making it hard to debug memory allocations (or actually _de_-allocations), especially since we use `jsi::HostObject` and `jni::HybridClass` in conjunction. Having two garbage-collected languages retain an object is a bit tricky, and making sure that we aren't doing anything wrong with our allocations and references was not easy - but manually calling `System.gc()` on app reloads helped us see that much better.

Before this, we needed to wait multiple minutes until some Java objects are actually freed from the GC. Our use-case was a `facebook::jni::HybridClass`, which was held strong in a `facebook::jsi::HostObject` (so again, two GC'd languages).

There _should_ be no change in behaviour with this PR, just two things to note:

1. Memory might be free'd more eagerly in full reloads (dev builds) - makes sense for library developers, especially when working with C++ modules.
2. `System.gc()` only _suggests_ garbage collection, it does not _force_ it. But when it runs, it might impact performance, although we haven't noticed any impact of that at all. The garbage collector runs anyways - better during a reload than later when exceuting the app normally.

## 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] [ADDED] - Trigger Java GC on app reload

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

Test Plan:
Open an app, create a Java module that holds a few objects, add `finalize()` methods to those objects and log their deletion.

Reload the app to see the logs, compare before vs after.

Reviewed By: rshest

Differential Revision: D65418163

Pulled By: javache

fbshipit-source-id: 7597548790577dfc542b57f59578ae48df543b14
2024-11-04 06:53:07 -08:00
Nicola Corti e1a1cead43 AGP to 8.7.2 (#47369)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47369

This just bumps the AGP patch version to the latest stable.

Changelog:
[Android] [Changed] - AGP to 8.7.2

Reviewed By: tdn120

Differential Revision: D65336357

fbshipit-source-id: 9a7464304ba29f6b752f41b252bde9cb0eca0e9a
2024-11-04 05:57:22 -08:00
Peter Abbondanzo 7211119d23 Add cache control check to multisource (#47357)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47357

`MultiSourceHelper` should not yield an `ImageSource` that has its cache control policy set to `RELOAD`. This change skips such sources when computing the bestCached item (but not best item)

Changelog: [Internal]

Reviewed By: NickGerleman

Differential Revision: D65337414

fbshipit-source-id: bdd0d55f4a65128b141a1c7a132dba085232fa11
2024-11-01 15:26:58 -07:00
Chi Tsai 6ab7b70241 Add utf16 method to JSI (#47356)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47356

Add utf16 method to JSI. This change will add the default implementation
for all VMs by calling UTF8 and manually convert it to UTF16. A later
change will be added for Hermes to use internal VM information to get
the UTF16 string.

Changelog: [Internal]

Reviewed By: neildhar

Differential Revision: D64918244

fbshipit-source-id: 6fc0c44fc397c2f8bb40a4262596b178ee4f1f29
2024-11-01 13:52:46 -07:00
zhongwuzw af384a914a FIxes CornerRadiiAreEqualAndSymmetrical error when check topLeftHorizontal == topLeftVertical (#47338)
Summary:
FIxes CornerRadiiAreEqualAndSymmetrical error when check topLeftHorizontal == topLeftVertical cc. jorge-cab

## Changelog:

[IOS] [FIXED] - FIxes CornerRadiiAreEqualAndSymmetrical error when check topLeftHorizontal == topLeftVertical

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

Test Plan: N/A

Reviewed By: jorge-cab

Differential Revision: D65281958

Pulled By: cipolleschi

fbshipit-source-id: f79fced7282bf75201d9dc99c82eeaddade0d314
2024-11-01 08:12:29 -07:00
Mateo Guzmán 566d30f88a fix(rn-tester): playground description not visible in dark mode (#47346)
Summary:
The informational description in the `RNTesterPlayground` is not visible in dark mode. To address this, the `RNTesterText`, which takes into account the theme, is used.

## Changelog:

[INTERNAL] [FIXED] -  `RNTesterPlayground` description not visible in dark mode

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

Test Plan:
| Before  | After |
  | ---------- | ---------- |
  | ![Screenshot_1730414376](https://github.com/user-attachments/assets/a42e1a99-de61-41b5-b677-ea3e2b4956fc) | ![Screenshot_1730414393](https://github.com/user-attachments/assets/885ed334-8277-4ba8-a033-477b9afef7b6) |

Reviewed By: cortinico

Differential Revision: D65319138

Pulled By: Abbondanzo

fbshipit-source-id: ff541be9705fb799cc4aa3624a9e2966a76a0f8d
2024-11-01 07:36:05 -07:00
Alex Hunt 4afc47a588 Revert to @babel/eslint-parser in eslint-config (#47333)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47333

Motivated by https://github.com/facebook/hermes/issues/1549. This was originally changed in https://github.com/facebook/react-native/pull/46696, as our internal Flow support had diverged from `babel/eslint-parser` (https://github.com/facebook/react-native/issues/46601).

We effectively have three flavours of JavaScript in support:
- Flow@latest for the `react-native` package, shipped as source — uses `hermes-parser`.
- TypeScript for product code (community template, Expo) — uses `babel/plugin-syntax-typescript`.
- Plain JavaScript or Flow in product code, *which may be extended with additional user Babel plugins and needs lenient parsing* — uses `babel/plugin-syntax-flow` via `babel/eslint-parser` (**this change**).

I'd love to simplify this 😅.

Switching to `hermes-eslint` for the RN monorepo codebase (D63541483) is unchanged.

Changelog: [Internal]

Reviewed By: robhogan, cipolleschi

Differential Revision: D65272156

fbshipit-source-id: 3a2bbe3fcf8ed6057f6d994a0be4985e6bf46fa9
2024-11-01 05:31:37 -07:00
Alan Lee 2cd48ef351 fix Modal content being cut off when Android Activity is edge-to-edge (#47339)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47339

Fixing issue raised in https://github.com/facebook/react-native/issues/47307

This is a follow up from D62286026.
It appears there was a line that went missing while trying to refactor the code.

`fitsSystemWindows = true` is needeod for < API 30 to avoid content rendering under the system bars when Modal is shown with Activity that is edge-to-edge.

Changelog:
[Android][Fixed] Fix Regression - Modal content rendering below system bar on < API 30 when activity is edge-to-edge

Reviewed By: cortinico

Differential Revision: D65280014

fbshipit-source-id: 616ff739be55635f1295ef3bf8b997a27ef769ae
2024-11-01 01:27:40 -07:00
Alan Lee 65cdd5b82c Enable 16KB page size binaries for RN libraries + hermes (#47042)
Summary:
X-link: https://github.com/facebook/hermes/pull/1557

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

Add native build flags to support 16KB page size

- https://developer.android.com/guide/practices/page-sizes#compile-r27-higher

Changelog:
[Android][Added] add cmake arguments to support 16KB page size for native libraries

Reviewed By: cortinico

Differential Revision: D64446876

fbshipit-source-id: 5c6b7874a8837c7ebc9b3e9267ce11fb152bf535
2024-10-31 18:45:31 -07:00
Samuel Susla 66a2f1d312 Back out "delete redundant EventEmitter::dispatchEvent overload" (#47347)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47347

changelog: [internal]

Original commit changeset: cffdc3ef0424

Original Phabricator Diff: D65040505

Reviewed By: lunaleaps

Differential Revision: D65305763

fbshipit-source-id: 4c9e4b4acd9c5f9530af428402b106272a4e0054
2024-10-31 18:42:07 -07:00
Nolan O'Brien 79d55542aa Move FBHashKit to LayerZero/METAHash (#47343)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47343

Moving `FBHashKit` to *LayerZero* as `METAHash`

## Changelog

[Internal][Change] Move `FBXXHashUtils`

Reviewed By: adamjernst

Differential Revision: D65256846

fbshipit-source-id: 6e24a78925367e83e94e7c67a235cda924edd28e
2024-10-31 18:01:57 -07:00
Nolan O'Brien f8fc90e754 Modernize in preparation for move to Layer Zero (#47342)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47342

There are things we can do to modernize `FBHashKit` to make it ready for prime time, aka Layer Zero.

  * Consolidate down to a singular `meta_hash(...)` generic macro (supports all primitives for hashing)
  * Eliminate the unnecessary C++
  * Deprecate legacy FB APIs
  * Make logic (and interfaces) explicit for 32 vs 64 bit inputs and 32 vs 64 bit outputs
  * Introduce robust unit tests
  * Have unit tests actually testable for 32-bit hashes

## Changelog

[Internal][Change] Prep to move `FBXXHashUtils`

Reviewed By: cipolleschi

Differential Revision: D65245787

fbshipit-source-id: 311404068fd9df2a77d1ae4850b8a785466e73f0
2024-10-31 18:01:57 -07:00
Parsa Nasirimehr ec4ead59e1 fix(iOS): small test fix for RCTViewTests (#47314)
Summary:
Depracated usage of scrollInsets + an unused param.

## Changelog:

[INTERNAL] [FIXED] - Switch to verticalScrollIndicatorInsets and mark unused value as __unused in test file

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

Test Plan:
Running the specific test itself, it passes:
<img width="1092" alt="Screenshot 2024-10-30 at 18 02 08" src="https://github.com/user-attachments/assets/e3ed27c6-9f00-4777-a72c-92f0da93a79f">

Reviewed By: NickGerleman

Differential Revision: D65231365

Pulled By: philIip

fbshipit-source-id: eed795ad65bd837fb9f38175081d961245ff3932
2024-10-31 16:24:41 -07:00
Jakub Piasecki fd273f83e0 Add RNTester examples for display: contents (#47201)
Summary:
Adds a page dedicated to `display: contents` to RNTester APIs section. Those can be used to verify that it's working correctly visually.

Needs https://github.com/facebook/react-native/pull/47194

## Changelog:

[INTERNAL] [ADDED] - Added `display: contents` examples to RNTester

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

Test Plan:
Row styles are ignored in new arch and TextInputs as leaf are hidden

https://www.internalfb.com/compare-screenshots-from-diff/D65248256

Reviewed By: javache

Differential Revision: D65248256

Pulled By: NickGerleman

fbshipit-source-id: 90410e1380e4cdb22cb4cac5c8c21e08a088ce69
2024-10-31 16:12:46 -07:00
Nicola Corti ecd138e267 Enable warningAsErrors for hermes-engine (#47320)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47320

I've solved all the warnings on ReactAndroid/hermes-engine.
This enables warningsAsErrors for that part of the codebase so we can make sure
no further warnings get introduced.

Changelog:
[Internal] [Changed] - Enable warningAsErrors for hermes-engine

Reviewed By: NickGerleman

Differential Revision: D65243753

fbshipit-source-id: 17c22d1a7a32d2c684d7f236f7554f6e26469e99
2024-10-31 15:05:12 -07:00
Sam Zhou b91a449e7f Cleanup problematic React.ElementRef (#47340)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47340

This diff cleans up some problematic `React.ElementRef<T>` when T is generic type.

Changelog: [Internal]

Reviewed By: alexmckenley

Differential Revision: D65280467

fbshipit-source-id: 71172b16320a10cbc7a8b46dae5d3dd0eb00ba0c
2024-10-31 13:30:17 -07:00
Pieter De Baets 6ba7cb3102 Fix potential race in FabricMountingManager (#47337)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47337

We call `onSurfaceStart` after calling `surfaceHandler.start()`. In theory it's possible for the React surface to start generating commits before we've informed the mounting manager of the surface having started, which could cause us to not accurately track views allocated for that surface so far.

Changelog: [Android][Fixed] Addressed race condition in surface start.

Reviewed By: rshest

Differential Revision: D65269674

fbshipit-source-id: 2927220bc17e61125dabcdd75f5325a0ca77e60b
2024-10-31 12:33:13 -07:00
Mateo Guzmán e5dd7d68bf feat(image): enabling basic cache control for android (#47182)
Summary:
Fixes https://github.com/facebook/react-native/issues/12606

Previously, `Image` cache control options were not functional on Android, even though they were being passed to the native component via the `source` prop. This PR addresses that by implementing logic to manage cache behaviour on Android.

When the `reload` option is explicitly set, the image is now evicted from both memory and disk caches before a new request is made. This ensures the image is always fetched from the source, aligning the caching behaviour between Android and iOS for the `default` and `reload` options.

## Changelog:

[ANDROID][ADDED] - Enabling basic `Image` cache control for Android

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

Test Plan:
Added a new example to the `rn-tester`, where we can notice that the image on the right is reloaded if rendered or re-rendered as the cache policy is set to `reload`. The image on the left has the cache policy set to `default` and won't be re-rendered as the image is already in the cache.  See the video below:

https://github.com/user-attachments/assets/88bc1d2d-0239-4deb-bcde-fe0ce521ff4d

Also tested on both old and new architecture.

Reviewed By: NickGerleman

Differential Revision: D64915440

Pulled By: Abbondanzo

fbshipit-source-id: 32e1c55dd20bf96ab0f69ef900d821c3c2552ef7
2024-10-31 09:07:40 -07:00
Samuel Susla a12036f7be delete redundant EventEmitter::dispatchEvent overload (#47231)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47231

changelog: [internal]

`EventEmitter::dispatchEvent` and `EventEmitter::dispatchUniqueEvent` that were accepting shared_ptr are not needed. Their functionality is covered by other methods. Let's get rid of them to keep the API of EventEmitter slim.

Reviewed By: rubennorte

Differential Revision: D65040505

fbshipit-source-id: cffdc3ef042418178c5e2e5714779dfd0b61455e
2024-10-31 08:15:21 -07:00
Pieter De Baets 3e46cb384c Downgrade fatal error in FabricMountingManager (#47329)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47329

Downgrading from fatal (introduced in D63148523). It's not yet clear why this is firing, and may point at deeper underlying issues, as the re-ordering we do in `disableMountItemReorderingAndroid` only occurs at a later point in `FabricMountingManager`.

Changelog: [Internal]

Reviewed By: sammy-SC

Differential Revision: D65267936

fbshipit-source-id: cb32b149a77c9e5a3ac6350baaeae9c7215df01b
2024-10-31 06:47:13 -07:00
HyunWoo Lee 667ba76aef Click basic button & scroll down until item 600 is visible (#46804)
Summary:
This pr is part of issue https://github.com/facebook/react-native/issues/46757 solving a task - [ME2E0008] [ME2E0009]

- Set up a test
  - Starts the app
  - Scrolls until flatlist is visilbe and clicks on flatlist
  - Click basic button
  - Scroll down until item 600 is visible

## Changelog:

[Internal] [Added] - Add e2e-test logic that click button & scroll down until specific item is visible

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

Test Plan:
### Test Locally

- iOS

```bash
yarn install
cd packages/rn-tester
yarn e2e-build-ios
```

- Android

```bash
yarn install
cd packages/rn-tester
yarn e2e-build-android
```

### Start Maestro

- iOS

```bash
 cd packages/rn-tester
 yarn e2e-test-ios
```

- Android

```
cd packages/rn-tester
yarn e2e-test-android
```

### Test in CI

To test in CI, just add a comment on your PR with the text:

```
/test-e2e
```

Reviewed By: cortinico

Differential Revision: D63829274

Pulled By: cipolleschi

fbshipit-source-id: f7b4342ed353a48123f87dcfd8d503009f65637c
2024-10-31 04:33:13 -07:00
hexboy 9a3958a619 fix(Android, iOS): Fix AnsiHighlight Style in RTL Layout (#47230)
Summary:
This pull request fixes a style bug in the AnsiHighlight component when the application is in Right-To-Left (RTL) mode. The adjustments ensure that text highlighting is visually consistent and functions properly across all layout modes.

### Before
| Android RTL | iOS RTL | Android LTR | iOS LTR |
|----------|----------|----------|----------|
|  ![Before-RTL-Android](https://github.com/user-attachments/assets/059e30e7-f6da-4a07-9c91-08d952c6a4b6) | ![Before-RTL-iOS](https://github.com/user-attachments/assets/a325c838-1510-4415-bd1f-c419ce75e7e2) | ![Before-LTR-Android](https://github.com/user-attachments/assets/26494fb1-71dd-4fae-a75c-381eead211de)  | ![Before-LTR-iOS](https://github.com/user-attachments/assets/72bba2d8-f70f-4e16-b771-4af995370d26) |

### After
| Android RTL | iOS RTL | Android LTR | iOS LTR |
|----------|----------|----------|----------|
| ![After-RTL-Android](https://github.com/user-attachments/assets/d2f674c2-7aec-454f-903a-33fcd3e93240) | ![After-RTL-iOS](https://github.com/user-attachments/assets/e3735e79-7323-48e8-8213-f0871bec0ca5) | ![After-LTR-Android](https://github.com/user-attachments/assets/18c80754-8743-4282-8f95-1e9772d51a36) | ![After-LTR-iOS](https://github.com/user-attachments/assets/068f4bd8-df4e-420b-8949-c20dff9c2bc8) |

## Changelog:
[GENERAL] [Fixed] - AnsiHighlight style in RTL layout

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

Pick one each for the category and type tags:

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

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

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

Test Plan:
To test the changes, open LogBox while the app is in RTL mode. The modifications ensure that any error messages display correctly. I have verified that the changes function properly in both LTR and RTL modes, and all existing functionality remains unaffected.

This is an example component to throw an error to show LogBox.

```tsx
import React from 'react';
import {Alert, Button, I18nManager, StyleSheet, Text, View} from 'react-native';

function SampleError() {
  return (
    <View>
      <Button
        title="Change to RTL"
        onPress={() => {
          I18nManager.allowRTL(true);
          I18nManager.forceRTL(true);
          Alert.alert('Restart app to apply changes');
        }}
      />
      <Button
        title="Change to LTR"
        onPress={() => {
          I18nManager.allowRTL(false);
          I18nManager.forceRTL(false);
          Alert.alert('Restart app to apply changes');
        }}
      />

      <Text style={styles.text}>
        isRTL: {I18nManager.isRTL ? 'true' : 'false'}
      </Text>

      <Button
        title="Show Error"
        onPress={() => {
          console.error('sample خطا');
        }}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  text: {
    fontSize: 24,
    textAlign: 'center',
    paddingVertical: 20,
  },
});

export default SampleError;
```

Reviewed By: sammy-SC

Differential Revision: D65145991

Pulled By: NickGerleman

fbshipit-source-id: cbca106813e587ed223be48b75ee5279072c2da0
2024-10-31 01:32:39 -07:00
Phillip Pan 4d90f84869 clean up unused callsites to contextContainer->at (#47322)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47322

Changelog: [Internal]

these callsites were causing crashes in new bridgeless integrations, it appears they are not used, so cleaning up. after this, we can remove all callsites that insert ReactNativeConfig to the contextContainer.

Reviewed By: javache

Differential Revision: D65191733

fbshipit-source-id: 94e694ef27249773c2a39bd77f316f8f5cc2b1fb
2024-10-31 00:56:21 -07:00
Phillip Pan 3a68f14ac2 cleanup enabled_automatic_interop_android (#47321)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47321

Changelog: [Internal]

this seems to be the last callsite where we read the ReactNativeConfig from the contextContainer. i don't think this killswitch should block cleanup of the ReactNativeConfig, so maybe we can just remove this?

Reviewed By: cortinico

Differential Revision: D65192744

fbshipit-source-id: d8b595edb6fecce05e67abc257d98805daa16a9a
2024-10-31 00:56:21 -07:00
Nolan O'Brien b98846c2e3 Fix up designated initializers 8/x (#47316)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47316

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

In preparation of enabling `-Wobjc-designated-initializers` error

## Changelog:

[iOS][Fixed] - Fix numerous class interfaces having incorrect designated initializer patterns

Reviewed By: caodoan

Differential Revision: D65180118

fbshipit-source-id: 6f977816ede0397225ec681a5357241c28e83f6c
2024-10-30 21:08:32 -07:00
Nolan O'Brien 13b93cfdda Remove implicit "start", then clean up callsites (#47313)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47313

We're going to fix up a bunch of designated initializers.  `RCTSurfaceHostingProxyRootView` is particularly problematic because different initializers will do different things even though reading the code it looks like they should be equivalent.  Remove the encapsulated "start" to the provided "surface", and require it to be explicit at the callsite.

## Changelog:

[iOS][Changed] - `RCTSurfaceHostingProxyRootView` no longer has different behavior (whether it calls `start` on the provided *surface*) depending on which initializer is used.  Call `start` yourself on the *surface* instead.

Reviewed By: cipolleschi

Differential Revision: D65214656

fbshipit-source-id: 179d5220d4f866b4452561e1bb6e2051020c8a11
2024-10-30 21:08:32 -07:00
Sam Zhou 3a01a0c9c5 Fix signature of VirtualizedSectionList (#47318)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47318

Changelog: [Internal]

Reviewed By: gkz

Differential Revision: D65239931

fbshipit-source-id: c09eaad8d63f6c415e5d07a4d00dd0acc636c6b9
2024-10-30 18:15:03 -07:00
Panos Vekris e3f8c63698 Deploy 0.251.1 to xplat (#47317)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47317

Changelog: [Internal]

Reviewed By: SamChou19815

Differential Revision: D65233278

fbshipit-source-id: 35057c00f9377b6492f43bb03e5f92572799a50a
2024-10-30 14:37:10 -07:00
David Vacca d79dc48abd Delete RCTConstants.RCTGetMemoryPressureUnloadLevel (#47297)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47297

In this diff I'm proposing to remove configuration for RCTConstants.RCTGetMemoryPressureUnloadLevel API in iOS

changelog: [iOS][Breaking] Delete experimental API RCTConstants.RCTGetMemoryPressureUnloadLevel

Reviewed By: rubennorte, philIip

Differential Revision: D65181556

fbshipit-source-id: c435bec6ed03562b53f1924add7b69ab517b190b
2024-10-30 13:32:04 -07:00
Samuel Susla 8bd1f3fbfa Back out "surface setup issues in EventBeat and Scheduler" (#47312)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47312

changelog: [internal]

Original commit changeset: 5e044e1e6b02

Original Phabricator Diff: D65001802

Reviewed By: rshest

Differential Revision: D65210838

fbshipit-source-id: 90d9db256374f32d2efc366fe120bf677639e67e
2024-10-30 12:06:27 -07:00
zhongwuzw 2d9933e616 automaticallyAdjustKeyboardInsets not shifting scrollview content (#46732)
Summary:
Fixes https://github.com/facebook/react-native/issues/46595 . It seems https://github.com/facebook/react-native/issues/37766 broke the `automaticallyAdjustKeyboardInsets` when input accessory view become first responder.

## Changelog:

[IOS] [FIXED] - automaticallyAdjustKeyboardInsets not shifting scrollview content

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

Test Plan: Repro please see in #https://github.com/facebook/react-native/issues/46595 .

Reviewed By: cipolleschi

Differential Revision: D65072478

Pulled By: javache

fbshipit-source-id: 7d5d7566438d4bb0e1d50074a953b18866e324d3
2024-10-30 12:01:10 -07:00
Oskar Kwaśniewski ec0dbb729d feat: introduce RCTArchConfiguratorProtocol (#47306)
Summary:
This PR introduces `RCTArchConfiguratorProtocol` for better separation of concerns inside of RCTAppDelegate.

It's also a prerequisite for https://github.com/facebook/react-native/issues/46298

Discussed with cipolleschi

## Changelog:

[IOS] [ADDED] - introduce RCTArchConfiguratorProtocol

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

Test Plan:
- CI Green
- Test if methods can be overriden

Reviewed By: realsoelynn

Differential Revision: D65212703

Pulled By: cipolleschi

fbshipit-source-id: 9850fec31c421f0c6230e7e23d7a208d823d828f
2024-10-30 11:24:19 -07:00
Nicola Corti 50e38cc9f1 Bump serve-static to 1.16.2 to fix CVE-2024-43800 (#47289)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47289

Bump serve-static to 1.16.2 to fix CVE-2024-43800

Changelog:
[General] [Changed] - Bump serve-static to 1.16.2 to fix CVE-2024-43800

Reviewed By: cipolleschi

Differential Revision: D65146027

fbshipit-source-id: 2876a78f195230cc4cdaa14b0076ecbecc1ee6e4
2024-10-30 09:08:55 -07:00
Samuel Susla a85955a446 resume image download if previously cancelled (#47302)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47302

changelog: [internal]

The original cancellation logic cancelled image request when RCTImageComponentView was recycled but the image request was never resumed.

So in case the request was cancelled and later the same shadow node representing the image view was showed, the image request was never fulfilled and it stayed blank. It entered invalid state from where it would never recover. The image would go from state: Loading -> Cancelled and Cancelled is terminal state.

This diff adds a "resume" mechanism. If image goes from Loading -> Cancelled and something subscribes to the image state, the image request will be started again.
So we can go from Loading -> Cancelled -> Loading -> Completed.
This diff also moves the resume/cancel mechanism to ImageResponseObserverCoordinator. Where we can observe if anything is observing result of the image response.

Even though this case was highly unlikely, with <Activity /> component in React Native, it may occur.

Reviewed By: lyahdav

Differential Revision: D65149804

fbshipit-source-id: d59c1793785a367bb92602f6438666fa53db4ceb
2024-10-30 06:01:03 -07:00
qy 758892a7d8 bugfix(image): add ts definition of resizeMethod attribute. (#47227)
Summary:
in the `image component`, add the ts definition with the `resizeMethod` attribute value as `none`.

## Changelog:

[Android][Fixed] - the definition of ts of resizeMethod attribute is none.

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

Test Plan: <img width="579" alt="image" src="https://github.com/user-attachments/assets/e91dc47a-22c4-4d47-a4c2-6497d47cb842">

Reviewed By: javache

Differential Revision: D65058737

Pulled By: Abbondanzo

fbshipit-source-id: a077e4e4786a72ebffaf0698217809b1e7fde226
2024-10-30 05:06:18 -07:00
Rubén Norte 1108b4d97b Clean up API of PerformanceMark and PerformanceMeasure (#47241)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47241

Changelog: [internal]

The options for the internal constructor of `PerformanceMeasure` shouldn't be optional. This just cleans that up.

Reviewed By: rshest

Differential Revision: D64480048

fbshipit-source-id: d0275276b11bd329aa2e4667646c67608d562299
2024-10-30 04:58:04 -07:00
Pieter De Baets 0dcbebd285 Fix lint failure in Github CI (#47301)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47301

Lint wasn't reported on diff / seems like our internal linter config is not aligned.

Changelog: [Internal]

Reviewed By: cortinico

Differential Revision: D65201683

fbshipit-source-id: 879e87aafff849f9247cf1d807da092fa17d0337
2024-10-30 04:57:24 -07:00
Oskar Kwaśniewski 8850736188 feat(iOS): introduce RCTUIConfiguratorProtocol (#47139)
Summary:
This PR introduces `RCTUIConfiguratorProtocol` for better separation of concerns inside of RCTAppDelegate.

It's also a prerequisite for https://github.com/facebook/react-native/issues/46298

Discussed with cipolleschi

## Changelog:

[IOS] [ADDED] - introduce RCTUIConfiguratorProtocol

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

Test Plan:
- CI Green
- Test if methods can be overriden

Reviewed By: blakef

Differential Revision: D65063839

Pulled By: cipolleschi

fbshipit-source-id: b63766e245d57f369ab94bd8047d5de9a3447b3e
2024-10-30 04:32:17 -07:00
Alex Taylor (alta) e797135247 Deploy 0.251.0 to www + fbsource (#47295)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47295

Changelog: [Internal]

Reviewed By: gkz

Differential Revision: D65176860

fbshipit-source-id: 2254fdac49a664f3a92ae0834c76d721132fddc4
2024-10-29 19:31:15 -07:00
Nick Gerleman 41265bac6b Reimplement Android lineHeight positioning/determination (#47271)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47271

Let's keep the recent goals of centering (instead of arbitrary prioritizing ascent), ala spec, and make some changes to allow overlapping interior line-boxes, and make the implementation a lot simpler, instead of the cruft it has been accumulating.

The new simple versions is implemented as the only `CustomLineHeightSpan`. This replaces the code used when `enableAndroidLineHeightCentering` is enabled (which is now the default).

Legacy path is renamed to `LegacyLineHeightSpan`, slated to be deleted if rollout goes well.

We cannot yet cause text to overflow the bounds of the underlying TextView until potentially large later work related to ReactTextView reimplementation.

There's a somewhat arbitrary choice here, when rounding, to whether we ceil ascent vs descent when pixels don't evenly split. This does result in a visual difference, and for sake of avoiding breakage of screenshots, I left the same choice as before.

Changelog:
[Android][Fixed] - Reimplement Android lineHeight positioning/determination

Reviewed By: javache

Differential Revision: D64716557

fbshipit-source-id: 5a947377df7cfee9dff4484c840939f527caf94b
2024-10-29 17:53:16 -07:00
Nick Gerleman 7cb9fa9737 Add lineHeight screenshot tests (#47270)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47270

Lets add some screenshot tests, along with one more example, and fixing some silly typos in test IDs.

Changelog: [Internal]

Reviewed By: javache

Differential Revision: D65094482

fbshipit-source-id: a5f3e06c4737158bf6419364d05668c3feb1bd5e
2024-10-29 17:53:16 -07:00
Joe Vilches 9f73edee2d Fix issue where text would truncate sometimes (#47294)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47294

TextView will set `setUseLineSpacingFromFallbacks` to `true` for their `StaticLayout`s while we ignore it in this case (`false` default). The docs even recommend setting it to `true`: https://developer.android.com/reference/android/text/StaticLayout.Builder#setUseLineSpacingFromFallbacks(boolean)

We set this in the `StaticLayout` builder below, but not up here so lets do that.

Changelog: [Internal]

Reviewed By: NickGerleman

Differential Revision: D65171352

fbshipit-source-id: aa7fd116898c6af9378d71c5c570c790e6ab415f
2024-10-29 17:49:41 -07:00
Nick Gerleman bfca7cfe7a Fix legacy arch RTL horizontal ScrollView regression (#47282)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47282

D63318754 fixed a class of issues with RTL horizontal scrollviews by moving logic from native Android view layer to Fabric ShadowNode layer.

I realized quite a bit later this is problematic for legacy arch, since it now never runs RTL translation code, and all our RTL screenshot tests are against new arch.

It's tricky to port Fabric ShadowNode related code to Paper since its shadownodes are more coupled to Yoga nodes, and the existing solution for contextual layout direction didn't quite work, so I went with the original logic we had for this, where we use global layout direction to determine whether to offset, and disable removeClippedSubviews, and this is applied via onLayout. This is wrong in several ways, but not a regression compared to previous legacy arch behavior. The fully correct behavior will require new arch.

Changelog:
[Android][Fixed] - Fix legacy arch RTL horizontal ScrollView regression

Reviewed By: rshest

Differential Revision: D65139747

fbshipit-source-id: 5662c0744c3c402efe583e602b2272662b4d5476
2024-10-29 16:29:36 -07:00
Nick Gerleman 0df59d4f03 Fix RTL ScrollView position when content smaller than container (#47280)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47280

Noticed in the screenshots of https://github.com/facebook/react-native/pull/47230 that Android's logic of setting scroll content origin to zero, then right aligning scroll offset, won't correctly handle case where content is smaller than scrolling container. We can fix that by only resetting the origin when content overflows container, since we otherwise are not scrollable, and scroll adjustment will not translate.

Changelog:
[Android][Fixed] - Fix RTL ScrollView position when content smaller than container

Reviewed By: rshest

Differential Revision: D65136654

fbshipit-source-id: 2818ff6360cbfac64d7e57bdcbbe8c0a9b4bbb97
2024-10-29 16:29:36 -07:00
Eric Rozell 0d664100bb Avoid null reference exception when fetching ReactRootView in bridgeless (#47284)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47284

If the surface hasn't been set up yet, attempting to fetch the ReactRootView will throw a null reference exception. Since the result is already nullable, it's perhaps better to just return null when the surface has not yet been initialized.

## Changelog

[Android][Fixed] Avoid null reference exception in bridgeless ReactDelegate

Reviewed By: javache

Differential Revision: D65141137

fbshipit-source-id: 9b002b0520a7eeea61767cb8934e9bb8d049fc6a
2024-10-29 15:55:56 -07:00
Eric Rozell e3f03269c5 Minor typo in ReactHostImpl comment (#47290)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47290

Fixes a comment typo.

## Changelog

[General][Fixed] Fixes typo in ReactHostImpl

Reviewed By: cortinico

Differential Revision: D65149529

fbshipit-source-id: b419241f861ab28b2c4a512b27f33b94e7929b81
2024-10-29 15:18:09 -07:00
Ramanpreet Nara cc6f75bb75 earlyjs: Integrate c++ pipeline with console.error
Summary:
## Changes
If the c++ pipeline is active:

If someone calls console.error:
- The c++ pipeline will report it as a soft error

If someone reports an error:
- The c++ pipeline will log it via console.error

Changelog: [Internal]

Reviewed By: javache

Differential Revision: D64506069

fbshipit-source-id: 293cd1774f19ee03d7eb61572b7b1f03a47a4756
2024-10-29 14:24:27 -07:00
Ramanpreet Nara 5b53c07329 earlyjs: Integrate c++ pipeline with all ios apps
Summary:
Now, all ios apps will just be integrated with the c++ error reporting pipeline, with zero configuration.

Changelog: [Internal]

Reviewed By: javache, philIip

Differential Revision: D64615457

fbshipit-source-id: db9d98115238d9a42563e39a4780234a9bc3c034
2024-10-29 14:24:27 -07:00
Ramanpreet Nara eb3977eccf earlyjs: Introduce flag for always available js error handling
Summary:
This diff introduces ReactNativeFeatureFlags.useAlwaysAvailableJSErrorHandling.

Changelog: [Internal]

Reviewed By: javache

Differential Revision: D64791786

fbshipit-source-id: 81cf3ed1fc7057638d7d817f1fea5fc371b53646
2024-10-29 14:24:27 -07:00
Dawid 08e8f6adfd fix(Android) drawing additional empty line when 'textAlign' is set to 'justify' (#47122)
Summary:
Fixes https://github.com/facebook/react-native/issues/46908

The `justificationMode` is not set for multiline text without unicode characters with known width on both architectures. This caused the issue of drawing additional empty line at the end of `TextView` because Yoga thought that text takes 5 lines and falsely calculated it's height.

Currently, on the old architecture, the `justificationMode` is set only on text that is not boring (contains unicode characters) with unknown width. I am not sure why is that, so I am opening this as a draft for now as I am still checking if it doesn't break anything.

## 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] [FIXED] - fix generating empty line at the end of multiline text view when `textAlign` is set to `justify`

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

Test Plan: I've tested on both architectures on repro provided in the issue.

Reviewed By: javache

Differential Revision: D65002386

Pulled By: NickGerleman

fbshipit-source-id: 0187956c88e6eb1e637c24e82b3052cc82581a64
2024-10-29 14:22:59 -07:00
Samuel Susla dacada7750 use move semantics in TouchEventEmitter (#47232)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47232

changelog: [internal]

TouchEventEmitter APIs take ownership of TouchEvent and PointerEvent, the use of const & qualifiers is misleading and may lead it unnecessary copy.

Reviewed By: rubennorte

Differential Revision: D65040506

fbshipit-source-id: 941e2eab6a057e31066751e26387604858f03e51
2024-10-29 13:18:50 -07:00
Phillip Pan 6fc500ee99 hook up useNativeViewConfigsInBridgelessMode feature flag (#47265)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47265

Changelog: [iOS][Breaking]

This was originally landed before as part of the effort to coalesce configurations with the feature flag infra, but got reverted due to a build issue. I'm pretty sure it was just because the legacy configuration methods were not cleaned up from the header (RCTConstants.h). I fixed that here.

Reviewed By: javache

Differential Revision: D65092536

fbshipit-source-id: 5012ba54b0314c487f2ef488c2eb30a3c4133cb5
2024-10-29 12:42:26 -07:00
Hanno J. Gödecke 0fc2e954be add example for dynamic sized text input (#46976)
Summary:
This PR adds an example showcasing a TextInput whose width gets resized dynamically based on the text content width.
This example was added for this PR, which tries to address a flickering bug with dynamic sized TextInputs:

- https://github.com/facebook/react-native/pull/46973

## Changelog:

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

Pick one each for the category and type tags:

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

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

[INTERNAL] [ADDED] Added dynamic content width TextInput example

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

Test Plan:
Test in RNTester app:

https://github.com/user-attachments/assets/7571b80b-7035-47df-b840-4218ab0802b5

Reviewed By: NickGerleman

Differential Revision: D64271454

Pulled By: arushikesarwani94

fbshipit-source-id: 28fe7bd93891ffe5284340d73e9ee947654f1788
2024-10-29 12:40:09 -07:00
Abdelhafidh Belalia e8f8ee3c0f Resume frame callback on host resume (#47264)
Summary:
When the app goes into background the frame callback is ignored by setting the `mShouldStop` flag to `true` https://github.com/facebook/react-native/blob/3111473d571a8315d11753f8c6acddd2ba301f8f/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/FabricEventDispatcher.java#L174
However this flag is never reset even after the app is back on foreground. This made the `AndroidEventBeat` not ticking in as much as expected causing events not being dispatched in time. In our case the `onLayout` was not being dispatched unless we tap on screen invoking a manual tick.

## Changelog:

[ANDROID] [FIXED] - Fix Frame Callback not being called after Host Resume

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

Test Plan:
1. Add log line `__android_log_print(ANDROID_LOG_DEBUG, "s77rt", "AndroidEventBeat::tick");` in `packages/react-native/ReactAndroid/src/main/jni/react/fabric/AndroidEventBeat.cpp` (tick method)
2. Open RN-Tester
3. Verify `AndroidEventBeat::tick` is logged for every frame
4. Put app into background
5. Verify no `AndroidEventBeat::tick` is logged
6. Open app again
7. Verify `AndroidEventBeat::tick` is logged for every frame

| Before | After |
|:------:|:-----:|
|     <video src="https://github.com/user-attachments/assets/9667ed49-3a56-4c30-992f-9e6426f5d08e" />   |     <video src="https://github.com/user-attachments/assets/548ae199-d9a2-497c-bba7-b89c4d684836" />  |
|     <video src="https://github.com/user-attachments/assets/e14851aa-0609-4b36-bf1e-dfd5d2ee8512" />   |     <video src="https://github.com/user-attachments/assets/db5a9fe6-dfc1-4b3c-92b0-359b4b68ac5c" />  |

Reviewed By: NickGerleman

Differential Revision: D65136338

Pulled By: javache

fbshipit-source-id: 0a101be2a7588cbbb5a55ee4d420082f85566c1b
2024-10-29 11:53:02 -07:00
Rubén Norte e51c32d7cf Improve intersection observer errors when trying to observe nullish targets (#47291)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47291

Changelog: [internal]

Small devx improvement to distinguish problems caused by calling `IntersectionObserver.observe` with null or undefined, vs. other values not supported by the API (like legacy refs).

Differential Revision: D65150750

fbshipit-source-id: b9452ff19d35ccd0dc2d47ee2d5a0e933e0ae180
2024-10-29 11:31:30 -07:00
Alan Lee 97622a5caa RedBoxDialogSurfaceDelegate crash fix (#47249)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47249

- It is likely that Dialog is being dismissed from an invalid state causing an exception
- apply similar changes from D63712422 which is to add try/catch around and ignore the exception as we are dismissing the dialog anyway

Changelog: [Internal]

Reviewed By: javache

Differential Revision: D65066186

fbshipit-source-id: 03ebbc3fec3adf6100e36ea38b43f410d98a5297
2024-10-29 11:19:02 -07:00
Mateo Guzmán c19fd11ccf fix(examples): fixing XMLHttpRequest file download example (#47152)
Summary:
The `XMLHttpRequest` example with a single file download doesn't seem to be working anymore. The test case is quite old so it seems like something changed in between with the example URLs.

- Changing the URL for the example. Using another file from `filesamples.com` as it's already being used in the chunk file download example as well.
- Adding an `onerror` callback as it was loading infinitely when something went wrong.

## Changelog:

[INTERNAL] [FIXED] - fixing `XMLHttpRequest` file download example

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

Test Plan:
Using the `rn-tester`, see the before and after for comparison

<details>
<summary>Before and after videos</summary>

**Before**:

https://github.com/user-attachments/assets/01f89cd9-0f5e-4ddb-9ff2-c3e053be5413

**After**:

https://github.com/user-attachments/assets/59ef161c-d5ba-43e3-827e-e250cc663276

</details>

Reviewed By: cipolleschi

Differential Revision: D65126952

Pulled By: NickGerleman

fbshipit-source-id: 7a4b2187570fd85d4444bfe63ae7bc77b09af261
2024-10-29 11:18:34 -07:00
Blake Friedman 7090b790c6 Changelog for 0.76.1 (#47288)
Summary:
Changelog: [Internal]

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

Reviewed By: cipolleschi

Differential Revision: D65146569

Pulled By: blakef

fbshipit-source-id: bdc25e4bf6b1b2f7fa7723171431aea3bb490622
2024-10-29 10:44:28 -07:00
Pieter De Baets 7a265d2406 Remove unused __inspectorLog (#47276)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47276

This dates back all the way to D4021502 and is unused by any of our modern debugger tools.

Changelog: [Internal]

Reviewed By: rubennorte

Differential Revision: D65134285

fbshipit-source-id: 44d8bf2553b28558755e9a603b8ddc8f7dd79b20
2024-10-29 10:34:00 -07:00
Nicola Corti 19813642f1 Move com/facebook/react/devsupport/AndroidManifest to Internal (#47279)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47279

This file is used by BUCK only and should have not been exposed in the first place.
Fixes https://github.com/facebook/react-native/issues/47223

Changelog:
[Internal] [Changed] - Move `com/facebook/react/devsupport/AndroidManifest` to Internal

Reviewed By: NickGerleman

Differential Revision: D65136247

fbshipit-source-id: 01f1e3aed55e932e842132312166b786fd39e7ce
2024-10-29 10:25:46 -07:00
Blake Friedman f5595c716b test-e2e-local support useLastSuccessfulPipeline (#47248)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47248

This argument wasn't implemented; this change implements it.

Changelog: [Internal]

Reviewed By: cipolleschi

Differential Revision: D65066030

fbshipit-source-id: 999fb2fa89cc71f9a568843d4cf92a500ff1b4f8
2024-10-29 10:08:07 -07:00
Blake Friedman 4c0cd72208 Fix typo in template action watcher script (#47286)
Summary:
Trivial typo - static analysis would have been a good thing.

Changelog: [Internal]

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

Test Plan: eyes

Reviewed By: NickGerleman

Differential Revision: D65145600

Pulled By: blakef

fbshipit-source-id: 567ef3637441aa84651dce03f45b80068c5f4290
2024-10-29 10:06:17 -07:00
Rubén Norte 9792d5e2d1 Quick print of feature flags definitions (#47240)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47240

Changelog: [internal]

Adding a new option for the feature flags script to print the current definitions of feature flags.

```
yarn featureflags --print
```

```
┌────────────────────────────────────────────────────────────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────┬─────────┬──────────────┐
│ (index)                                                    │ Description                                                                                               │ Purpose │ Date added   │
├────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────┼─────────┼──────────────┤
│ commonTestFlag                                             │ 'Common flag for testing. Do NOT modify.'                                                                 │ '🔨'    │ undefined    │
│ commonTestFlagWithoutNativeImplementation                  │ 'Common flag for testing (without native implementation). Do NOT modify.'                                 │ '🔨'    │ undefined    │
│ enableFabricLogs                                           │ 'This feature flag enables logs for Fabric.'                                                              │ '🔨'    │ undefined    │
│ jsOnlyTestFlag                                             │ 'JS-only flag for testing. Do NOT modify.'                                                                │ '🔨'    │ undefined    │
│ traceTurboModulePromiseRejectionsOnAndroid                 │ 'Enables storing js caller stack when creating promise in native module. This is useful in case of Pr...' │ '🔨'    │ undefined    │
│ batchRenderingUpdatesInEventLoop                           │ 'When enabled, the RuntimeScheduler processing the event loop will batch all rendering updates and di...' │ '🚀'    │ undefined    │
│ disableEventLoopOnBridgeless                               │ 'The bridgeless architecture enables the event loop by default. This feature flag allows us to force ...' │ '🚀'    │ undefined    │
│ enableAccessToHostTreeInFabric                             │ 'Enables access to the host tree in Fabric using DOM-compatible APIs.'                                    │ '🚀'    │ undefined    │
│ enableBridgelessArchitecture                               │ 'Feature flag to enable the new bridgeless architecture. Note: Enabling this will force enable the fo...' │ '🚀'    │ undefined    │
│ enableFabricRenderer                                       │ 'Enables the use of the Fabric renderer in the whole app.'                                                │ '🚀'    │ undefined    │
│ enableFabricRendererExclusively                            │ 'When the app is completely migrated to Fabric, set this flag to true to disable parts of Paper infra...' │ '🚀'    │ undefined    │
│ enableLayoutAnimationsOnAndroid                            │ 'When enabled, LayoutAnimations API will animate state changes on Android.'                               │ '🚀'    │ undefined    │
│ enableLayoutAnimationsOnIOS                                │ 'When enabled, LayoutAnimations API will animate state changes on iOS.'                                   │ '🚀'    │ undefined    │
│ enableLongTaskAPI                                          │ 'Enables the reporting of long tasks through `PerformanceObserver`. Only works if the event loop is e...' │ '🚀'    │ undefined    │
│ enableMicrotasks                                           │ 'Enables the use of microtasks in Hermes (scheduling) and RuntimeScheduler (execution).'                  │ '🚀'    │ undefined    │
│ enableReportEventPaintTime                                 │ 'Report paint time inside the Event Timing API implementation (PerformanceObserver).'                     │ '🚀'    │ undefined    │
│ fuseboxEnabledDebug                                        │ 'Flag determining if the React Native DevTools (Fusebox) CDP backend should be enabled in debug build...' │ '🚀'    │ undefined    │
│ fuseboxEnabledRelease                                      │ 'Flag determining if the React Native DevTools (Fusebox) CDP backend should be enabled in release bui...' │ '🚀'    │ undefined    │
│ isLayoutAnimationEnabled                                   │ 'Function used to enable / disabled Layout Animations in React Native.'                                   │ '🚀'    │ undefined    │
│ useFabricInterop                                           │ 'Should this application enable the Fabric Interop Layer for Android? If yes, the application will be...' │ '🚀'    │ undefined    │
│ useModernRuntimeScheduler                                  │ 'When enabled, it uses the modern fork of RuntimeScheduler that allows scheduling tasks with prioriti...' │ '🚀'    │ undefined    │
│ useTurboModules                                            │ 'When enabled, NativeModules will be executed by using the TurboModule system'                            │ '🚀'    │ undefined    │
│ allowRecursiveCommitsWithSynchronousMountOnAndroid         │ 'Adds support for recursively processing commits that mount synchronously (Android only).'                │ '🧪'    │ '2024-05-30' │
│ animatedShouldDebounceQueueFlush                           │ 'Enables an experimental flush-queue debouncing in Animated.js.'                                          │ '🧪'    │ '2024-02-05' │
│ animatedShouldUseSingleOp                                  │ 'Enables an experimental mega-operation for Animated.js that replaces many calls to native with a sin...' │ '🧪'    │ '2024-02-05' │
│ completeReactInstanceCreationOnBgThreadOnAndroid           │ 'Do not wait for a main-thread dispatch to complete init to start executing work on the JS thread on ...' │ '🧪'    │ '2024-07-22' │
│ enableAlignItemsBaselineOnFabricIOS                        │ 'Kill-switch to turn off support for aling-items:baseline on Fabric iOS.'                                 │ '🧪'    │ '2024-07-10' │
│ enableAndroidLineHeightCentering                           │ 'When enabled, custom line height calculation will be centered from top to bottom.'                       │ '🧪'    │ '2024-09-11' │
│ enableAnimatedAllowlist                                    │ 'Enables Animated to skip non-allowlisted props and styles.'                                              │ '🧪'    │ '2024-09-10' │
│ enableAnimatedClearImmediateFix                            │ 'Enables an experimental to use the proper clearIntermediate instead of calling the wrong clearTimeou...' │ '🧪'    │ '2024-09-17' │
│ enableAnimatedPropsMemo                                    │ 'Enables Animated to analyze props to minimize invalidating `AnimatedProps`.'                             │ '🧪'    │ '2024-09-11' │
│ enableCleanTextInputYogaNode                               │ 'Clean yoga node when <TextInput /> does not change.'                                                     │ '🧪'    │ '2024-04-06' │
│ enableCppPropsIteratorSetter                               │ 'Enable prop iterator setter-style construction of Props in C++ (this flag is not used in Java).'         │ '🧪'    │ '2024-09-13' │
│ enableDeletionOfUnmountedViews                             │ 'Deletes views that were pre-allocated but never mounted on the screen.'                                  │ '🧪'    │ '2024-09-13' │
│ enableEagerRootViewAttachment                              │ 'Feature flag to configure eager attachment of the root view/initialisation of the JS code.'              │ '🧪'    │ '2024-07-28' │
│ enableEventEmitterRetentionDuringGesturesOnAndroid         │ 'Enables the retention of EventEmitterWrapper on Android till the touch gesture is over to fix a bug ...' │ '🧪'    │ '2024-08-08' │
│ enableGranularShadowTreeStateReconciliation                │ 'When enabled, the renderer would only fail commits when they propagate state and the last commit tha...' │ '🧪'    │ '2024-05-01' │
│ enableIOSViewClipToPaddingBox                              │ 'iOS Views will clip to their padding box vs border box'                                                  │ '🧪'    │ '2024-08-30' │
│ enableNewBackgroundAndBorderDrawables                      │ 'Use BackgroundDrawable and BorderDrawable instead of CSSBackgroundDrawable'                              │ '🧪'    │ '2024-09-24' │
│ enableOptimisedVirtualizedCells                            │ 'Removing unnecessary rerenders Virtualized cells after any rerenders of Virualized list. Works with ...' │ '🧪'    │ '2024-08-21' │
│ enablePreciseSchedulingForPremountItemsOnAndroid           │ 'Moves execution of pre-mount items to outside the choregrapher in the main thread, so we can estimat...' │ '🧪'    │ '2024-09-19' │
│ enablePropsUpdateReconciliationAndroid                     │ 'When enabled, Android will receive prop updates based on the differences between the last rendered s...' │ '🧪'    │ '2024-07-12' │
│ enableSynchronousStateUpdates                              │ 'Dispatches state updates synchronously in Fabric (e.g.: updates the scroll position in the shadow tr...' │ '🧪'    │ '2024-04-25' │
│ enableTextPreallocationOptimisation                        │ 'Text preallocation optimisation where unnecessary work is removed.'                                      │ '🧪'    │ '2024-09-12' │
│ enableUIConsistency                                        │ 'Ensures that JavaScript always has a consistent view of the state of the UI (e.g.: commits done in o...' │ '🧪'    │ '2024-04-25' │
│ enableViewRecycling                                        │ 'Enables View Recycling. When enabled, individual ViewManagers must still opt-in.'                        │ '🧪'    │ '2024-07-31' │
│ excludeYogaFromRawProps                                    │ 'When enabled, rawProps in Props will not include Yoga specific props.'                                   │ '🧪'    │ '2024-07-22' │
│ fixMappingOfEventPrioritiesBetweenFabricAndReact           │ 'Uses the default event priority instead of the discreet event priority by default when dispatching e...' │ '🧪'    │ '2024-06-18' │
│ fixMountingCoordinatorReportedPendingTransactionsOnAndroid │ 'Fixes a limitation on Android where the mounting coordinator would report there are no pending trans...' │ '🧪'    │ '2024-08-27' │
│ forceBatchingMountItemsOnAndroid                           │ 'Forces the mounting layer on Android to always batch mount items instead of dispatching them immedia...' │ '🧪'    │ '2024-04-10' │
│ initEagerTurboModulesOnNativeModulesQueueAndroid           │ 'Construct modules that requires eager init on the dedicate native modules thread'                        │ '🧪'    │ '2024-07-11' │
│ lazyAnimationCallbacks                                     │ 'Only enqueue Choreographer calls if there is an ongoing animation, instead of enqueueing every frame...' │ '🧪'    │ '2024-05-01' │
│ loadVectorDrawablesOnImages                                │ 'Adds support for loading vector drawable assets in the Image component (only on Android)'                │ '🧪'    │ '2024-07-12' │
│ scheduleAnimatedEndCallbackInMicrotask                     │ 'Changes the completion callback supplied via `Animation#start` to be scheduled in a microtask instea...' │ '🧪'    │ '2024-09-27' │
│ setAndroidLayoutDirection                                  │ 'Propagate layout direction to Android views.'                                                            │ '🧪'    │ '2024-05-17' │
│ shouldSkipStateUpdatesForLoopingAnimations                 │ 'If the animation is within Animated.loop, we do not send state updates to React.'                        │ '🧪'    │ '2024-07-25' │
│ shouldUseAnimatedObjectForTransform                        │ 'Enables use of AnimatedObject for animating transform values.'                                           │ '🧪'    │ '2024-02-05' │
│ shouldUseRemoveClippedSubviewsAsDefaultOnIOS               │ 'removeClippedSubviews prop will be used as the default in FlatList on iOS to match Android'              │ '🧪'    │ '2024-02-05' │
│ shouldUseSetNativePropsInFabric                            │ 'Enables use of setNativeProps in JS driven animations.'                                                  │ '🧪'    │ '2024-03-05' │
│ shouldUseSetNativePropsInNativeAnimationsInFabric          │ 'Enables use of setNativeProps in Native driven animations in Fabric.'                                    │ '🧪'    │ '2024-03-05' │
│ useImmediateExecutorInAndroidBridgeless                    │ 'Invoke callbacks immediately on the ReactInstance rather than going through a background thread for ...' │ '🧪'    │ '2024-06-06' │
│ useInsertionEffectsForAnimations                           │ 'Changes construction of the animation graph to `useInsertionEffect` instead of `useLayoutEffect`.'       │ '🧪'    │ '2024-09-12' │
│ useNativeViewConfigsInBridgelessMode                       │ 'When enabled, the native view configs are used in bridgeless mode.'                                      │ '🧪'    │ '2024-04-03' │
│ useOptimisedViewPreallocationOnAndroid                     │ 'Moves more of the work in view preallocation to the main thread to free up JS thread.'                   │ '🧪'    │ '2024-07-23' │
│ useOptimizedEventBatchingOnAndroid                         │ 'Uses an optimized mechanism for event batching on Android that does not need to wait for a Choreogra...' │ '🧪'    │ '2024-08-29' │
│ useRefsForTextInputState                                   │ 'Enable a variant of TextInput that moves some state to refs to avoid unnecessary re-renders'             │ '🧪'    │ '2024-07-08' │
│ useRuntimeShadowNodeReferenceUpdate                        │ 'When enabled, cloning shadow nodes within react native will update the reference held by the current...' │ '🧪'    │ '2024-06-03' │
│ useTurboModuleInterop                                      │ 'In Bridgeless mode, should legacy NativeModules use the TurboModule system?'                             │ '🧪'    │ '2024-07-28' │
└────────────────────────────────────────────────────────────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────┴─────────┴──────────────┘
Summary
┌─────────────────┬────────┐
│ (index)         │ Values │
├─────────────────┼────────┤
│ Total           │ 68     │
│ Common          │ 51     │
│ JS Only         │ 17     │
│ Operational     │ 5      │
│ Release         │ 17     │
│ Experimentation │ 46     │
└─────────────────┴────────┘
Done in 1.62s.
```

```
yarn featureflags --print --json
```

```
{"common":{"commonTestFlag":{"defaultValue":false,"metadata":{"description":"Common flag for testing. Do NOT modify.","purpose":"operational"}},"commonTestFlagWithoutNativeImplementation":{"defaultValue":false,"metadata":{"description":"Common flag for testing (without native implementation). Do NOT modify.","purpose":"operational"},"skipNativeAPI":true},"allowRecursiveCommitsWithSynchronousMountOnAndroid":{"defaultValue":false,"metadata":{"dateAdded":"2024-05-30","description":"Adds support for recursively processing commits that mount synchronously (Android only).","purpose":"experimentation"}},"batchRenderingUpdatesInEventLoop":{"defaultValue":false,"metadata":{"description":"When enabled, the RuntimeScheduler processing the event loop will batch all rendering updates and dispatch them together at the end of each iteration of the loop.","purpose":"release"},"skipNativeAPI":true},"completeReactInstanceCreationOnBgThreadOnAndroid":{"defaultValue":false,"metadata":{"dateAdded":"2024-07-22","description":"Do not wait for a main-thread dispatch to complete init to start executing work on the JS thread on Android","purpose":"experimentation"}},"disableEventLoopOnBridgeless":{"defaultValue":false,"metadata":{"description":"The bridgeless architecture enables the event loop by default. This feature flag allows us to force disabling it in specific instances.","purpose":"release"}},"enableAlignItemsBaselineOnFabricIOS":{"defaultValue":true,"metadata":{"dateAdded":"2024-07-10","description":"Kill-switch to turn off support for aling-items:baseline on Fabric iOS.","purpose":"experimentation"}},"enableAndroidLineHeightCentering":{"defaultValue":false,"metadata":{"dateAdded":"2024-09-11","description":"When enabled, custom line height calculation will be centered from top to bottom.","purpose":"experimentation"}},"enableBridgelessArchitecture":{"defaultValue":false,"metadata":{"description":"Feature flag to enable the new bridgeless architecture. Note: Enabling this will force enable the following flags: `useTurboModules` & `enableFabricRenderer.","purpose":"release"}},"enableCleanTextInputYogaNode":{"defaultValue":false,"metadata":{"dateAdded":"2024-04-06","description":"Clean yoga node when <TextInput /> does not change.","purpose":"experimentation"}},"enableCppPropsIteratorSetter":{"defaultValue":false,"metadata":{"dateAdded":"2024-09-13","description":"Enable prop iterator setter-style construction of Props in C++ (this flag is not used in Java).","purpose":"experimentation"}},"enableDeletionOfUnmountedViews":{"defaultValue":false,"metadata":{"dateAdded":"2024-09-13","description":"Deletes views that were pre-allocated but never mounted on the screen.","purpose":"experimentation"}},"enableEagerRootViewAttachment":{"defaultValue":false,"metadata":{"dateAdded":"2024-07-28","description":"Feature flag to configure eager attachment of the root view/initialisation of the JS code.","purpose":"experimentation"}},"enableEventEmitterRetentionDuringGesturesOnAndroid":{"defaultValue":false,"metadata":{"dateAdded":"2024-08-08","description":"Enables the retention of EventEmitterWrapper on Android till the touch gesture is over to fix a bug on pressable (#44610)","purpose":"experimentation"}},"enableFabricLogs":{"defaultValue":false,"metadata":{"description":"This feature flag enables logs for Fabric.","purpose":"operational"}},"enableFabricRenderer":{"defaultValue":false,"metadata":{"description":"Enables the use of the Fabric renderer in the whole app.","purpose":"release"}},"enableFabricRendererExclusively":{"defaultValue":false,"metadata":{"description":"When the app is completely migrated to Fabric, set this flag to true to disable parts of Paper infrastructure that are not needed anymore but consume memory and CPU. Specifically, UIViewOperationQueue and EventDispatcherImpl will no longer work as they will not subscribe to ReactChoreographer for updates.","purpose":"release"}},"enableGranularShadowTreeStateReconciliation":{"defaultValue":false,"metadata":{"dateAdded":"2024-05-01","description":"When enabled, the renderer would only fail commits when they propagate state and the last commit that updated state changed before committing.","purpose":"experimentation"}},"enableIOSViewClipToPaddingBox":{"defaultValue":false,"metadata":{"dateAdded":"2024-08-30","description":"iOS Views will clip to their padding box vs border box","purpose":"experimentation"}},"enableLayoutAnimationsOnAndroid":{"defaultValue":false,"metadata":{"description":"When enabled, LayoutAnimations API will animate state changes on Android.","purpose":"release"}},"enableLayoutAnimationsOnIOS":{"defaultValue":true,"metadata":{"description":"When enabled, LayoutAnimations API will animate state changes on iOS.","purpose":"release"}},"enableLongTaskAPI":{"defaultValue":false,"metadata":{"description":"Enables the reporting of long tasks through `PerformanceObserver`. Only works if the event loop is enabled.","purpose":"release"}},"enableMicrotasks":{"defaultValue":false,"metadata":{"description":"Enables the use of microtasks in Hermes (scheduling) and RuntimeScheduler (execution).","purpose":"release"},"skipNativeAPI":true},"enableNewBackgroundAndBorderDrawables":{"defaultValue":false,"metadata":{"dateAdded":"2024-09-24","description":"Use BackgroundDrawable and BorderDrawable instead of CSSBackgroundDrawable","purpose":"experimentation"}},"enablePreciseSchedulingForPremountItemsOnAndroid":{"defaultValue":false,"metadata":{"dateAdded":"2024-09-19","description":"Moves execution of pre-mount items to outside the choregrapher in the main thread, so we can estimate idle time more precisely (Android only).","purpose":"experimentation"}},"enablePropsUpdateReconciliationAndroid":{"defaultValue":false,"metadata":{"dateAdded":"2024-07-12","description":"When enabled, Android will receive prop updates based on the differences between the last rendered shadow node and the last committed shadow node.","purpose":"experimentation"}},"enableReportEventPaintTime":{"defaultValue":false,"metadata":{"description":"Report paint time inside the Event Timing API implementation (PerformanceObserver).","purpose":"release"}},"enableSynchronousStateUpdates":{"defaultValue":false,"metadata":{"dateAdded":"2024-04-25","description":"Dispatches state updates synchronously in Fabric (e.g.: updates the scroll position in the shadow tree synchronously from the main thread).","purpose":"experimentation"}},"enableTextPreallocationOptimisation":{"defaultValue":false,"metadata":{"dateAdded":"2024-09-12","description":"Text preallocation optimisation where unnecessary work is removed.","purpose":"experimentation"}},"enableUIConsistency":{"defaultValue":false,"metadata":{"dateAdded":"2024-04-25","description":"Ensures that JavaScript always has a consistent view of the state of the UI (e.g.: commits done in other threads are not immediately propagated to JS during its execution).","purpose":"experimentation"}},"enableViewRecycling":{"defaultValue":false,"metadata":{"dateAdded":"2024-07-31","description":"Enables View Recycling. When enabled, individual ViewManagers must still opt-in.","purpose":"experimentation"}},"excludeYogaFromRawProps":{"defaultValue":false,"metadata":{"dateAdded":"2024-07-22","description":"When enabled, rawProps in Props will not include Yoga specific props.","purpose":"experimentation"}},"fixMappingOfEventPrioritiesBetweenFabricAndReact":{"defaultValue":false,"metadata":{"dateAdded":"2024-06-18","description":"Uses the default event priority instead of the discreet event priority by default when dispatching events from Fabric to React.","purpose":"experimentation"}},"fixMountingCoordinatorReportedPendingTransactionsOnAndroid":{"defaultValue":false,"metadata":{"dateAdded":"2024-08-27","description":"Fixes a limitation on Android where the mounting coordinator would report there are no pending transactions but some of them were actually not processed due to the use of the push model.","purpose":"experimentation"}},"forceBatchingMountItemsOnAndroid":{"defaultValue":false,"metadata":{"dateAdded":"2024-04-10","description":"Forces the mounting layer on Android to always batch mount items instead of dispatching them immediately. This might fix some crashes related to synchronous state updates, where some views dispatch state updates during mount.","purpose":"experimentation"}},"fuseboxEnabledDebug":{"defaultValue":true,"metadata":{"description":"Flag determining if the React Native DevTools (Fusebox) CDP backend should be enabled in debug builds. This flag is global and should not be changed across React Host lifetimes.","purpose":"release"}},"fuseboxEnabledRelease":{"defaultValue":false,"metadata":{"description":"Flag determining if the React Native DevTools (Fusebox) CDP backend should be enabled in release builds. This flag is global and should not be changed across React Host lifetimes.","purpose":"release"}},"initEagerTurboModulesOnNativeModulesQueueAndroid":{"defaultValue":false,"metadata":{"dateAdded":"2024-07-11","description":"Construct modules that requires eager init on the dedicate native modules thread","purpose":"experimentation"}},"lazyAnimationCallbacks":{"defaultValue":false,"metadata":{"dateAdded":"2024-05-01","description":"Only enqueue Choreographer calls if there is an ongoing animation, instead of enqueueing every frame.","purpose":"experimentation"}},"loadVectorDrawablesOnImages":{"defaultValue":false,"metadata":{"dateAdded":"2024-07-12","description":"Adds support for loading vector drawable assets in the Image component (only on Android)","purpose":"experimentation"}},"setAndroidLayoutDirection":{"defaultValue":true,"metadata":{"dateAdded":"2024-05-17","description":"Propagate layout direction to Android views.","purpose":"experimentation"}},"traceTurboModulePromiseRejectionsOnAndroid":{"defaultValue":false,"metadata":{"description":"Enables storing js caller stack when creating promise in native module. This is useful in case of Promise rejection and tracing the cause.","purpose":"operational"}},"useFabricInterop":{"defaultValue":false,"metadata":{"description":"Should this application enable the Fabric Interop Layer for Android? If yes, the application will behave so that it can accept non-Fabric components and render them on Fabric. This toggle is controlling extra logic such as custom event dispatching that are needed for the Fabric Interop Layer to work correctly.","purpose":"release"}},"useImmediateExecutorInAndroidBridgeless":{"defaultValue":false,"metadata":{"dateAdded":"2024-06-06","description":"Invoke callbacks immediately on the ReactInstance rather than going through a background thread for synchronization","purpose":"experimentation"}},"useModernRuntimeScheduler":{"defaultValue":false,"metadata":{"description":"When enabled, it uses the modern fork of RuntimeScheduler that allows scheduling tasks with priorities from any thread.","purpose":"release"},"skipNativeAPI":true},"useNativeViewConfigsInBridgelessMode":{"defaultValue":false,"metadata":{"dateAdded":"2024-04-03","description":"When enabled, the native view configs are used in bridgeless mode.","purpose":"experimentation"}},"useOptimisedViewPreallocationOnAndroid":{"defaultValue":false,"metadata":{"dateAdded":"2024-07-23","description":"Moves more of the work in view preallocation to the main thread to free up JS thread.","purpose":"experimentation"}},"useOptimizedEventBatchingOnAndroid":{"defaultValue":false,"metadata":{"dateAdded":"2024-08-29","description":"Uses an optimized mechanism for event batching on Android that does not need to wait for a Choreographer frame callback.","purpose":"experimentation"}},"useRuntimeShadowNodeReferenceUpdate":{"defaultValue":false,"metadata":{"dateAdded":"2024-06-03","description":"When enabled, cloning shadow nodes within react native will update the reference held by the current JS fiber tree.","purpose":"experimentation"}},"useTurboModuleInterop":{"defaultValue":false,"metadata":{"dateAdded":"2024-07-28","description":"In Bridgeless mode, should legacy NativeModules use the TurboModule system?","purpose":"experimentation"}},"useTurboModules":{"defaultValue":false,"metadata":{"description":"When enabled, NativeModules will be executed by using the TurboModule system","purpose":"release"}}},"jsOnly":{"jsOnlyTestFlag":{"defaultValue":false,"metadata":{"description":"JS-only flag for testing. Do NOT modify.","purpose":"operational"}},"animatedShouldDebounceQueueFlush":{"defaultValue":false,"metadata":{"dateAdded":"2024-02-05","description":"Enables an experimental flush-queue debouncing in Animated.js.","purpose":"experimentation"}},"animatedShouldUseSingleOp":{"defaultValue":false,"metadata":{"dateAdded":"2024-02-05","description":"Enables an experimental mega-operation for Animated.js that replaces many calls to native with a single call into native, to reduce JSI/JNI traffic.","purpose":"experimentation"}},"enableAccessToHostTreeInFabric":{"defaultValue":false,"metadata":{"description":"Enables access to the host tree in Fabric using DOM-compatible APIs.","purpose":"release"}},"enableAnimatedAllowlist":{"defaultValue":false,"metadata":{"dateAdded":"2024-09-10","description":"Enables Animated to skip non-allowlisted props and styles.","purpose":"experimentation"}},"enableAnimatedClearImmediateFix":{"defaultValue":true,"metadata":{"dateAdded":"2024-09-17","description":"Enables an experimental to use the proper clearIntermediate instead of calling the wrong clearTimeout and canceling another timer.","purpose":"experimentation"}},"enableAnimatedPropsMemo":{"defaultValue":false,"metadata":{"dateAdded":"2024-09-11","description":"Enables Animated to analyze props to minimize invalidating `AnimatedProps`.","purpose":"experimentation"}},"enableOptimisedVirtualizedCells":{"defaultValue":false,"metadata":{"dateAdded":"2024-08-21","description":"Removing unnecessary rerenders Virtualized cells after any rerenders of Virualized list. Works with strict=true option","purpose":"experimentation"}},"isLayoutAnimationEnabled":{"defaultValue":true,"metadata":{"description":"Function used to enable / disabled Layout Animations in React Native.","purpose":"release"}},"scheduleAnimatedEndCallbackInMicrotask":{"defaultValue":false,"metadata":{"dateAdded":"2024-09-27","description":"Changes the completion callback supplied via `Animation#start` to be scheduled in a microtask instead of synchronously executed.","purpose":"experimentation"}},"shouldSkipStateUpdatesForLoopingAnimations":{"defaultValue":false,"metadata":{"dateAdded":"2024-07-25","description":"If the animation is within Animated.loop, we do not send state updates to React.","purpose":"experimentation"}},"shouldUseAnimatedObjectForTransform":{"defaultValue":false,"metadata":{"dateAdded":"2024-02-05","description":"Enables use of AnimatedObject for animating transform values.","purpose":"experimentation"}},"shouldUseRemoveClippedSubviewsAsDefaultOnIOS":{"defaultValue":false,"metadata":{"dateAdded":"2024-02-05","description":"removeClippedSubviews prop will be used as the default in FlatList on iOS to match Android","purpose":"experimentation"}},"shouldUseSetNativePropsInFabric":{"defaultValue":true,"metadata":{"dateAdded":"2024-03-05","description":"Enables use of setNativeProps in JS driven animations.","purpose":"experimentation"}},"shouldUseSetNativePropsInNativeAnimationsInFabric":{"defaultValue":false,"metadata":{"dateAdded":"2024-03-05","description":"Enables use of setNativeProps in Native driven animations in Fabric.","purpose":"experimentation"}},"useInsertionEffectsForAnimations":{"defaultValue":false,"metadata":{"dateAdded":"2024-09-12","description":"Changes construction of the animation graph to `useInsertionEffect` instead of `useLayoutEffect`.","purpose":"experimentation"}},"useRefsForTextInputState":{"defaultValue":false,"metadata":{"dateAdded":"2024-07-08","description":"Enable a variant of TextInput that moves some state to refs to avoid unnecessary re-renders","purpose":"experimentation"}}}}
```

Reviewed By: mdvacca

Differential Revision: D64406244

fbshipit-source-id: 6f82da64d1212faf6d5a82862a71fbc1d168134b
2024-10-29 08:02:54 -07:00
Rubén Norte 66ffa5ee4d Small improvement in types for feature flags definitions in JS (#47239)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47239

Changelog: [internal]

Small refactor of the types for feature flags in JS to make objects read-only.

Reviewed By: mdvacca

Differential Revision: D65058612

fbshipit-source-id: 0d72df2f4afebf0426b9ac76a8f8b195c74fea52
2024-10-29 08:02:54 -07:00
Rubén Norte 66df63d3b5 Generalize feature flags script (#47208)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47208

Changelog: [internal]

Small change to unify the yarn commands for feature flags into a single `featureflags` command with options.

Reviewed By: NickGerleman, mdvacca

Differential Revision: D64982509

fbshipit-source-id: 3f9d7ac35f61950bd03fef243e1a95625144a0cd
2024-10-29 08:02:54 -07:00
Samuel Susla 63f8c3dcd6 batch sync events based on event beats second try (#47255)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47255

changelog: [internal]

Batching sync events into a single JavaScript task. The batching mechanism uses EventBeat's induce method.

Reviewed By: javache

Differential Revision: D64930580

fbshipit-source-id: dd68444ae5679155bb360353eec9e38dceb604ce
2024-10-29 07:50:29 -07:00
170 changed files with 2256 additions and 1045 deletions
+1 -1
View File
@@ -90,4 +90,4 @@ untyped-import
untyped-type-import
[version]
^0.250.0
^0.251.1
+1 -1
View File
@@ -21,7 +21,7 @@ module.exports.sleep = sleep;
async function getNpmPackageInfo(pkg, versionOrTag) {
return fetch(`https://registry.npmjs.org/${pkg}/${versionOrTag}`).then(resp =>
res.json(),
resp.json(),
);
}
module.exports.getNpmPackageInfo = getNpmPackageInfo;
+17
View File
@@ -1,5 +1,22 @@
# Changelog
## v0.76.1
### Fixed
#### Android specific
- **runtime** Made AppRegistry callable from Native code in Bridgeless (fixes headless tasks) ([f3fee67c54](https://github.com/facebook/react-native/commit/f3fee67c547ace5e08bc9e119bcb80e0f3454d30) by [@robik](https://github.com/robik))
- **runtime** Add jsBundleFile to DefaultReactNativeHost.kt ([e56bd89ef](https://github.com/facebook/react-native/commit/e56bd89eff72f1d38d2940b9dbd8f7b97037dc22))
#### iOS specific
- **codegen** Do not generate the ComponentCls function in the RCTThirdPartyFabricComponentsProvider for components deined in the app. ([dc7e9e2d83](https://github.com/facebook/react-native/commit/dc7e9e2d83f5af3d2a970521af4fcc7f86d2168d) by [@cipolleschi](https://github.com/cipolleschi))
- **infra** Generated NODE_BINARY in .xcode.env.local now supports paths with a space ([eeaa3ff458](https://github.com/facebook/react-native/commit/eeaa3ff458a3e5c902075bb45161d6ccde31fe53) by [@blakef](https://github.com/blakef))
- **infra** Pin Xcodeproj to < 1.26.0 ([e8776240b41](https://github.com/facebook/react-native/commit/e8776240b41a3147e95713299b69c813be60b8e8))
- **runtime** Fixed bug where background colors would sometimes animate when changing on Views ([1d6ac09530](https://github.com/facebook/react-native/commit/1d6ac09530145e6d2bf1e4dd9d40f51542d9e7f6) by [@joevilches](https://github.com/joevilches))
- **runtime** Fixes regression of RCTWindowFrameDidChangeNotification not fired ([e271b23fad](https://github.com/facebook/react-native/commit/e271b23fad89e1e7da2e91a8f1e5cbb295406c74) by [@zhongwuzw](https://github.com/zhongwuzw))
## v0.76.0
### Breaking
+2 -3
View File
@@ -14,8 +14,7 @@
"flow": "flow",
"format-check": "prettier --list-different \"./**/*.{js,md,yml,ts,tsx}\"",
"format": "npm run prettier && npm run clang-format",
"featureflags-check": "cd packages/react-native && yarn featureflags-check",
"featureflags-update": "cd packages/react-native && yarn featureflags-update",
"featureflags": "cd packages/react-native && yarn featureflags",
"lint-ci": "./scripts/circleci/analyze_code.sh && yarn shellcheck",
"lint-java": "node ./scripts/lint-java.js",
"lint": "eslint .",
@@ -78,7 +77,7 @@
"eslint-plugin-redundant-undefined": "^0.4.0",
"eslint-plugin-relay": "^1.8.3",
"flow-api-translator": "0.24.0",
"flow-bin": "^0.250.0",
"flow-bin": "^0.251.1",
"glob": "^7.1.1",
"hermes-eslint": "0.24.0",
"hermes-transform": "0.24.0",
+1 -1
View File
@@ -31,7 +31,7 @@
"nullthrows": "^1.1.1",
"open": "^7.0.3",
"selfsigned": "^2.4.1",
"serve-static": "^1.13.1",
"serve-static": "^1.16.2",
"ws": "^6.2.3"
},
"engines": {
+2 -2
View File
@@ -39,7 +39,7 @@ module.exports = {
overrides: [
{
files: ['*.js'],
parser: 'hermes-eslint',
parser: '@babel/eslint-parser',
plugins: ['ft-flow'],
rules: {
// Flow Plugin
@@ -51,7 +51,7 @@ module.exports = {
},
{
files: ['*.jsx'],
parser: 'hermes-eslint',
parser: '@babel/eslint-parser',
},
{
files: ['*.ts', '*.tsx'],
@@ -21,6 +21,7 @@
"main": "index.js",
"dependencies": {
"@babel/core": "^7.25.2",
"@babel/eslint-parser": "^7.25.1",
"@react-native/eslint-plugin": "0.77.0-main",
"@typescript-eslint/eslint-plugin": "^7.1.1",
"@typescript-eslint/parser": "^7.1.1",
@@ -30,8 +31,7 @@
"eslint-plugin-jest": "^27.9.0",
"eslint-plugin-react": "^7.30.1",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-native": "^4.0.0",
"hermes-eslint": "0.24.0"
"eslint-plugin-react-native": "^4.0.0"
},
"peerDependencies": {
"eslint": ">=8",
@@ -1,5 +1,5 @@
[versions]
agp = "8.7.1"
agp = "8.7.2"
gson = "2.8.9"
guava = "31.0.1-jre"
javapoet = "1.13.0"
@@ -53,11 +53,8 @@ internal object NdkConfiguratorUtils {
if (cmakeArgs.none { it.startsWith("-DANDROID_STL") }) {
cmakeArgs.add("-DANDROID_STL=c++_shared")
}
// Due to the new NDK toolchain file, the C++ flags gets overridden between compilation
// units. This is causing some libraries to don't be compiled with -DANDROID and other
// crucial flags. This can be revisited once we bump to NDK 25/26
if (cmakeArgs.none { it.startsWith("-DANDROID_USE_LEGACY_TOOLCHAIN_FILE") }) {
cmakeArgs.add("-DANDROID_USE_LEGACY_TOOLCHAIN_FILE=ON")
if (cmakeArgs.none { it.startsWith("-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES") }) {
cmakeArgs.add("-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON")
}
val architectures = project.getReactNativeArchitectures()
-17
View File
@@ -387,15 +387,6 @@ const LOG_LEVELS = {
warn: 2,
error: 3,
};
const INSPECTOR_LEVELS = [];
INSPECTOR_LEVELS[LOG_LEVELS.trace] = 'debug';
INSPECTOR_LEVELS[LOG_LEVELS.info] = 'log';
INSPECTOR_LEVELS[LOG_LEVELS.warn] = 'warning';
INSPECTOR_LEVELS[LOG_LEVELS.error] = 'error';
// Strip the inner function in getNativeLogFunction(), if in dev also
// strip method printing to originalConsole.
const INSPECTOR_FRAMES_TO_SKIP = __DEV__ ? 2 : 1;
function getNativeLogFunction(level) {
return function () {
@@ -429,14 +420,6 @@ function getNativeLogFunction(level) {
// (Note: Logic duplicated in ExceptionsManager.js.)
logLevel = LOG_LEVELS.warn;
}
if (global.__inspectorLog) {
global.__inspectorLog(
INSPECTOR_LEVELS[logLevel],
str,
[].slice.call(arguments),
INSPECTOR_FRAMES_TO_SKIP,
);
}
if (groupStack.length) {
str = groupFormat('', str);
}
@@ -16,5 +16,5 @@ import * as React from 'react';
export default (createAnimatedComponent(FlatList): AnimatedComponentType<
React.ElementConfig<typeof FlatList>,
React.ElementRef<typeof FlatList>,
FlatList<mixed>,
>);
@@ -8,7 +8,9 @@
#import <React/RCTBridgeDelegate.h>
#import <React/RCTConvert.h>
#import <UIKit/UIKit.h>
#import "RCTArchConfiguratorProtocol.h"
#import "RCTRootViewFactory.h"
#import "RCTUIConfiguratorProtocol.h"
@class RCTBridge;
@protocol RCTBridgeDelegate;
@@ -55,7 +57,12 @@ NS_ASSUME_NONNULL_BEGIN
(const facebook::react::ObjCTurboModule::InitParams &)params
* - (id<RCTTurboModule>)getModuleInstanceFromClass:(Class)moduleClass
*/
@interface RCTAppDelegate : UIResponder <UIApplicationDelegate, UISceneDelegate, RCTBridgeDelegate>
@interface RCTAppDelegate : UIResponder <
UIApplicationDelegate,
UISceneDelegate,
RCTBridgeDelegate,
RCTUIConfiguratorProtocol,
RCTArchConfiguratorProtocol>
/// The window object, used to render the UViewControllers
@property (nonatomic, strong, nonnull) UIWindow *window;
@@ -96,48 +103,6 @@ NS_ASSUME_NONNULL_BEGIN
- (UIView *)createRootViewWithBridge:(RCTBridge *)bridge
moduleName:(NSString *)moduleName
initProps:(NSDictionary *)initProps;
/**
* This method can be used to customize the rootView that is passed to React Native.
* A typical example is to override this method in the AppDelegate to change the background color.
* To achieve this, add in your `AppDelegate.mm`:
* ```
* - (void)customizeRootView:(RCTRootView *)rootView
* {
* rootView.backgroundColor = [UIColor colorWithDynamicProvider:^UIColor *(UITraitCollection *traitCollection) {
* if ([traitCollection userInterfaceStyle] == UIUserInterfaceStyleDark) {
* return [UIColor blackColor];
* } else {
* return [UIColor whiteColor];
* }
* }];
* }
* ```
*
* @parameter: rootView - The root view to customize.
*/
- (void)customizeRootView:(RCTRootView *)rootView;
/**
* It creates the RootViewController.
* By default, it creates a new instance of a `UIViewController`.
* You can override it to provide your own initial ViewController.
*
* @return: an instance of `UIViewController`.
*/
- (UIViewController *)createRootViewController;
/**
* It assigns the rootView to the rootViewController
* By default, it assigns the rootView to the view property of the rootViewController
* If you are not using a simple UIViewController, then there could be other methods to use to setup the rootView.
* For example: UISplitViewController requires `setViewController(_:for:)`
*/
- (void)setRootView:(UIView *)rootView toRootViewController:(UIViewController *)rootViewController;
/**
* The default `RCTColorSpace` for the app. It defaults to `RCTColorSpaceSRGB`.
*/
@property (nonatomic, readonly) RCTColorSpace defaultColorSpace;
/// 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
@@ -147,27 +112,6 @@ NS_ASSUME_NONNULL_BEGIN
/// @return a dictionary that associate a component for the new renderer with his descriptor.
- (NSDictionary<NSString *, Class<RCTComponentViewProtocol>> *)thirdPartyFabricComponents;
/// This method controls whether the `turboModules` feature of the New Architecture is turned on or off.
///
/// @note: This is required to be rendering on Fabric (i.e. on the New Architecture).
/// @return: `true` if the Turbo Native Module are enabled. Otherwise, it returns `false`.
- (BOOL)turboModuleEnabled __attribute__((deprecated("Use newArchEnabled instead")));
/// This method controls whether the App will use the Fabric renderer of the New Architecture or not.
///
/// @return: `true` if the Fabric Renderer is enabled. Otherwise, it returns `false`.
- (BOOL)fabricEnabled __attribute__((deprecated("Use newArchEnabled instead")));
/// This method controls whether React Native's new initialization layer is enabled.
///
/// @return: `true` if the new initialization layer is enabled. Otherwise returns `false`.
- (BOOL)bridgelessEnabled __attribute__((deprecated("Use newArchEnabled instead")));
/// This method controls whether React Native uses new Architecture.
///
/// @return: `true` if the new architecture is enabled. Otherwise returns `false`.
- (BOOL)newArchEnabled;
/// Return the bundle URL for the main bundle.
- (NSURL *__nullable)bundleURL;
@@ -34,6 +34,8 @@
#endif
#import <react/nativemodule/defaults/DefaultTurboModules.h>
using namespace facebook::react;
@interface RCTAppDelegate () <RCTComponentViewFactoryComponentProvider, RCTHostDelegate>
@end
@@ -179,18 +181,6 @@
{
}
- (void)host:(RCTHost *)host
didReceiveJSErrorStack:(NSArray<NSDictionary<NSString *, id> *> *)stack
message:(NSString *)message
originalMessage:(NSString *_Nullable)originalMessage
name:(NSString *_Nullable)name
componentStack:(NSString *_Nullable)componentStack
exceptionId:(NSUInteger)exceptionId
isFatal:(BOOL)isFatal
extraData:(NSDictionary<NSString *, id> *)extraData
{
}
#pragma mark - Bridge and Bridge Adapter properties
- (RCTBridge *)bridge
@@ -224,15 +214,14 @@
#endif
}
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const std::string &)name
jsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
- (std::shared_ptr<TurboModule>)getTurboModule:(const std::string &)name
jsInvoker:(std::shared_ptr<CallInvoker>)jsInvoker
{
return facebook::react::DefaultTurboModules::getTurboModule(name, jsInvoker);
return DefaultTurboModules::getTurboModule(name, jsInvoker);
}
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const std::string &)name
initParams:
(const facebook::react::ObjCTurboModule::InitParams &)params
- (std::shared_ptr<TurboModule>)getTurboModule:(const std::string &)name
initParams:(const ObjCTurboModule::InitParams &)params
{
return nullptr;
}
@@ -306,7 +295,7 @@
#pragma mark - Feature Flags
class RCTAppDelegateBridgelessFeatureFlags : public facebook::react::ReactNativeFeatureFlagsDefaults {
class RCTAppDelegateBridgelessFeatureFlags : public ReactNativeFeatureFlagsDefaults {
public:
bool enableBridgelessArchitecture() override
{
@@ -320,12 +309,16 @@ class RCTAppDelegateBridgelessFeatureFlags : public facebook::react::ReactNative
{
return true;
}
bool useNativeViewConfigsInBridgelessMode() override
{
return true;
}
};
- (void)_setUpFeatureFlags
{
if ([self bridgelessEnabled]) {
facebook::react::ReactNativeFeatureFlags::override(std::make_unique<RCTAppDelegateBridgelessFeatureFlags>());
ReactNativeFeatureFlags::override(std::make_unique<RCTAppDelegateBridgelessFeatureFlags>());
}
}
@@ -53,7 +53,9 @@ RCTAppSetupDefaultRootView(RCTBridge *bridge, NSString *moduleName, NSDictionary
id<RCTSurfaceProtocol> surface = [[RCTFabricSurface alloc] initWithBridge:bridge
moduleName:moduleName
initialProperties:initialProperties];
return [[RCTSurfaceHostingProxyRootView alloc] initWithSurface:surface];
UIView *rootView = [[RCTSurfaceHostingProxyRootView alloc] initWithSurface:surface];
[surface start];
return rootView;
}
return [[RCTRootView alloc] initWithBridge:bridge moduleName:moduleName initialProperties:initialProperties];
}
@@ -0,0 +1,32 @@
/*
* 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/RCTConvert.h>
#import <UIKit/UIKit.h>
@protocol RCTArchConfiguratorProtocol
/// This method controls whether the `turboModules` feature of the New Architecture is turned on or off.
///
/// @note: This is required to be rendering on Fabric (i.e. on the New Architecture).
/// @return: `true` if the Turbo Native Module are enabled. Otherwise, it returns `false`.
- (BOOL)turboModuleEnabled __attribute__((deprecated("Use newArchEnabled instead")));
/// This method controls whether the App will use the Fabric renderer of the New Architecture or not.
///
/// @return: `true` if the Fabric Renderer is enabled. Otherwise, it returns `false`.
- (BOOL)fabricEnabled __attribute__((deprecated("Use newArchEnabled instead")));
/// This method controls whether React Native's new initialization layer is enabled.
///
/// @return: `true` if the new initialization layer is enabled. Otherwise returns `false`.
- (BOOL)bridgelessEnabled __attribute__((deprecated("Use newArchEnabled instead")));
/// This method controls whether React Native uses new Architecture.
///
/// @return: `true` if the new architecture is enabled. Otherwise returns `false`.
- (BOOL)newArchEnabled;
@end
@@ -161,12 +161,9 @@ static NSDictionary *updateInitialProps(NSDictionary *initialProps, BOOL isFabri
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);
NSDictionary *initProps = updateInitialProps(initialProperties, _configuration.fabricEnabled);
if (_configuration.bridgelessEnabled) {
// Enable TurboModule interop by default in Bridgeless mode
RCTEnableTurboModuleInterop(YES);
RCTEnableTurboModuleInteropBridgeProxy(YES);
@@ -175,9 +172,8 @@ static NSDictionary *updateInitialProps(NSDictionary *initialProps, BOOL isFabri
RCTFabricSurface *surface = [self.reactHost createSurfaceWithModuleName:moduleName initialProperties:initProps];
RCTSurfaceHostingProxyRootView *surfaceHostingProxyRootView = [[RCTSurfaceHostingProxyRootView alloc]
initWithSurface:surface
sizeMeasureMode:RCTSurfaceSizeMeasureModeWidthExact | RCTSurfaceSizeMeasureModeHeightExact];
RCTSurfaceHostingProxyRootView *surfaceHostingProxyRootView =
[[RCTSurfaceHostingProxyRootView alloc] initWithSurface:surface];
surfaceHostingProxyRootView.backgroundColor = [UIColor systemBackgroundColor];
if (self->_configuration.customizeRootView != nil) {
@@ -190,8 +186,8 @@ static NSDictionary *updateInitialProps(NSDictionary *initialProps, BOOL isFabri
[self createBridgeAdapterIfNeeded];
UIView *rootView;
if (self->_configuration.createRootViewWithBridge != nil) {
rootView = self->_configuration.createRootViewWithBridge(self.bridge, moduleName, initProps);
if (_configuration.createRootViewWithBridge != nil) {
rootView = _configuration.createRootViewWithBridge(self.bridge, moduleName, initProps);
} else {
rootView = [self createRootViewWithBridge:self.bridge moduleName:moduleName initProps:initProps];
}
@@ -0,0 +1,56 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <React/RCTConvert.h>
#import <UIKit/UIKit.h>
@class RCTRootView;
@protocol RCTUIConfiguratorProtocol
/**
* The default `RCTColorSpace` for the app. It defaults to `RCTColorSpaceSRGB`.
*/
- (RCTColorSpace)defaultColorSpace;
/**
* This method can be used to customize the rootView that is passed to React Native.
* A typical example is to override this method in the AppDelegate to change the background color.
* To achieve this, add in your `AppDelegate.mm`:
* ```
* - (void)customizeRootView:(RCTRootView *)rootView
* {
* rootView.backgroundColor = [UIColor colorWithDynamicProvider:^UIColor *(UITraitCollection *traitCollection) {
* if ([traitCollection userInterfaceStyle] == UIUserInterfaceStyleDark) {
* return [UIColor blackColor];
* } else {
* return [UIColor whiteColor];
* }
* }];
* }
* ```
*
* @parameter: rootView - The root view to customize.
*/
- (void)customizeRootView:(RCTRootView *)rootView;
/**
* It creates the RootViewController.
* By default, it creates a new instance of a `UIViewController`.
* You can override it to provide your own initial ViewController.
*
* @return: an instance of `UIViewController`.
*/
- (UIViewController *)createRootViewController;
/**
* It assigns the rootView to the rootViewController
* By default, it assigns the rootView to the view property of the rootViewController
* If you are not using a simple UIViewController, then there could be other methods to use to setup the rootView.
* For example: UISplitViewController requires `setViewController(_:for:)`
*/
- (void)setRootView:(UIView *)rootView toRootViewController:(UIViewController *)rootViewController;
@end
+25 -11
View File
@@ -142,7 +142,11 @@ let inExceptionHandler = false;
*/
function handleException(e: mixed, isFatal: boolean) {
// TODO(T196834299): We should really use a c++ turbomodule for this
if (!global.RN$handleException || !global.RN$handleException(e, isFatal)) {
const reportToConsole = true;
if (
!global.RN$handleException ||
!global.RN$handleException(e, isFatal, reportToConsole)
) {
let error: Error;
if (e instanceof Error) {
error = e;
@@ -158,7 +162,7 @@ function handleException(e: mixed, isFatal: boolean) {
/* $FlowFixMe[class-object-subtyping] added when improving typing for this
* parameters */
// $FlowFixMe[incompatible-call]
reportException(error, isFatal, /*reportToConsole*/ true);
reportException(error, isFatal, reportToConsole);
} finally {
inExceptionHandler = false;
}
@@ -173,7 +177,10 @@ function reactConsoleErrorHandler(...args) {
if (!console.reportErrorsAsExceptions) {
return;
}
if (inExceptionHandler) {
if (
inExceptionHandler ||
(global.RN$inExceptionHandler && global.RN$inExceptionHandler())
) {
// The fundamental trick here is that are multiple entry point to logging errors:
// (see D19743075 for more background)
//
@@ -227,14 +234,21 @@ function reactConsoleErrorHandler(...args) {
error.name = 'console.error';
}
reportException(
/* $FlowFixMe[class-object-subtyping] added when improving typing for this
* parameters */
// $FlowFixMe[incompatible-call]
error,
false, // isFatal
false, // reportToConsole
);
const isFatal = false;
const reportToConsole = false;
if (
!global.RN$handleException ||
!global.RN$handleException(error, isFatal, reportToConsole)
) {
reportException(
/* $FlowFixMe[class-object-subtyping] added when improving typing for this
* parameters */
// $FlowFixMe[incompatible-call]
error,
isFatal,
reportToConsole,
);
}
}
/**
+18 -29
View File
@@ -60,18 +60,28 @@ export interface ImagePropsIOS {
interface ImagePropsAndroid {
/**
* The mechanism that should be used to resize the image when the image's dimensions
* differ from the image view's dimensions. Defaults to auto.
* differ from the image view's dimensions. Defaults to `auto`.
*
* 'auto': Use heuristics to pick between resize and scale.
* - `auto`: Use heuristics to pick between `resize` and `scale`.
*
* 'resize': A software operation which changes the encoded image in memory before it gets decoded.
* This should be used instead of scale when the image is much larger than the view.
* - `resize`: A software operation which changes the encoded image in memory before it
* gets decoded. This should be used instead of `scale` when the image is much larger
* than the view.
*
* 'scale': The image gets drawn downscaled or upscaled. Compared to resize, scale is faster (usually hardware accelerated)
* and produces higher quality images. This should be used if the image is smaller than the view.
* It should also be used if the image is slightly bigger than the view.
* - `scale`: The image gets drawn downscaled or upscaled. Compared to `resize`, `scale` is
* faster (usually hardware accelerated) and produces higher quality images. This
* should be used if the image is smaller than the view. It should also be used if the
* image is slightly bigger than the view.
*
* - `none`: No sampling is performed and the image is displayed in its full resolution. This
* should only be used in rare circumstances because it is considered unsafe as Android will
* throw a runtime exception when trying to render images that consume too much memory.
*
* More details about `resize` and `scale` can be found at http://frescolib.org/docs/resizing-rotating.html.
*
* @platform android
*/
resizeMethod?: 'auto' | 'resize' | 'scale' | undefined;
resizeMethod?: 'auto' | 'resize' | 'scale' | 'none' | undefined;
/**
* Duration of fade in animation in ms. Defaults to 300
@@ -193,27 +203,6 @@ export interface ImagePropsBase
*/
resizeMode?: ImageResizeMode | undefined;
/**
* The mechanism that should be used to resize the image when the image's dimensions
* differ from the image view's dimensions. Defaults to `auto`.
*
* - `auto`: Use heuristics to pick between `resize` and `scale`.
*
* - `resize`: A software operation which changes the encoded image in memory before it
* gets decoded. This should be used instead of `scale` when the image is much larger
* than the view.
*
* - `scale`: The image gets drawn downscaled or upscaled. Compared to `resize`, `scale` is
* faster (usually hardware accelerated) and produces higher quality images. This
* should be used if the image is smaller than the view. It should also be used if the
* image is slightly bigger than the view.
*
* More details about `resize` and `scale` can be found at http://frescolib.org/docs/resizing-rotating.html.
*
* @platform android
*/
resizeMethod?: 'auto' | 'resize' | 'scale' | undefined;
/**
* The image source (either a remote URL or a local file resource).
*
+1 -1
View File
@@ -51,7 +51,7 @@ export interface ImageURISource {
* to a URL load request, no attempt is made to load the data from the originating source,
* and the load is considered to have failed.
*
* @platform ios
* @platform ios (for `force-cache`)
*/
cache?: 'default' | 'reload' | 'force-cache' | 'only-if-cached' | undefined;
/**
+1 -1
View File
@@ -66,7 +66,7 @@ export interface ImageURISource {
* to a URL load request, no attempt is made to load the data from the originating source,
* and the load is considered to have failed.
*
* @platform ios
* @platform ios (for `force-cache`)
*/
+cache?: ?('default' | 'reload' | 'force-cache' | 'only-if-cached');
+2 -2
View File
@@ -480,10 +480,10 @@ class FlatList<ItemT> extends React.PureComponent<Props<ItemT>, void> {
this._checkProps(this.props);
}
_listRef: ?React.ElementRef<typeof VirtualizedList>;
_listRef: ?VirtualizedList;
_virtualizedListPairs: Array<ViewabilityConfigCallbackPair> = [];
_captureRef = (ref: ?React.ElementRef<typeof VirtualizedList>) => {
_captureRef = (ref: ?VirtualizedList) => {
this._listRef = ref;
};
+26 -17
View File
@@ -37,6 +37,8 @@ const COLORS = {
'ansi-bright-white': 'rgb(247, 247, 247)',
};
const LRM = '\u200E'; // Left-to-Right Mark
export default function Ansi({
text,
style,
@@ -80,25 +82,28 @@ export default function Ansi({
};
return (
<View>
<View style={styles.container}>
{parsedLines.map((items, i) => (
<View style={styles.line} key={i}>
{items.map((bundle, key) => {
const textStyle =
bundle.fg && COLORS[bundle.fg]
? {
backgroundColor: bundle.bg && COLORS[bundle.bg],
color: bundle.fg && COLORS[bundle.fg],
}
: {
backgroundColor: bundle.bg && COLORS[bundle.bg],
};
return (
<Text style={[style, textStyle]} key={key}>
{getText(bundle.content, key)}
</Text>
);
})}
<Text>
{LRM}
{items.map((bundle, key) => {
const textStyle =
bundle.fg && COLORS[bundle.fg]
? {
backgroundColor: bundle.bg && COLORS[bundle.bg],
color: bundle.fg && COLORS[bundle.fg],
}
: {
backgroundColor: bundle.bg && COLORS[bundle.bg],
};
return (
<Text style={[style, textStyle]} key={key}>
{getText(bundle.content, key)}
</Text>
);
})}
</Text>
</View>
))}
</View>
@@ -106,6 +111,10 @@ export default function Ansi({
}
const styles = StyleSheet.create({
container: {
minWidth: '100%',
direction: 'ltr',
},
line: {
flexDirection: 'row',
},
@@ -59,7 +59,9 @@ function LogBoxInspectorCodeFrame(props: Props): React.Node {
<LogBoxInspectorSection heading="Source" action={<AppInfo />}>
<View style={styles.box}>
<View style={styles.frame}>
<ScrollView horizontal>
<ScrollView
horizontal
contentContainerStyle={styles.contentContainer}>
<AnsiHighlight style={styles.content} text={codeFrame.content} />
</ScrollView>
</View>
@@ -138,6 +140,9 @@ const styles = StyleSheet.create({
paddingTop: 10,
paddingBottom: 10,
},
contentContainer: {
minWidth: '100%',
},
content: {
color: LogBoxStyle.getTextColor(1),
fontSize: 12,
@@ -26,6 +26,11 @@ exports[`LogBoxInspectorCodeFrame should render a code frame 1`] = `
}
>
<ScrollView
contentContainerStyle={
Object {
"minWidth": "100%",
}
}
horizontal={true}
>
<Ansi
@@ -108,6 +113,11 @@ exports[`LogBoxInspectorCodeFrame should render a code frame without a location
}
>
<ScrollView
contentContainerStyle={
Object {
"minWidth": "100%",
}
}
horizontal={true}
>
<Ansi
@@ -36,6 +36,7 @@ static NSSet<NSNumber *> *returnKeyTypesSet;
{
if (![self isDescendantOfView:scrollView]) {
// View is outside scroll view
scrollView.firstResponderViewOutsideScrollView = self.backedTextInputView;
return;
}
@@ -683,7 +683,7 @@ exports[`public API should not change unintentionally Libraries/Animated/bezier.
exports[`public API should not change unintentionally Libraries/Animated/components/AnimatedFlatList.js 1`] = `
"declare export default AnimatedComponentType<
React.ElementConfig<typeof FlatList>,
React.ElementRef<typeof FlatList>,
FlatList<mixed>,
>;
"
`;
@@ -5725,7 +5725,7 @@ declare class FlatList<ItemT> extends React.PureComponent<Props<ItemT>, void> {
setNativeProps(props: { [string]: mixed, ... }): void;
constructor(props: Props<ItemT>): void;
componentDidUpdate(prevProps: Props<ItemT>): void;
_listRef: ?React.ElementRef<typeof VirtualizedList>;
_listRef: ?VirtualizedList;
_virtualizedListPairs: Array<ViewabilityConfigCallbackPair>;
_captureRef: $FlowFixMe;
_checkProps(props: Props<ItemT>): void;
@@ -18,6 +18,9 @@ NS_ASSUME_NONNULL_BEGIN
@interface RCTBridgeProxy : NSProxy
- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)new NS_UNAVAILABLE;
- (instancetype)initWithViewRegistry:(RCTViewRegistry *)viewRegistry
moduleRegistry:(RCTModuleRegistry *)moduleRegistry
bundleManager:(RCTBundleManager *)bundleManager
@@ -41,6 +41,8 @@ using namespace facebook;
void *_runtime;
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-designated-initializers"
- (instancetype)initWithViewRegistry:(RCTViewRegistry *)viewRegistry
moduleRegistry:(RCTModuleRegistry *)moduleRegistry
bundleManager:(RCTBundleManager *)bundleManager
@@ -61,8 +63,10 @@ using namespace facebook;
_runtime = runtime;
_launchOptions = [launchOptions copy];
}
return self;
}
#pragma clang diagnostic pop
- (void)dispatchBlock:(dispatch_block_t)block queue:(dispatch_queue_t)queue
{
@@ -414,6 +418,10 @@ using namespace facebook;
RCTViewRegistry *_viewRegistry;
NSMutableDictionary<NSNumber *, UIView *> *_legacyViewRegistry;
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-designated-initializers"
- (instancetype)initWithViewRegistry:(RCTViewRegistry *)viewRegistry
{
self = [super self];
@@ -424,6 +432,8 @@ using namespace facebook;
return self;
}
#pragma clang diagnostic pop
/**
* RCTViewRegistry
*/
@@ -11,6 +11,11 @@
std::shared_ptr<facebook::react::CallInvoker> _callInvoker;
}
- (instancetype)init
{
return [self initWithCallInvoker:nullptr];
}
- (instancetype)initWithCallInvoker:(std::shared_ptr<facebook::react::CallInvoker>)callInvoker
{
if (self = [super init]) {
@@ -50,15 +50,3 @@ RCT_EXTERN NSString *const RCTDidInitializeModuleNotification;
*/
RCT_EXTERN BOOL RCTGetDispatchW3CPointerEvents(void);
RCT_EXTERN void RCTSetDispatchW3CPointerEvents(BOOL value);
/*
* Memory Pressure Unloading Level
*/
RCT_EXTERN int RCTGetMemoryPressureUnloadLevel(void);
RCT_EXTERN void RCTSetMemoryPressureUnloadLevel(int value);
/*
* Use native view configs in bridgeless mode
*/
RCT_EXTERN BOOL RCTGetUseNativeViewConfigsInBridgelessMode(void);
RCT_EXTERN void RCTSetUseNativeViewConfigsInBridgelessMode(BOOL value);
@@ -38,34 +38,3 @@ void RCTSetDispatchW3CPointerEvents(BOOL value)
{
RCTDispatchW3CPointerEvents = value;
}
/*
* Memory Pressure Unloading Level for experimentation only.
* Default is 15, which is TRIM_MEMORY_RUNNING_CRITICAL.
*/
static int RCTMemoryPressureUnloadLevel = 15;
int RCTGetMemoryPressureUnloadLevel(void)
{
return RCTMemoryPressureUnloadLevel;
}
void RCTSetMemoryPressureUnloadLevel(int value)
{
RCTMemoryPressureUnloadLevel = value;
}
/*
* Use native view configs in bridgeless mode
*/
static BOOL RCTUseNativeViewConfigsInBridgelessMode = NO;
BOOL RCTGetUseNativeViewConfigsInBridgelessMode(void)
{
return RCTUseNativeViewConfigsInBridgelessMode;
}
void RCTSetUseNativeViewConfigsInBridgelessMode(BOOL value)
{
RCTUseNativeViewConfigsInBridgelessMode = value;
}
@@ -34,7 +34,7 @@ typedef id<RCTBridgeModule> (^RCTBridgeModuleProvider)(void);
moduleRegistry:(RCTModuleRegistry *)moduleRegistry
viewRegistry_DEPRECATED:(RCTViewRegistry *)viewRegistry_DEPRECATED
bundleManager:(RCTBundleManager *)bundleManager
callableJSModules:(RCTCallableJSModules *)callableJSModules;
callableJSModules:(RCTCallableJSModules *)callableJSModules NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithModuleInstance:(id<RCTBridgeModule>)instance
bridge:(RCTBridge *)bridge
@@ -53,8 +53,21 @@ int32_t getUniqueId()
@synthesize instance = _instance;
@synthesize methodQueue = _methodQueue;
- (void)setUp
- (void)_setUpWithBridge:(RCTBridge *)bridge
moduleRegistry:(RCTModuleRegistry *)moduleRegistry
viewRegistry_DEPRECATED:(RCTViewRegistry *)viewRegistry_DEPRECATED
bundleManager:(RCTBundleManager *)bundleManager
callableJSModules:(RCTCallableJSModules *)callableJSModules
{
// start with the ivars
{
_bridge = bridge;
_moduleRegistry = moduleRegistry;
_viewRegistry_DEPRECATED = viewRegistry_DEPRECATED;
_bundleManager = bundleManager;
_callableJSModules = callableJSModules;
}
_implementsBatchDidComplete = [_moduleClass instancesRespondToSelector:@selector(batchDidComplete)];
// If a module overrides `constantsToExport` and doesn't implement `requiresMainQueueSetup`, then we must assume
@@ -86,35 +99,17 @@ int32_t getUniqueId()
viewRegistry_DEPRECATED:(RCTViewRegistry *)viewRegistry_DEPRECATED
bundleManager:(RCTBundleManager *)bundleManager
callableJSModules:(RCTCallableJSModules *)callableJSModules
{
return [self _initWithModuleClass:moduleClass
moduleProvider:^id<RCTBridgeModule> {
return [moduleClass new];
}
bridge:bridge
moduleRegistry:moduleRegistry
viewRegistry_DEPRECATED:viewRegistry_DEPRECATED
bundleManager:bundleManager
callableJSModules:callableJSModules];
}
- (instancetype)_initWithModuleClass:(Class)moduleClass
moduleProvider:(RCTBridgeModuleProvider)moduleProvider
bridge:(RCTBridge *)bridge
moduleRegistry:(RCTModuleRegistry *)moduleRegistry
viewRegistry_DEPRECATED:(RCTViewRegistry *)viewRegistry_DEPRECATED
bundleManager:(RCTBundleManager *)bundleManager
callableJSModules:(RCTCallableJSModules *)callableJSModules
{
if (self = [super init]) {
_bridge = bridge;
_moduleClass = moduleClass;
_moduleProvider = [moduleProvider copy];
_moduleRegistry = moduleRegistry;
_viewRegistry_DEPRECATED = viewRegistry_DEPRECATED;
_bundleManager = bundleManager;
_callableJSModules = callableJSModules;
[self setUp];
_moduleProvider = [^id<RCTBridgeModule> {
return [moduleClass new];
} copy];
[self _setUpWithBridge:bridge
moduleRegistry:moduleRegistry
viewRegistry_DEPRECATED:viewRegistry_DEPRECATED
bundleManager:bundleManager
callableJSModules:callableJSModules];
}
return self;
}
@@ -127,14 +122,13 @@ int32_t getUniqueId()
callableJSModules:(RCTCallableJSModules *)callableJSModules
{
if (self = [super init]) {
_bridge = bridge;
_instance = instance;
_moduleClass = [instance class];
_moduleRegistry = moduleRegistry;
_viewRegistry_DEPRECATED = viewRegistry_DEPRECATED;
_bundleManager = bundleManager;
_callableJSModules = callableJSModules;
[self setUp];
[self _setUpWithBridge:bridge
moduleRegistry:moduleRegistry
viewRegistry_DEPRECATED:viewRegistry_DEPRECATED
bundleManager:bundleManager
callableJSModules:callableJSModules];
}
return self;
}
@@ -39,6 +39,13 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, assign) NSTimeInterval loadingViewFadeDuration;
@property (nonatomic, assign) CGSize minimumSize;
- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)new NS_UNAVAILABLE;
- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE;
- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_UNAVAILABLE;
- (instancetype)initWithSurface:(id<RCTSurfaceProtocol>)surface
sizeMeasureMode:(RCTSurfaceSizeMeasureMode)sizeMeasureMode NS_UNAVAILABLE;
- (instancetype)initWithSurface:(id<RCTSurfaceProtocol>)surface NS_DESIGNATED_INITIALIZER;
- (void)cancelTouches;
@@ -53,11 +53,8 @@ static RCTRootViewSizeFlexibility convertToRootViewSizeFlexibility(RCTSurfaceSiz
- (instancetype)initWithSurface:(id<RCTSurfaceProtocol>)surface
{
if (self = [super initWithSurface:surface
sizeMeasureMode:RCTSurfaceSizeMeasureModeWidthExact | RCTSurfaceSizeMeasureModeHeightExact]) {
[surface start];
}
return self;
return [super initWithSurface:surface
sizeMeasureMode:RCTSurfaceSizeMeasureModeWidthExact | RCTSurfaceSizeMeasureModeHeightExact];
}
RCT_NOT_IMPLEMENTED(-(instancetype)initWithFrame : (CGRect)frame)
@@ -34,7 +34,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)reportJsException:(nullable NSString *)message
stack:(nullable NSArray<NSDictionary *> *)stack
exceptionId:(double)exceptionId
isFatal:(bool)isFatal;
isFatal:(bool)isFatal __attribute__((deprecated));
@property (nonatomic, weak) id<RCTExceptionsManagerDelegate> delegate;
@@ -371,7 +371,8 @@ struct RCTInstanceCallback : public InstanceCallback {
// in case if some other tread resets it.
auto reactInstance = _reactInstance;
if (reactInstance) {
int unloadLevel = RCTGetMemoryPressureUnloadLevel();
// Memory Pressure Unloading Level 15 represents TRIM_MEMORY_RUNNING_CRITICAL.
int unloadLevel = 15;
reactInstance->handleMemoryPressure(unloadLevel);
}
}
@@ -100,13 +100,6 @@ using namespace facebook::react;
const auto &imageRequest = _state->getData().getImageRequest();
auto &observerCoordinator = imageRequest.getObserverCoordinator();
observerCoordinator.removeObserver(_imageResponseObserverProxy);
// Cancelling image request because we are no longer observing it.
// This is not 100% correct place to do this because we may want to
// re-create RCTImageComponentView with the same image and if it
// was cancelled before downloaded, download is not resumed.
// This will only become issue if we decouple life cycle of a
// ShadowNode from ComponentView, which is not something we do now.
imageRequest.cancel();
}
_state = state;
@@ -38,6 +38,9 @@ NS_ASSUME_NONNULL_BEGIN
/** Focus area of newly-activated text input relative to the window to compare against UIKeyboardFrameBegin/End */
@property (nonatomic, assign) CGRect firstResponderFocus;
/** newly-activated text input outside of the scroll view */
@property (nonatomic, weak) UIView *firstResponderViewOutsideScrollView;
/*
* Returns the subview of the scroll view that the component uses to mount all subcomponents into. That's useful to
* separate component views from auxiliary views to be able to reliably implement pull-to-refresh- and RTL-related
@@ -182,6 +182,7 @@ RCTSendScrollEventForNativeAnimations_DEPRECATED(UIScrollView *scrollView, NSInt
UIViewAnimationCurve curve =
(UIViewAnimationCurve)[notification.userInfo[UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue];
CGRect keyboardEndFrame = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGRect keyboardBeginFrame = [notification.userInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue];
CGPoint absoluteViewOrigin = [self convertPoint:self.bounds.origin toView:nil];
CGFloat scrollViewLowerY = isInverted ? absoluteViewOrigin.y : absoluteViewOrigin.y + self.bounds.size.height;
@@ -203,21 +204,24 @@ RCTSendScrollEventForNativeAnimations_DEPRECATED(UIScrollView *scrollView, NSInt
from:self
forEvent:nil]) {
if (CGRectEqualToRect(_firstResponderFocus, CGRectNull)) {
// Text input view is outside of the scroll view.
return;
}
UIView *inputAccessoryView = _firstResponderViewOutsideScrollView.inputAccessoryView;
if (inputAccessoryView) {
// Text input view is within the inputAccessoryView.
contentDiff = keyboardEndFrame.origin.y - keyboardBeginFrame.origin.y;
}
} else {
CGRect viewIntersection = CGRectIntersection(self.firstResponderFocus, keyboardEndFrame);
CGRect viewIntersection = CGRectIntersection(self.firstResponderFocus, keyboardEndFrame);
if (CGRectIsNull(viewIntersection)) {
return;
}
if (CGRectIsNull(viewIntersection)) {
return;
}
// Inner text field focused
CGFloat focusEnd = CGRectGetMaxY(self.firstResponderFocus);
if (focusEnd > keyboardEndFrame.origin.y) {
// Text field active region is below visible area with keyboard - update diff to bring into view
contentDiff = keyboardEndFrame.origin.y - focusEnd;
// Inner text field focused
CGFloat focusEnd = CGRectGetMaxY(self.firstResponderFocus);
if (focusEnd > keyboardEndFrame.origin.y) {
// Text field active region is below visible area with keyboard - update diff to bring into view
contentDiff = keyboardEndFrame.origin.y - focusEnd;
}
}
}
@@ -126,6 +126,7 @@ static NSSet<NSNumber *> *returnKeyTypesSet;
{
if (![self isDescendantOfView:scrollView.scrollView] || !_backedTextInputView.isFirstResponder) {
// View is outside scroll view or it's not a first responder.
scrollView.firstResponderViewOutsideScrollView = _backedTextInputView;
return;
}
@@ -114,9 +114,6 @@ class LayoutAnimationDelegateProxy : public LayoutAnimationStatusDelegate, publi
- (instancetype)initWithToolbox:(SchedulerToolbox)toolbox
{
if (self = [super init]) {
auto reactNativeConfig =
toolbox.contextContainer->at<std::shared_ptr<const ReactNativeConfig>>("ReactNativeConfig");
_delegateProxy = std::make_unique<SchedulerDelegateProxy>((__bridge void *)self);
if (ReactNativeFeatureFlags::enableLayoutAnimationsOnIOS()) {
@@ -620,22 +620,22 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithTarget : (id)target action : (SEL)act
if (eventEmitter != nil) {
switch (eventType) {
case RCTPointerEventTypeStart: {
eventEmitter->onPointerDown(pointerEvent);
eventEmitter->onPointerDown(std::move(pointerEvent));
break;
}
case RCTPointerEventTypeMove: {
eventEmitter->onPointerMove(pointerEvent);
eventEmitter->onPointerMove(std::move(pointerEvent));
break;
}
case RCTPointerEventTypeEnd: {
eventEmitter->onPointerUp(pointerEvent);
if (pointerEvent.isPrimary && pointerEvent.button == 0 && IsPointerWithinInitialTree(activePointer)) {
eventEmitter->onClick(pointerEvent);
eventEmitter->onClick(std::move(pointerEvent));
}
break;
}
case RCTPointerEventTypeCancel: {
eventEmitter->onPointerCancel(pointerEvent);
eventEmitter->onPointerCancel(std::move(pointerEvent));
break;
}
}
@@ -761,10 +761,10 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithTarget : (id)target action : (SEL)act
if (eventEmitter != nil) {
switch (recognizer.state) {
case UIGestureRecognizerStateEnded:
eventEmitter->onPointerLeave(event);
eventEmitter->onPointerLeave(std::move(event));
break;
default:
eventEmitter->onPointerMove(event);
eventEmitter->onPointerMove(std::move(event));
break;
}
}
@@ -26,7 +26,6 @@
#import <React/RCTSurfaceView.h>
#import <React/RCTUtils.h>
#import <react/config/ReactNativeConfig.h>
#import <react/featureflags/ReactNativeFeatureFlags.h>
#import <react/renderer/componentregistry/ComponentDescriptorFactory.h>
#import <react/renderer/components/text/BaseTextProps.h>
@@ -226,8 +225,6 @@ using namespace facebook::react;
- (RCTScheduler *)_createScheduler
{
auto reactNativeConfig = _contextContainer->at<std::shared_ptr<const ReactNativeConfig>>("ReactNativeConfig");
auto componentRegistryFactory =
[factory = wrapManagedObject(_mountingManager.componentViewRegistry.componentViewFactory)](
const EventDispatcher::Weak &eventDispatcher, const ContextContainer::Shared &contextContainer) {
@@ -1,3 +1,4 @@
// @lint-ignore-every LICENSELINT
/*
* Copyright (c) 2015 Daniel Kirchner
*
@@ -27,10 +28,6 @@
NS_ASSUME_NONNULL_BEGIN
#ifdef __cplusplus
extern "C" {
#endif
/// magic constants :-)
static const uint64_t PRIME1 = 11400714785074694791ULL;
static const uint64_t PRIME2 = 14029467366897019727ULL;
@@ -106,13 +103,18 @@ NS_INLINE uint64_t h32bytes(const char *p, uint64_t len, const uint64_t seed)
return h32bytes_compute(p, len, seed + PRIME1 + PRIME2, seed + PRIME2, seed, seed - PRIME1);
}
/*
Primary APIs
*/
NS_INLINE uint64_t meta_xxhash64(const char *p, uint64_t len, uint64_t seed)
{
return finalize((len >= 32 ? h32bytes(p, len, seed) : seed + PRIME5) + len, p + (len & ~0x1FULL), len & 0x1FULL);
}
NS_INLINE uint64_t FBxxHash64(const char *p, uint64_t len, uint64_t seed)
{
return finalize((len >= 32 ? h32bytes(p, len, seed) : seed + PRIME5) + len, p + (len & ~0x1F), len & 0x1F);
return meta_xxhash64(p, len, seed);
}
#ifdef __cplusplus
}
#endif
NS_ASSUME_NONNULL_END
@@ -9,6 +9,7 @@
#import <AVFoundation/AVFoundation.h>
#import <React/RCTSurfacePresenterStub.h>
#import <react/featureflags/ReactNativeFeatureFlags.h>
#import "RCTAssert.h"
#import "RCTBridge+Private.h"
@@ -1154,10 +1155,10 @@ RCT_EXPORT_METHOD(dispatchViewManagerCommand
return;
}
__weak typeof(self) weakSelf = self;
__weak __typeof(self) weakSelf = self;
void (^mountingBlock)(void) = ^{
typeof(self) strongSelf = weakSelf;
__typeof(self) strongSelf = weakSelf;
@try {
for (RCTViewManagerUIBlock block in previousPendingUIBlocks) {
@@ -1438,7 +1439,7 @@ NSMutableDictionary<NSString *, id> *RCTModuleConstantsForDestructuredComponent(
// lazifyViewManagerConfig function in JS. This fuction uses NativeModules global object that is not available in the
// New Architecture. To make native view configs work in the New Architecture we will populate these properties in
// native.
if (RCTGetUseNativeViewConfigsInBridgelessMode()) {
if (facebook::react::ReactNativeFeatureFlags::useNativeViewConfigsInBridgelessMode()) {
moduleConstants[@"Commands"] = viewConfig[@"Commands"];
moduleConstants[@"Constants"] = viewConfig[@"Constants"];
}
@@ -19,7 +19,7 @@ BOOL RCTBorderInsetsAreEqual(UIEdgeInsets borderInsets)
BOOL RCTCornerRadiiAreEqualAndSymmetrical(RCTCornerRadii cornerRadii)
{
return cornerRadii.topLeftHorizontal == cornerRadii.topLeftHorizontal &&
return cornerRadii.topLeftHorizontal == cornerRadii.topLeftVertical &&
cornerRadii.topRightHorizontal == cornerRadii.topRightVertical &&
cornerRadii.bottomLeftHorizontal == cornerRadii.bottomLeftVertical &&
cornerRadii.bottomRightHorizontal == cornerRadii.bottomRightVertical &&
@@ -8,6 +8,7 @@
#import "RCTComponentData.h"
#import <objc/message.h>
#import <react/featureflags/ReactNativeFeatureFlags.h>
#import "RCTBridge.h"
#import "RCTBridgeModule.h"
@@ -288,9 +289,9 @@ static RCTPropBlock createNSInvocationSetter(NSMethodSignature *typeSignature, S
case _value: { \
__block BOOL setDefaultValue = NO; \
__block _type defaultValue; \
_type (*convert)(id, SEL, id) = (typeof(convert))objc_msgSend; \
_type (*get)(id, SEL) = (typeof(get))objc_msgSend; \
void (*set)(id, SEL, _type) = (typeof(set))objc_msgSend; \
_type (*convert)(id, SEL, id) = (__typeof(convert))objc_msgSend; \
_type (*get)(id, SEL) = (__typeof(get))objc_msgSend; \
void (*set)(id, SEL, _type) = (__typeof(set))objc_msgSend; \
setterBlock = ^(id target, id json) { \
if (json) { \
if (!setDefaultValue && target) { \
@@ -522,7 +523,7 @@ static RCTPropBlock createNSInvocationSetter(NSMethodSignature *typeSignature, S
@"baseModuleName" : superClass == [NSObject class] ? (id)kCFNull : RCTViewManagerModuleNameForClass(superClass),
}];
if (RCTGetUseNativeViewConfigsInBridgelessMode()) {
if (facebook::react::ReactNativeFeatureFlags::useNativeViewConfigsInBridgelessMode()) {
result[@"Commands"] = [self commandsForViewMangerClass:managerClass methods:methods methodCount:count];
result[@"Constants"] = [self constantsForViewMangerClass:managerClass];
}
@@ -50,6 +50,8 @@
@property (nonatomic, assign) BOOL inverted;
/** Focus area of newly-activated text input relative to the window to compare against UIKeyboardFrameBegin/End */
@property (nonatomic, assign) CGRect firstResponderFocus;
/** newly-activated text input outside of the scroll view */
@property (nonatomic, weak) UIView *firstResponderViewOutsideScrollView;
// NOTE: currently these event props are only declared so we can export the
// event names to JS - we don't call the blocks directly because scroll events
@@ -338,6 +338,12 @@ static inline UIViewAnimationOptions animationOptionsWithCurve(UIViewAnimationCu
if (!didFocusExternalTextField && focusEnd > endFrame.origin.y) {
// Text field active region is below visible area with keyboard - update diff to bring into view
contentDiff = endFrame.origin.y - focusEnd;
} else {
UIView *inputAccessoryView = _firstResponderViewOutsideScrollView.inputAccessoryView;
if (inputAccessoryView) {
// Text input view is within the inputAccessoryView.
contentDiff = endFrame.origin.y - beginFrame.origin.y;
}
}
} else if (endFrame.origin.y <= beginFrame.origin.y) {
// Keyboard opened for other reason
@@ -3377,14 +3377,26 @@ public final class com/facebook/react/modules/fresco/FrescoModule$Companion {
public final fun hasBeenInitialized ()Z
}
public final class com/facebook/react/modules/fresco/ImageCacheControl : java/lang/Enum {
public static final field DEFAULT Lcom/facebook/react/modules/fresco/ImageCacheControl;
public static final field ONLY_IF_CACHED Lcom/facebook/react/modules/fresco/ImageCacheControl;
public static final field RELOAD Lcom/facebook/react/modules/fresco/ImageCacheControl;
public static fun getEntries ()Lkotlin/enums/EnumEntries;
public static fun valueOf (Ljava/lang/String;)Lcom/facebook/react/modules/fresco/ImageCacheControl;
public static fun values ()[Lcom/facebook/react/modules/fresco/ImageCacheControl;
}
public final class com/facebook/react/modules/fresco/ReactNetworkImageRequest : com/facebook/imagepipeline/request/ImageRequest {
public static final field Companion Lcom/facebook/react/modules/fresco/ReactNetworkImageRequest$Companion;
public synthetic fun <init> (Lcom/facebook/imagepipeline/request/ImageRequestBuilder;Lcom/facebook/react/bridge/ReadableMap;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> (Lcom/facebook/imagepipeline/request/ImageRequestBuilder;Lcom/facebook/react/bridge/ReadableMap;Lcom/facebook/react/modules/fresco/ImageCacheControl;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public static final fun fromBuilderWithHeaders (Lcom/facebook/imagepipeline/request/ImageRequestBuilder;Lcom/facebook/react/bridge/ReadableMap;)Lcom/facebook/react/modules/fresco/ReactNetworkImageRequest;
public static final fun fromBuilderWithHeaders (Lcom/facebook/imagepipeline/request/ImageRequestBuilder;Lcom/facebook/react/bridge/ReadableMap;Lcom/facebook/react/modules/fresco/ImageCacheControl;)Lcom/facebook/react/modules/fresco/ReactNetworkImageRequest;
}
public final class com/facebook/react/modules/fresco/ReactNetworkImageRequest$Companion {
public final fun fromBuilderWithHeaders (Lcom/facebook/imagepipeline/request/ImageRequestBuilder;Lcom/facebook/react/bridge/ReadableMap;)Lcom/facebook/react/modules/fresco/ReactNetworkImageRequest;
public final fun fromBuilderWithHeaders (Lcom/facebook/imagepipeline/request/ImageRequestBuilder;Lcom/facebook/react/bridge/ReadableMap;Lcom/facebook/react/modules/fresco/ImageCacheControl;)Lcom/facebook/react/modules/fresco/ReactNetworkImageRequest;
public static synthetic fun fromBuilderWithHeaders$default (Lcom/facebook/react/modules/fresco/ReactNetworkImageRequest$Companion;Lcom/facebook/imagepipeline/request/ImageRequestBuilder;Lcom/facebook/react/bridge/ReadableMap;Lcom/facebook/react/modules/fresco/ImageCacheControl;ILjava/lang/Object;)Lcom/facebook/react/modules/fresco/ReactNetworkImageRequest;
}
public final class com/facebook/react/modules/fresco/SystraceRequestListener : com/facebook/imagepipeline/listener/BaseRequestListener {
@@ -6707,8 +6719,10 @@ public class com/facebook/react/views/imagehelper/ImageSource {
public fun <init> (Landroid/content/Context;Ljava/lang/String;)V
public fun <init> (Landroid/content/Context;Ljava/lang/String;D)V
public fun <init> (Landroid/content/Context;Ljava/lang/String;DD)V
public synthetic fun <init> (Landroid/content/Context;Ljava/lang/String;DDILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Landroid/content/Context;Ljava/lang/String;DDLcom/facebook/react/modules/fresco/ImageCacheControl;)V
public synthetic fun <init> (Landroid/content/Context;Ljava/lang/String;DDLcom/facebook/react/modules/fresco/ImageCacheControl;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun equals (Ljava/lang/Object;)Z
public final fun getCacheControl ()Lcom/facebook/react/modules/fresco/ImageCacheControl;
public final fun getSize ()D
public final fun getSource ()Ljava/lang/String;
public static final fun getTransparentBitmapImageSource (Landroid/content/Context;)Lcom/facebook/react/views/imagehelper/ImageSource;
@@ -6959,6 +6973,9 @@ public final class com/facebook/react/views/scroll/ReactHorizontalScrollContaine
public static final field Companion Lcom/facebook/react/views/scroll/ReactHorizontalScrollContainerViewManager$Companion;
public static final field REACT_CLASS Ljava/lang/String;
public fun <init> ()V
public synthetic fun createViewInstance (ILcom/facebook/react/uimanager/ThemedReactContext;Lcom/facebook/react/uimanager/ReactStylesDiffMap;Lcom/facebook/react/uimanager/StateWrapper;)Landroid/view/View;
public synthetic fun createViewInstance (Lcom/facebook/react/uimanager/ThemedReactContext;)Landroid/view/View;
public fun createViewInstance (Lcom/facebook/react/uimanager/ThemedReactContext;)Lcom/facebook/react/views/view/ReactViewGroup;
public fun getName ()Ljava/lang/String;
}
@@ -533,9 +533,7 @@ android {
"-DREACT_BUILD_DIR=$buildDir",
"-DANDROID_STL=c++_shared",
"-DANDROID_TOOLCHAIN=clang",
// Due to https://github.com/android/ndk/issues/1693 we're losing Android
// specific compilation flags. This can be removed once we moved to NDK 25/26
"-DANDROID_USE_LEGACY_TOOLCHAIN_FILE=ON")
"-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON")
targets(
"reactnative",
@@ -41,7 +41,7 @@ if (PROJECT_ROOT_DIR)
endif ()
file(GLOB input_SRC CONFIGURE_DEPENDS
*.cpp
${REACT_ANDROID_DIR}/cmake-utils/default-app-setup/*.cpp
${BUILD_DIR}/generated/autolinking/src/main/jni/*.cpp)
add_library(${CMAKE_PROJECT_NAME} SHARED ${input_SRC})
@@ -228,6 +228,7 @@ android {
"-DHERMES_IS_ANDROID=True",
"-DANDROID_STL=c++_shared",
"-DANDROID_PIE=True",
"-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON",
"-DIMPORT_HERMESC=${File(hermesBuildDir, "ImportHermesc.cmake").toString()}",
"-DJSI_DIR=${jsiDir}",
"-DHERMES_SLOW_DEBUG=False",
@@ -235,10 +236,7 @@ android {
"-DHERMES_RELEASE_VERSION=for RN ${version}",
// We intentionally build Hermes with Intl support only. This is to simplify
// the build setup and to avoid overcomplicating the build-type matrix.
"-DHERMES_ENABLE_INTL=True",
// Due to https://github.com/android/ndk/issues/1693 we're losing Android
// specific compilation flags. This can be removed once we moved to NDK 25/26
"-DANDROID_USE_LEGACY_TOOLCHAIN_FILE=ON")
"-DHERMES_ENABLE_INTL=True")
targets("libhermes")
}
@@ -262,11 +260,6 @@ android {
// This has the (unlucky) side effect of letting AGP call the build
// tasks `configureCMakeRelease` while is actually building the debug flavor.
arguments("-DCMAKE_BUILD_TYPE=Release")
// Adding -O3 to handle the issue here:
// https://github.com/android/ndk/issues/1740#issuecomment-1198438260
// The old NDK toolchain is not passing -O3 correctly for release CMake builds. This is
// fixed in NDK 25 and can be removed once we're there.
cppFlags("-O3")
}
}
}
@@ -330,6 +323,11 @@ afterEvaluate {
tasks.getByName("preBuild").dependsOn(prepareHeadersForPrefab)
}
tasks.withType<JavaCompile>().configureEach {
options.compilerArgs.add("-Xlint:deprecation,unchecked")
options.compilerArgs.add("-Werror")
}
/* Publishing Configuration */
apply(from = "../publish.gradle")
@@ -1,30 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.debug.debugoverlay.model;
import javax.annotation.concurrent.Immutable;
/** Tag for a debug overlay log message. Name must be unique. */
@Immutable
public class DebugOverlayTag {
/** Name of tag. */
public final String name;
/** Description to display in settings. */
public final String description;
/** Color for tag display. */
public final int color;
public DebugOverlayTag(String name, String description, int color) {
this.name = name;
this.description = description;
this.color = color;
}
}
@@ -0,0 +1,21 @@
/*
* 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.debug.debugoverlay.model
/**
* Tag for a debug overlay log message. Name must be unique.
*
* @param name Name of tag.
* @param description Description to display in settings.
* @param color Color for tag display.
*/
public class DebugOverlayTag(
public val name: String,
public val description: String,
public val color: Int,
)
@@ -1,38 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.debug.tags;
import android.graphics.Color;
import com.facebook.debug.debugoverlay.model.DebugOverlayTag;
/** Category for debug overlays. */
public class ReactDebugOverlayTags {
public static final DebugOverlayTag PERFORMANCE =
new DebugOverlayTag("Performance", "Markers for Performance", Color.GREEN);
public static final DebugOverlayTag NAVIGATION =
new DebugOverlayTag("Navigation", "Tag for navigation", Color.rgb(0x9C, 0x27, 0xB0));
public static final DebugOverlayTag RN_CORE =
new DebugOverlayTag("RN Core", "Tag for React Native Core", Color.BLACK);
public static final DebugOverlayTag BRIDGE_CALLS =
new DebugOverlayTag(
"Bridge Calls", "JS to Java calls (warning: this is spammy)", Color.MAGENTA);
public static final DebugOverlayTag NATIVE_MODULE =
new DebugOverlayTag("Native Module", "Native Module init", Color.rgb(0x80, 0x00, 0x80));
public static final DebugOverlayTag UI_MANAGER =
new DebugOverlayTag(
"UI Manager",
"UI Manager View Operations (requires restart\nwarning: this is spammy)",
Color.CYAN);
public static final DebugOverlayTag FABRIC_UI_MANAGER =
new DebugOverlayTag("FabricUIManager", "Fabric UI Manager View Operations", Color.CYAN);
public static final DebugOverlayTag FABRIC_RECONCILER =
new DebugOverlayTag("FabricReconciler", "Reconciler for Fabric", Color.CYAN);
public static final DebugOverlayTag RELAY =
new DebugOverlayTag("Relay", "including prefetching", Color.rgb(0xFF, 0x99, 0x00));
}
@@ -0,0 +1,45 @@
/*
* 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.debug.tags
import android.graphics.Color
import com.facebook.debug.debugoverlay.model.DebugOverlayTag
/** Category for debug overlays. */
public object ReactDebugOverlayTags {
@JvmField
public val PERFORMANCE: DebugOverlayTag =
DebugOverlayTag("Performance", "Markers for Performance", Color.GREEN)
@JvmField
public val NAVIGATION: DebugOverlayTag =
DebugOverlayTag("Navigation", "Tag for navigation", Color.rgb(0x9C, 0x27, 0xB0))
@JvmField
public val RN_CORE: DebugOverlayTag =
DebugOverlayTag("RN Core", "Tag for React Native Core", Color.BLACK)
@JvmField
public val BRIDGE_CALLS: DebugOverlayTag =
DebugOverlayTag("Bridge Calls", "JS to Java calls (warning: this is spammy)", Color.MAGENTA)
@JvmField
public val NATIVE_MODULE: DebugOverlayTag =
DebugOverlayTag("Native Module", "Native Module init", Color.rgb(0x80, 0x00, 0x80))
@JvmField
public val UI_MANAGER: DebugOverlayTag =
DebugOverlayTag(
"UI Manager",
"UI Manager View Operations (requires restart\nwarning: this is spammy)",
Color.CYAN)
@JvmField
public val FABRIC_UI_MANAGER: DebugOverlayTag =
DebugOverlayTag("FabricUIManager", "Fabric UI Manager View Operations", Color.CYAN)
@JvmField
public val FABRIC_RECONCILER: DebugOverlayTag =
DebugOverlayTag("FabricReconciler", "Reconciler for Fabric", Color.CYAN)
@JvmField
public val RELAY: DebugOverlayTag =
DebugOverlayTag("Relay", "including prefetching", Color.rgb(0xFF, 0x99, 0x00))
}
@@ -319,7 +319,11 @@ public class ReactDelegate {
@Nullable
public ReactRootView getReactRootView() {
if (ReactNativeFeatureFlags.enableBridgelessArchitecture()) {
return (ReactRootView) mReactSurface.getView();
if (mReactSurface != null) {
return (ReactRootView) mReactSurface.getView();
} else {
return null;
}
} else {
return mReactRootView;
}
@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.facebook.react.devsupport">
<application>
<!-- This activity will be removed for release builds -->
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity"
android:exported="false"
/>
</application>
</manifest>
@@ -593,6 +593,14 @@ public abstract class DevSupportManagerBase implements DevSupportManager {
// for this manager
resetCurrentContext(null);
}
// If some JNI types (e.g. jni::HybridClass) are used in JSI (e.g. jsi::HostObject), they might
// not be immediately deleted on an app refresh as both Java and JavaScript are
// garbage-collected languages and the memory might float around for a while. For C++
// developers, this will be hard to debug as destructors might be called at a later point, so in
// this case we trigger a Java GC to maybe eagerly collect such objects when the app
// reloads.
System.gc();
}
@Override
@@ -144,7 +144,12 @@ class RedBoxDialogSurfaceDelegate implements SurfaceDelegate {
public void hide() {
// dismiss redbox if exists
if (mDialog != null) {
mDialog.dismiss();
try {
mDialog.dismiss();
} catch (IllegalArgumentException e) {
FLog.e(
ReactConstants.TAG, "RedBoxDialogSurfaceDelegate: error while dismissing dialog: ", e);
}
destroyContentView();
mDialog = null;
}
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<64521c5f18fcaf7092590a2629bb8418>>
* @generated SignedSource<<b7f79cb934f8bf2519439339fc7562d3>>
*/
/**
@@ -14,7 +14,7 @@
* packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js.
*
* To regenerate this code, run the following script from the repo root:
* yarn featureflags-update
* yarn featureflags --update
*/
package com.facebook.react.internal.featureflags
@@ -256,6 +256,12 @@ public object ReactNativeFeatureFlags {
@JvmStatic
public fun traceTurboModulePromiseRejectionsOnAndroid(): Boolean = accessor.traceTurboModulePromiseRejectionsOnAndroid()
/**
* In Bridgeless mode, use the always available javascript error reporting pipeline.
*/
@JvmStatic
public fun useAlwaysAvailableJSErrorHandling(): Boolean = accessor.useAlwaysAvailableJSErrorHandling()
/**
* Should this application enable the Fabric Interop Layer for Android? If yes, the application will behave so that it can accept non-Fabric components and render them on Fabric. This toggle is controlling extra logic such as custom event dispatching that are needed for the Fabric Interop Layer to work correctly.
*/
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<8ed11f58c6671703e4021a91256d315d>>
* @generated SignedSource<<1fa2a94ddb1563952c457e098f0deed7>>
*/
/**
@@ -14,7 +14,7 @@
* packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js.
*
* To regenerate this code, run the following script from the repo root:
* yarn featureflags-update
* yarn featureflags --update
*/
package com.facebook.react.internal.featureflags
@@ -58,6 +58,7 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso
private var loadVectorDrawablesOnImagesCache: Boolean? = null
private var setAndroidLayoutDirectionCache: Boolean? = null
private var traceTurboModulePromiseRejectionsOnAndroidCache: Boolean? = null
private var useAlwaysAvailableJSErrorHandlingCache: Boolean? = null
private var useFabricInteropCache: Boolean? = null
private var useImmediateExecutorInAndroidBridgelessCache: Boolean? = null
private var useNativeViewConfigsInBridgelessModeCache: Boolean? = null
@@ -409,6 +410,15 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso
return cached
}
override fun useAlwaysAvailableJSErrorHandling(): Boolean {
var cached = useAlwaysAvailableJSErrorHandlingCache
if (cached == null) {
cached = ReactNativeFeatureFlagsCxxInterop.useAlwaysAvailableJSErrorHandling()
useAlwaysAvailableJSErrorHandlingCache = cached
}
return cached
}
override fun useFabricInterop(): Boolean {
var cached = useFabricInteropCache
if (cached == null) {
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<6f5d74e7ec13afa88fbd088182f0ba2b>>
* @generated SignedSource<<fe7f93d5f6aeba9007d892074aac5b3a>>
*/
/**
@@ -14,7 +14,7 @@
* packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js.
*
* To regenerate this code, run the following script from the repo root:
* yarn featureflags-update
* yarn featureflags --update
*/
package com.facebook.react.internal.featureflags
@@ -104,6 +104,8 @@ public object ReactNativeFeatureFlagsCxxInterop {
@DoNotStrip @JvmStatic public external fun traceTurboModulePromiseRejectionsOnAndroid(): Boolean
@DoNotStrip @JvmStatic public external fun useAlwaysAvailableJSErrorHandling(): Boolean
@DoNotStrip @JvmStatic public external fun useFabricInterop(): Boolean
@DoNotStrip @JvmStatic public external fun useImmediateExecutorInAndroidBridgeless(): Boolean
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<e1868b062c62107e77fe2897a0681e6e>>
* @generated SignedSource<<09dd6fb517b7b965c5cc554a075e5590>>
*/
/**
@@ -14,7 +14,7 @@
* packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js.
*
* To regenerate this code, run the following script from the repo root:
* yarn featureflags-update
* yarn featureflags --update
*/
package com.facebook.react.internal.featureflags
@@ -35,7 +35,7 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
override fun enableAlignItemsBaselineOnFabricIOS(): Boolean = true
override fun enableAndroidLineHeightCentering(): Boolean = false
override fun enableAndroidLineHeightCentering(): Boolean = true
override fun enableBridgelessArchitecture(): Boolean = false
@@ -99,6 +99,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
override fun traceTurboModulePromiseRejectionsOnAndroid(): Boolean = false
override fun useAlwaysAvailableJSErrorHandling(): Boolean = false
override fun useFabricInterop(): Boolean = false
override fun useImmediateExecutorInAndroidBridgeless(): Boolean = false
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<c6e809489f71a930ad05d83a4ef37cde>>
* @generated SignedSource<<7e78a7ec91d557297f869b964cc91eac>>
*/
/**
@@ -14,7 +14,7 @@
* packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js.
*
* To regenerate this code, run the following script from the repo root:
* yarn featureflags-update
* yarn featureflags --update
*/
package com.facebook.react.internal.featureflags
@@ -62,6 +62,7 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces
private var loadVectorDrawablesOnImagesCache: Boolean? = null
private var setAndroidLayoutDirectionCache: Boolean? = null
private var traceTurboModulePromiseRejectionsOnAndroidCache: Boolean? = null
private var useAlwaysAvailableJSErrorHandlingCache: Boolean? = null
private var useFabricInteropCache: Boolean? = null
private var useImmediateExecutorInAndroidBridgelessCache: Boolean? = null
private var useNativeViewConfigsInBridgelessModeCache: Boolean? = null
@@ -451,6 +452,16 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces
return cached
}
override fun useAlwaysAvailableJSErrorHandling(): Boolean {
var cached = useAlwaysAvailableJSErrorHandlingCache
if (cached == null) {
cached = currentProvider.useAlwaysAvailableJSErrorHandling()
accessedFeatureFlags.add("useAlwaysAvailableJSErrorHandling")
useAlwaysAvailableJSErrorHandlingCache = cached
}
return cached
}
override fun useFabricInterop(): Boolean {
var cached = useFabricInteropCache
if (cached == null) {
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<4c0f737c0dfaa5095d46defe1f67bddf>>
* @generated SignedSource<<0c6450697814b66ae910d66f278213ef>>
*/
/**
@@ -14,7 +14,7 @@
* packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js.
*
* To regenerate this code, run the following script from the repo root:
* yarn featureflags-update
* yarn featureflags --update
*/
package com.facebook.react.internal.featureflags
@@ -99,6 +99,8 @@ public interface ReactNativeFeatureFlagsProvider {
@DoNotStrip public fun traceTurboModulePromiseRejectionsOnAndroid(): Boolean
@DoNotStrip public fun useAlwaysAvailableJSErrorHandling(): Boolean
@DoNotStrip public fun useFabricInterop(): Boolean
@DoNotStrip public fun useImmediateExecutorInAndroidBridgeless(): Boolean
@@ -0,0 +1,25 @@
/*
* 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.modules.fresco
public enum class ImageCacheControl {
/** Uses OkHttp's default cache control policy with no store. */
DEFAULT,
/**
* The data for the URL will be loaded from the originating source. No existing cache data should
* be used to satisfy a URL load request.
*/
RELOAD,
/**
* The existing cache data will be used to satisfy a request, regardless of its age or expiration
* date. If there is no existing data in the cache corresponding to a URL load request, no attempt
* is made to load the data from the originating source, and the load is considered to have
* failed.
*/
ONLY_IF_CACHED,
}
@@ -16,16 +16,19 @@ public class ReactNetworkImageRequest
private constructor(
builder: ImageRequestBuilder,
/** Headers for the request */
internal val headers: ReadableMap?
internal val headers: ReadableMap?,
internal val cacheControl: ImageCacheControl,
) : ImageRequest(builder) {
public companion object {
@JvmStatic
@JvmOverloads
public fun fromBuilderWithHeaders(
builder: ImageRequestBuilder,
headers: ReadableMap?
headers: ReadableMap?,
cacheControl: ImageCacheControl = ImageCacheControl.DEFAULT,
): ReactNetworkImageRequest {
return ReactNetworkImageRequest(builder, headers)
return ReactNetworkImageRequest(builder, headers, cacheControl)
}
}
}
@@ -35,22 +35,30 @@ internal class ReactOkHttpNetworkFetcher(private val okHttpClient: OkHttpClient)
fetchState.submitTime = SystemClock.elapsedRealtime()
val uri = fetchState.uri
var requestHeaders: Map<String, String>? = null
val cacheControlBuilder = CacheControl.Builder().noStore()
if (fetchState.context.imageRequest is ReactNetworkImageRequest) {
val networkImageRequest = fetchState.context.imageRequest as ReactNetworkImageRequest
requestHeaders = getHeaders(networkImageRequest.headers)
when (networkImageRequest.cacheControl) {
ImageCacheControl.RELOAD -> {
cacheControlBuilder.noCache()
}
ImageCacheControl.ONLY_IF_CACHED -> {
cacheControlBuilder.onlyIfCached()
}
ImageCacheControl.DEFAULT -> {
// No-op
}
}
}
val headers = OkHttpCompat.getHeadersFromMap(requestHeaders)
val request =
Request.Builder()
.cacheControl(CacheControl.Builder().noStore().build())
.cacheControl(cacheControlBuilder.build())
.url(uri.toString())
.headers(headers)
.get()
.build()
fetchWithRequest(fetchState, callback, request)
}
private companion object {
private const val TAG = "ReactOkHttpNetworkFetcher"
}
}
@@ -546,8 +546,7 @@ public class ReactHostImpl implements ReactHost {
* Entrypoint to destroy the ReactInstance. If the ReactInstance is reloading, will wait until
* reload is finished, before destroying.
*
* @param reason {@link String} describing why ReactHost is being destroyed (e.g. memmory
* pressure)
* @param reason {@link String} describing why ReactHost is being destroyed (e.g. memory pressure)
* @param ex {@link Exception} exception that caused the trigger to destroy ReactHost (or null)
* This exception will be used to log properly the cause of destroy operation.
* @return A task that completes when React Native gets destroyed.
@@ -143,6 +143,9 @@ public class FabricEventDispatcher implements EventDispatcher, LifecycleEventLis
@Override
public void onHostResume() {
scheduleDispatchOfBatchedEvents();
if (!ReactNativeFeatureFlags.useOptimizedEventBatchingOnAndroid()) {
mCurrentFrameCallback.resume();
}
}
@Override
@@ -216,6 +219,10 @@ public class FabricEventDispatcher implements EventDispatcher, LifecycleEventLis
mShouldStop = true;
}
public void resume() {
mShouldStop = false;
}
public void maybeDispatchBatchedEvents() {
if (!mIsDispatchScheduled) {
mIsDispatchScheduled = true;
@@ -24,6 +24,7 @@ import android.graphics.drawable.Drawable
import android.net.Uri
import com.facebook.common.references.CloseableReference
import com.facebook.common.util.UriUtil
import com.facebook.drawee.backends.pipeline.Fresco
import com.facebook.drawee.controller.AbstractDraweeControllerBuilder
import com.facebook.drawee.controller.ControllerListener
import com.facebook.drawee.controller.ForwardingControllerListener
@@ -40,6 +41,7 @@ import com.facebook.imagepipeline.image.ImageInfo
import com.facebook.imagepipeline.postprocessors.IterativeBoxBlurPostProcessor
import com.facebook.imagepipeline.request.BasePostprocessor
import com.facebook.imagepipeline.request.ImageRequest
import com.facebook.imagepipeline.request.ImageRequest.RequestLevel
import com.facebook.imagepipeline.request.ImageRequestBuilder
import com.facebook.imagepipeline.request.Postprocessor
import com.facebook.react.bridge.ReactContext
@@ -49,6 +51,7 @@ import com.facebook.react.common.annotations.UnstableReactNativeAPI
import com.facebook.react.common.annotations.VisibleForTesting
import com.facebook.react.common.build.ReactBuildConfig
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags
import com.facebook.react.modules.fresco.ImageCacheControl
import com.facebook.react.modules.fresco.ReactNetworkImageRequest
import com.facebook.react.uimanager.BackgroundStyleApplicator
import com.facebook.react.uimanager.LengthPercentage
@@ -268,7 +271,8 @@ public class ReactImageView(
} else if (sources.size() == 1) {
// Optimize for the case where we have just one uri, case in which we don't need the sizes
val source = sources.getMap(0)
var imageSource = ImageSource(context, source.getString("uri"))
val cacheControl = computeCacheControl(source.getString("cache"))
var imageSource = ImageSource(context, source.getString("uri"), cacheControl = cacheControl)
if (Uri.EMPTY == imageSource.uri) {
warnImageSource(source.getString("uri"))
imageSource = getTransparentBitmapImageSource(context)
@@ -277,12 +281,14 @@ public class ReactImageView(
} else {
for (idx in 0 until sources.size()) {
val source = sources.getMap(idx)
val cacheControl = computeCacheControl(source.getString("cache"))
var imageSource =
ImageSource(
context,
source.getString("uri"),
source.getDouble("width"),
source.getDouble("height"))
source.getDouble("height"),
cacheControl)
if (Uri.EMPTY == imageSource.uri) {
warnImageSource(source.getString("uri"))
imageSource = getTransparentBitmapImageSource(context)
@@ -301,6 +307,23 @@ public class ReactImageView(
isDirty = true
}
private fun computeCacheControl(cacheControl: String?): ImageCacheControl {
return when (cacheControl) {
null,
"default" -> ImageCacheControl.DEFAULT
"reload" -> ImageCacheControl.RELOAD
"only-if-cached" -> ImageCacheControl.ONLY_IF_CACHED
else -> ImageCacheControl.DEFAULT
}
}
private fun computeRequestLevel(cacheControl: ImageCacheControl): RequestLevel {
return when (cacheControl) {
ImageCacheControl.ONLY_IF_CACHED -> RequestLevel.DISK_CACHE
else -> RequestLevel.FULL_FETCH
}
}
public fun setDefaultSource(name: String?) {
val newDefaultDrawable = instance.getResourceDrawable(context, name)
if (defaultImageDrawable != newDefaultDrawable) {
@@ -409,7 +432,10 @@ public class ReactImageView(
}
private fun maybeUpdateViewFromRequest(doResize: Boolean) {
val uri = this.imageSource?.uri ?: return
val imageSource = this.imageSource ?: return
val uri = imageSource.uri
val cacheControl = imageSource.cacheControl
val requestLevel = computeRequestLevel(cacheControl)
val postprocessorList = mutableListOf<Postprocessor>()
iterativeBoxBlurPostProcessor?.let { postprocessorList.add(it) }
@@ -418,19 +444,25 @@ public class ReactImageView(
val resizeOptions = if (doResize) resizeOptions else null
if (cacheControl == ImageCacheControl.RELOAD) {
val imagePipeline = Fresco.getImagePipeline()
imagePipeline.evictFromCache(uri)
}
val imageRequestBuilder =
ImageRequestBuilder.newBuilderWithSource(uri)
.setPostprocessor(postprocessor)
.setResizeOptions(resizeOptions)
.setAutoRotateEnabled(true)
.setProgressiveRenderingEnabled(progressiveRenderingEnabled)
.setLowestPermittedRequestLevel(requestLevel)
if (resizeMethod == ImageResizeMethod.NONE) {
imageRequestBuilder.setDownsampleOverride(DownsampleMode.NEVER)
}
val imageRequest: ImageRequest =
ReactNetworkImageRequest.fromBuilderWithHeaders(imageRequestBuilder, headers)
ReactNetworkImageRequest.fromBuilderWithHeaders(imageRequestBuilder, headers, cacheControl)
globalImageLoadListener?.onLoadAttempt(uri)
@@ -9,6 +9,7 @@ package com.facebook.react.views.imagehelper
import android.content.Context
import android.net.Uri
import com.facebook.react.modules.fresco.ImageCacheControl
import java.util.Objects
/** Class describing an image source (network URI or resource) and size. */
@@ -19,7 +20,8 @@ constructor(
/** Get the source of this image, as it was passed to the constructor. */
public val source: String?,
width: Double = 0.0,
height: Double = 0.0
height: Double = 0.0,
public val cacheControl: ImageCacheControl = ImageCacheControl.DEFAULT,
) {
/** Get the URI for this image - can be either a parsed network URI or a resource URI. */
@@ -45,10 +47,11 @@ constructor(
return java.lang.Double.compare(that.size, size) == 0 &&
isResource == that.isResource &&
uri == that.uri &&
source == that.source
source == that.source &&
cacheControl == that.cacheControl
}
override fun hashCode(): Int = Objects.hash(uri, source, size, isResource)
override fun hashCode(): Int = Objects.hash(uri, source, size, isResource, cacheControl)
private fun computeUri(context: Context): Uri =
try {
@@ -70,6 +73,6 @@ constructor(
@JvmStatic
public fun getTransparentBitmapImageSource(context: Context): ImageSource =
ImageSource(context, TRANSPARENT_BITMAP_URI)
ImageSource(context, TRANSPARENT_BITMAP_URI, cacheControl = ImageCacheControl.DEFAULT)
}
}
@@ -8,6 +8,7 @@
package com.facebook.react.views.imagehelper
import com.facebook.imagepipeline.core.ImagePipelineFactory
import com.facebook.react.modules.fresco.ImageCacheControl
/** Helper class for dealing with multisource images. */
public object MultiSourceHelper {
@@ -62,7 +63,10 @@ public object MultiSourceHelper {
best = source
}
if (precision < bestCachePrecision &&
source.cacheControl != ImageCacheControl.RELOAD &&
(imagePipeline.isInBitmapMemoryCache(source.uri) ||
// TODO: T206445115 isInDiskCacheSync is a blocking operation, we should move this to
// a separate thread
imagePipeline.isInDiskCacheSync(source.uri))) {
bestCachePrecision = precision
bestCached = source
@@ -300,7 +300,14 @@ public class ReactModalHostView(context: ThemedReactContext) :
* changed. This has the pleasant side-effect of us not having to preface all Modals with "top:
* statusBarHeight", since that margin will be included in the FrameLayout.
*/
get() = FrameLayout(context).apply { addView(dialogRootViewGroup) }
get() =
FrameLayout(context).apply {
addView(dialogRootViewGroup)
if (!statusBarTranslucent) {
// this is needed to prevent content hiding behind systems bars < API 30
this.fitsSystemWindows = true
}
}
/**
* updateProperties will update the properties that do not require us to recreate the dialog
@@ -0,0 +1,46 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.react.views.scroll
import android.content.Context
import com.facebook.react.modules.i18nmanager.I18nUtil
import com.facebook.react.views.view.ReactViewGroup
/**
* Used by legacy/Paper renderer to perform offsetting of scroll content when the app-wide layout
* direction is RTL. Contextually set layout direction is not respected by legacy renderer.
*/
internal class ReactHorizontalScrollContainerLegacyView(context: Context) :
ReactViewGroup(context) {
private val isRTL: Boolean = I18nUtil.instance.isRTL(context)
override fun setRemoveClippedSubviews(removeClippedSubviews: Boolean) {
// removeClippedSubviews logic may read metrics before the offsetting we do in onLayout() and is
// such unsafe
if (isRTL) {
super.setRemoveClippedSubviews(false)
return
}
super.setRemoveClippedSubviews(removeClippedSubviews)
}
protected override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
if (isRTL) {
// When the layout direction is RTL, we expect Yoga to give us a layout
// that extends off the screen to the left so we re-center it with left=0
val newLeft = 0
val width = right - left
val newRight = newLeft + width
setLeft(newLeft)
setTop(top)
setRight(newRight)
setBottom(bottom)
}
}
}
@@ -8,6 +8,12 @@
package com.facebook.react.views.scroll
import com.facebook.react.module.annotations.ReactModule
import com.facebook.react.uimanager.ReactStylesDiffMap
import com.facebook.react.uimanager.StateWrapper
import com.facebook.react.uimanager.ThemedReactContext
import com.facebook.react.uimanager.common.UIManagerType
import com.facebook.react.uimanager.common.ViewUtil
import com.facebook.react.views.view.ReactViewGroup
import com.facebook.react.views.view.ReactViewManager
/** View manager for {@link ReactHorizontalScrollContainerView} components. */
@@ -15,7 +21,28 @@ import com.facebook.react.views.view.ReactViewManager
public class ReactHorizontalScrollContainerViewManager : ReactViewManager() {
override public fun getName(): String = REACT_CLASS
protected override fun createViewInstance(
reactTag: Int,
context: ThemedReactContext,
initialProps: ReactStylesDiffMap?,
stateWrapper: StateWrapper?
): ReactViewGroup {
check(uiManagerType == null)
uiManagerType = ViewUtil.getUIManagerType(reactTag)
val view = super.createViewInstance(reactTag, context, initialProps, stateWrapper)
uiManagerType = null
return view
}
public override fun createViewInstance(context: ThemedReactContext): ReactViewGroup {
return when (checkNotNull(uiManagerType)) {
UIManagerType.FABRIC -> ReactViewGroup(context)
else -> ReactHorizontalScrollContainerLegacyView(context)
}
}
public companion object {
public const val REACT_CLASS: String = "AndroidHorizontalScrollContentView"
private @UIManagerType var uiManagerType: Int? = null
}
}
@@ -21,6 +21,7 @@ import com.facebook.infer.annotation.Assertions;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.common.ReactConstants;
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags;
import com.facebook.react.uimanager.IllegalViewOperationException;
import com.facebook.react.uimanager.LayoutShadowNode;
import com.facebook.react.uimanager.NativeViewHierarchyOptimizer;
@@ -34,6 +35,7 @@ import com.facebook.react.views.text.internal.ReactTextInlineImageShadowNode;
import com.facebook.react.views.text.internal.span.CustomLetterSpacingSpan;
import com.facebook.react.views.text.internal.span.CustomLineHeightSpan;
import com.facebook.react.views.text.internal.span.CustomStyleSpan;
import com.facebook.react.views.text.internal.span.LegacyLineHeightSpan;
import com.facebook.react.views.text.internal.span.ReactAbsoluteSizeSpan;
import com.facebook.react.views.text.internal.span.ReactBackgroundColorSpan;
import com.facebook.react.views.text.internal.span.ReactClickableSpan;
@@ -229,7 +231,11 @@ public abstract class ReactBaseTextShadowNode extends LayoutShadowNode {
if (!Float.isNaN(effectiveLineHeight)
&& (parentTextAttributes == null
|| parentTextAttributes.getEffectiveLineHeight() != effectiveLineHeight)) {
ops.add(new SetSpanOperation(start, end, new CustomLineHeightSpan(effectiveLineHeight)));
if (ReactNativeFeatureFlags.enableAndroidLineHeightCentering()) {
ops.add(new SetSpanOperation(start, end, new CustomLineHeightSpan(effectiveLineHeight)));
} else {
ops.add(new SetSpanOperation(start, end, new LegacyLineHeightSpan(effectiveLineHeight)));
}
}
ops.add(new SetSpanOperation(start, end, new ReactTagSpan(textShadowNode.getReactTag())));
}
@@ -270,6 +270,10 @@ public class ReactTextShadowNode extends ReactBaseTextShadowNode {
.setBreakStrategy(mTextBreakStrategy)
.setHyphenationFrequency(mHyphenationFrequency);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
builder.setJustificationMode(mJustificationMode);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
builder.setUseLineSpacingFromFallbacks(true);
}
@@ -380,8 +380,9 @@ public class ReactTextView extends AppCompatTextView implements ReactCompoundVie
getBreakStrategy(),
getHyphenationFrequency(),
// always passing ALIGN_NORMAL here should be fine, since this method doesn't depend on
// how exacly lines are aligned, just their width
// how exactly lines are aligned, just their width
Layout.Alignment.ALIGN_NORMAL,
(Build.VERSION.SDK_INT < Build.VERSION_CODES.O) ? -1 : getJustificationMode(),
getPaint());
setText(getSpanned());
}
@@ -32,12 +32,14 @@ import com.facebook.react.bridge.WritableArray;
import com.facebook.react.common.ReactConstants;
import com.facebook.react.common.build.ReactBuildConfig;
import com.facebook.react.common.mapbuffer.MapBuffer;
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags;
import com.facebook.react.uimanager.PixelUtil;
import com.facebook.react.uimanager.ReactAccessibilityDelegate.AccessibilityRole;
import com.facebook.react.uimanager.ReactAccessibilityDelegate.Role;
import com.facebook.react.views.text.internal.span.CustomLetterSpacingSpan;
import com.facebook.react.views.text.internal.span.CustomLineHeightSpan;
import com.facebook.react.views.text.internal.span.CustomStyleSpan;
import com.facebook.react.views.text.internal.span.LegacyLineHeightSpan;
import com.facebook.react.views.text.internal.span.ReactAbsoluteSizeSpan;
import com.facebook.react.views.text.internal.span.ReactBackgroundColorSpan;
import com.facebook.react.views.text.internal.span.ReactClickableSpan;
@@ -146,13 +148,41 @@ public class TextLayoutManager {
== LayoutDirection.RTL;
}
private static Layout.Alignment getTextAlignment(MapBuffer attributedString, Spannable spanned) {
@Nullable
private static String getTextAlignmentAttr(MapBuffer attributedString) {
// TODO: Don't read AS_KEY_FRAGMENTS, which may be expensive, and is not present when using
// cached Spannable
if (!attributedString.contains(AS_KEY_FRAGMENTS)) {
return Layout.Alignment.ALIGN_NORMAL;
return null;
}
MapBuffer fragments = attributedString.getMapBuffer(AS_KEY_FRAGMENTS);
if (fragments.getCount() != 0) {
MapBuffer fragment = fragments.getMapBuffer(0);
MapBuffer textAttributes = fragment.getMapBuffer(FR_KEY_TEXT_ATTRIBUTES);
if (textAttributes.contains(TextAttributeProps.TA_KEY_ALIGNMENT)) {
return textAttributes.getString(TextAttributeProps.TA_KEY_ALIGNMENT);
}
}
return null;
}
private static int getTextJustificationMode(@Nullable String alignmentAttr) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
return -1;
}
if (alignmentAttr != null && alignmentAttr.equals("justified")) {
return Layout.JUSTIFICATION_MODE_INTER_WORD;
}
return Layout.JUSTIFICATION_MODE_NONE;
}
private static Layout.Alignment getTextAlignment(
MapBuffer attributedString, Spannable spanned, @Nullable String alignmentAttr) {
// Android will align text based on the script, so normal and opposite alignment needs to be
// swapped when the directions of paragraph and script don't match.
// I.e. paragraph is LTR but script is RTL, text needs to be aligned to the left, which means
@@ -165,23 +195,15 @@ public class TextLayoutManager {
Layout.Alignment alignment =
swapNormalAndOpposite ? Layout.Alignment.ALIGN_OPPOSITE : Layout.Alignment.ALIGN_NORMAL;
MapBuffer fragments = attributedString.getMapBuffer(AS_KEY_FRAGMENTS);
if (fragments.getCount() != 0) {
MapBuffer fragment = fragments.getMapBuffer(0);
MapBuffer textAttributes = fragment.getMapBuffer(FR_KEY_TEXT_ATTRIBUTES);
if (alignmentAttr == null) {
return alignment;
}
if (textAttributes.contains(TextAttributeProps.TA_KEY_ALIGNMENT)) {
String alignmentAttr = textAttributes.getString(TextAttributeProps.TA_KEY_ALIGNMENT);
if (alignmentAttr.equals("center")) {
alignment = Layout.Alignment.ALIGN_CENTER;
} else if (alignmentAttr.equals("right")) {
alignment =
swapNormalAndOpposite
? Layout.Alignment.ALIGN_NORMAL
: Layout.Alignment.ALIGN_OPPOSITE;
}
}
if (alignmentAttr.equals("center")) {
alignment = Layout.Alignment.ALIGN_CENTER;
} else if (alignmentAttr.equals("right")) {
alignment =
swapNormalAndOpposite ? Layout.Alignment.ALIGN_NORMAL : Layout.Alignment.ALIGN_OPPOSITE;
}
return alignment;
@@ -190,7 +212,8 @@ public class TextLayoutManager {
public static int getTextGravity(
MapBuffer attributedString, Spannable spanned, int defaultValue) {
int gravity = defaultValue;
Layout.Alignment alignment = getTextAlignment(attributedString, spanned);
@Nullable String alignmentAttr = getTextAlignmentAttr(attributedString);
Layout.Alignment alignment = getTextAlignment(attributedString, spanned, alignmentAttr);
// depending on whether the script is LTR or RTL, ALIGN_NORMAL and ALIGN_OPPOSITE may mean
// different things
@@ -296,9 +319,15 @@ public class TextLayoutManager {
textAttributes.mTextShadowColor)));
}
if (!Float.isNaN(textAttributes.getEffectiveLineHeight())) {
ops.add(
new SetSpanOperation(
start, end, new CustomLineHeightSpan(textAttributes.getEffectiveLineHeight())));
if (ReactNativeFeatureFlags.enableAndroidLineHeightCentering()) {
ops.add(
new SetSpanOperation(
start, end, new CustomLineHeightSpan(textAttributes.getEffectiveLineHeight())));
} else {
ops.add(
new SetSpanOperation(
start, end, new LegacyLineHeightSpan(textAttributes.getEffectiveLineHeight())));
}
}
ops.add(new SetSpanOperation(start, end, new ReactTagSpan(reactTag)));
@@ -363,6 +392,7 @@ public class TextLayoutManager {
int textBreakStrategy,
int hyphenationFrequency,
Layout.Alignment alignment,
int justificationMode,
TextPaint paint) {
Layout layout;
@@ -382,7 +412,7 @@ public class TextLayoutManager {
}
int hintWidth = (int) Math.ceil(desiredWidth);
layout =
StaticLayout.Builder builder =
StaticLayout.Builder.obtain(text, 0, spanLength, paint, hintWidth)
.setAlignment(alignment)
.setLineSpacing(0.f, 1.f)
@@ -390,8 +420,13 @@ public class TextLayoutManager {
.setBreakStrategy(textBreakStrategy)
.setHyphenationFrequency(hyphenationFrequency)
.setTextDirection(
isScriptRTL ? TextDirectionHeuristics.RTL : TextDirectionHeuristics.LTR)
.build();
isScriptRTL ? TextDirectionHeuristics.RTL : TextDirectionHeuristics.LTR);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
builder.setUseLineSpacingFromFallbacks(true);
}
layout = builder.build();
} else if (boring != null && (unconstrainedWidth || boring.width <= width)) {
int boringLayoutWidth = boring.width;
@@ -420,6 +455,10 @@ public class TextLayoutManager {
.setTextDirection(
isScriptRTL ? TextDirectionHeuristics.RTL : TextDirectionHeuristics.LTR);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
builder.setJustificationMode(justificationMode);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
builder.setUseLineSpacingFromFallbacks(true);
}
@@ -506,7 +545,9 @@ public class TextLayoutManager {
? paragraphAttributes.getInt(PA_KEY_MAX_NUMBER_OF_LINES)
: ReactConstants.UNSET;
Layout.Alignment alignment = getTextAlignment(attributedString, text);
@Nullable String alignmentAttr = getTextAlignmentAttr(attributedString);
Layout.Alignment alignment = getTextAlignment(attributedString, text, alignmentAttr);
int justificationMode = getTextJustificationMode(alignmentAttr);
if (adjustFontSizeToFit) {
double minimumFontSize =
@@ -526,6 +567,7 @@ public class TextLayoutManager {
textBreakStrategy,
hyphenationFrequency,
alignment,
justificationMode,
paint);
}
@@ -538,6 +580,7 @@ public class TextLayoutManager {
textBreakStrategy,
hyphenationFrequency,
alignment,
justificationMode,
paint);
}
@@ -553,6 +596,7 @@ public class TextLayoutManager {
int textBreakStrategy,
int hyphenationFrequency,
Layout.Alignment alignment,
int justificationMode,
TextPaint paint) {
BoringLayout.Metrics boring = BoringLayout.isBoring(text, paint);
Layout layout =
@@ -565,6 +609,7 @@ public class TextLayoutManager {
textBreakStrategy,
hyphenationFrequency,
alignment,
justificationMode,
paint);
// Minimum font size is 4pts to match the iOS implementation.
@@ -613,6 +658,7 @@ public class TextLayoutManager {
textBreakStrategy,
hyphenationFrequency,
alignment,
justificationMode,
paint);
}
}
@@ -9,105 +9,48 @@ package com.facebook.react.views.text.internal.span
import android.graphics.Paint.FontMetricsInt
import android.text.style.LineHeightSpan
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags
import kotlin.math.ceil
import kotlin.math.floor
import kotlin.math.min
/**
* We use a custom [LineHeightSpan], because `lineSpacingExtra` is broken. Details here:
* https://github.com/facebook/react-native/issues/7546
* Implements a [LineHeightSpan] which follows web-like behavior for line height, unlike
* LineHeightSpan.Standard which only effects space between the baselines of adjacent line boxes
* (does not impact space before the first line or after the last).
*/
public class CustomLineHeightSpan(height: Float) : LineHeightSpan, ReactSpan {
public val lineHeight: Int = ceil(height.toDouble()).toInt()
private fun chooseCenteredHeight(fm: FontMetricsInt) {
if (fm.descent > lineHeight) {
// Show as much descent as possible
fm.descent = lineHeight
fm.bottom = 0
fm.top = 0
fm.ascent = 0
} else if (-fm.ascent + fm.descent > lineHeight) {
// Calculate the amount we are over, and split the adjustment between descent and ascent
val difference = -(lineHeight + fm.ascent - fm.descent) / 2
val remainder = difference % 2
fm.ascent = fm.ascent + difference
fm.descent = fm.descent - difference - remainder
fm.top = fm.ascent
fm.bottom = fm.descent
} else if (-fm.top + fm.bottom > lineHeight) {
// Calculate the amount we are over, and split the adjustment between top and bottom
val excess = ((-fm.top + fm.bottom) - lineHeight) / 2
fm.top += excess
fm.bottom -= excess
} else {
// Show proportionally additional ascent / top & descent / bottom
val additional = lineHeight - (-fm.top + fm.bottom)
// Round up for the negative values and down for the positive values (arbitrary choice)
// So that bottom - top equals additional even if it's an odd number.
val top = (fm.top - ceil(additional / 2.0f)).toInt()
val bottom = (fm.bottom + floor(additional / 2.0f)).toInt()
fm.top = top
fm.ascent = top
fm.descent = bottom
fm.bottom = bottom
}
}
private fun chooseOriginalHeight(fm: FontMetricsInt) {
// This is more complicated that I wanted it to be. You can find a good explanation of what the
// FontMetrics mean here: http://stackoverflow.com/questions/27631736.
// The general solution is that if there's not enough height to show the full line height, we
// will prioritize in this order: descent, ascent, bottom, top
if (fm.descent > lineHeight) {
// Show as much descent as possible
fm.descent = min(lineHeight.toDouble(), fm.descent.toDouble()).toInt()
fm.bottom = fm.descent
fm.ascent = 0
fm.top = fm.ascent
} else if (-fm.ascent + fm.descent > lineHeight) {
// Show all descent, and as much ascent as possible
fm.bottom = fm.descent
fm.ascent = -lineHeight + fm.descent
fm.top = fm.ascent
} else if (-fm.ascent + fm.bottom > lineHeight) {
// Show all ascent, descent, as much bottom as possible
fm.top = fm.ascent
fm.bottom = fm.ascent + lineHeight
} else if (-fm.top + fm.bottom > lineHeight) {
// Show all ascent, descent, bottom, as much top as possible
fm.top = fm.bottom - lineHeight
} else {
// Show proportionally additional ascent / top & descent / bottom
val additional = lineHeight - (-fm.top + fm.bottom)
// Round up for the negative values and down for the positive values (arbitrary choice)
// So that bottom - top equals additional even if it's an odd number.
val top = (fm.top - ceil(additional / 2.0f)).toInt()
val bottom = (fm.bottom + floor(additional / 2.0f)).toInt()
fm.top = top
fm.ascent = top
fm.descent = bottom
fm.bottom = bottom
}
}
public override fun chooseHeight(
text: CharSequence?,
text: CharSequence,
start: Int,
end: Int,
spanstartv: Int,
v: Int,
fm: FontMetricsInt,
) {
if (ReactNativeFeatureFlags.enableAndroidLineHeightCentering()) chooseCenteredHeight(fm)
else chooseOriginalHeight(fm)
// https://www.w3.org/TR/css-inline-3/#inline-height
// When its computed line-height is not normal, its layout bounds are derived solely from
// metrics of its first available font (ignoring glyphs from other fonts), and leading is used
// to adjust the effective A and D to add up to the used line-height. Calculate the leading L as
// L = line-height - (A + D). Half the leading (its half-leading) is added above A of the first
// available font, and the other half below D of the first available font, giving an effective
// ascent above the baseline of A = A + L/2, and an effective descent of D = D + L/2. However,
// if line-fit-edge is not leading and this is not the root inline box, if the half-leading is
// positive, treat it as zero. The layout bounds exactly encloses this effective A and D.
val leading = lineHeight - ((-fm.ascent) + fm.descent)
fm.ascent -= ceil(leading / 2.0f).toInt()
fm.descent += floor(leading / 2.0f).toInt()
// The top of the first line, and the bottom of the last line, may influence bounds of the
// paragraph, so we match them to the text ascent/descent. It is otherwise desirable to allow
// line boxes to overlap (to allow too large glyphs to be drawn outside them), so we do not
// adjust the top/bottom of interior line-boxes.
if (start == 0) {
fm.top = fm.ascent
}
if (end == text.length) {
fm.bottom = fm.descent
}
}
}
@@ -0,0 +1,69 @@
/*
* 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.views.text.internal.span
import android.graphics.Paint.FontMetricsInt
import android.text.style.LineHeightSpan
import kotlin.math.ceil
import kotlin.math.floor
import kotlin.math.min
/**
* We use a custom [LineHeightSpan], because `lineSpacingExtra` is broken. Details here:
* https://github.com/facebook/react-native/issues/7546
*/
public class LegacyLineHeightSpan(height: Float) : LineHeightSpan, ReactSpan {
public val lineHeight: Int = ceil(height.toDouble()).toInt()
public override fun chooseHeight(
text: CharSequence?,
start: Int,
end: Int,
spanstartv: Int,
v: Int,
fm: FontMetricsInt,
) {
// This is more complicated that I wanted it to be. You can find a good explanation of what the
// FontMetrics mean here: http://stackoverflow.com/questions/27631736.
// The general solution is that if there's not enough height to show the full line height, we
// will prioritize in this order: descent, ascent, bottom, top
if (fm.descent > lineHeight) {
// Show as much descent as possible
fm.descent = min(lineHeight.toDouble(), fm.descent.toDouble()).toInt()
fm.bottom = fm.descent
fm.ascent = 0
fm.top = fm.ascent
} else if (-fm.ascent + fm.descent > lineHeight) {
// Show all descent, and as much ascent as possible
fm.bottom = fm.descent
fm.ascent = -lineHeight + fm.descent
fm.top = fm.ascent
} else if (-fm.ascent + fm.bottom > lineHeight) {
// Show all ascent, descent, as much bottom as possible
fm.top = fm.ascent
fm.bottom = fm.ascent + lineHeight
} else if (-fm.top + fm.bottom > lineHeight) {
// Show all ascent, descent, bottom, as much top as possible
fm.top = fm.bottom - lineHeight
} else {
// Show proportionally additional ascent / top & descent / bottom
val additional = lineHeight - (-fm.top + fm.bottom)
// Round up for the negative values and down for the positive values (arbitrary choice)
// So that bottom - top equals additional even if it's an odd number.
val top = (fm.top - ceil(additional / 2.0f)).toInt()
val bottom = (fm.bottom + floor(additional / 2.0f)).toInt()
fm.top = top
fm.ascent = top
fm.descent = bottom
fm.bottom = bottom
}
}
}
@@ -50,6 +50,7 @@ import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactSoftExceptionLogger;
import com.facebook.react.common.ReactConstants;
import com.facebook.react.common.build.ReactBuildConfig;
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags;
import com.facebook.react.uimanager.BackgroundStyleApplicator;
import com.facebook.react.uimanager.LengthPercentage;
import com.facebook.react.uimanager.LengthPercentageType;
@@ -71,6 +72,7 @@ import com.facebook.react.views.text.TextLayoutManager;
import com.facebook.react.views.text.internal.span.CustomLetterSpacingSpan;
import com.facebook.react.views.text.internal.span.CustomLineHeightSpan;
import com.facebook.react.views.text.internal.span.CustomStyleSpan;
import com.facebook.react.views.text.internal.span.LegacyLineHeightSpan;
import com.facebook.react.views.text.internal.span.ReactAbsoluteSizeSpan;
import com.facebook.react.views.text.internal.span.ReactBackgroundColorSpan;
import com.facebook.react.views.text.internal.span.ReactForegroundColorSpan;
@@ -866,7 +868,13 @@ public class ReactEditText extends AppCompatEditText {
float lineHeight = mTextAttributes.getEffectiveLineHeight();
if (!Float.isNaN(lineHeight)) {
workingText.setSpan(new CustomLineHeightSpan(lineHeight), 0, workingText.length(), spanFlags);
if (ReactNativeFeatureFlags.enableAndroidLineHeightCentering()) {
workingText.setSpan(
new CustomLineHeightSpan(lineHeight), 0, workingText.length(), spanFlags);
} else {
workingText.setSpan(
new LegacyLineHeightSpan(lineHeight), 0, workingText.length(), spanFlags);
}
}
}
@@ -495,7 +495,8 @@ void FabricMountingManager::executeMount(
? allocatedViewsIterator->second
: defaultAllocatedViews;
if (allocatedViewsIterator == allocatedViewRegistry_.end()) {
LOG(ERROR) << "Executing commit after surface was stopped!";
LOG(ERROR) << "Executing commit after surface " << surfaceId
<< " was stopped!";
}
for (const auto& mutation : mutations) {
@@ -529,7 +530,7 @@ void FabricMountingManager::executeMount(
(maintainMutationOrder ? cppCommonMountItems : cppDeleteMountItems)
.push_back(CppMountItem::DeleteMountItem(oldChildShadowView));
if (allocatedViewTags.erase(oldChildShadowView.tag) != 1) {
LOG(ERROR) << "Emitting delete for unallocated view. "
LOG(ERROR) << "Emitting delete for unallocated view "
<< oldChildShadowView.tag;
}
break;
@@ -537,7 +538,7 @@ void FabricMountingManager::executeMount(
case ShadowViewMutation::Update: {
if (!isVirtual) {
if (!allocatedViewTags.contains(newChildShadowView.tag)) {
LOG(FATAL) << "Emitting update for unallocated view. "
LOG(ERROR) << "Emitting update for unallocated view "
<< newChildShadowView.tag;
}
@@ -605,7 +606,7 @@ void FabricMountingManager::executeMount(
bool shouldCreateView =
!allocatedViewTags.contains(newChildShadowView.tag);
if (shouldCreateView) {
LOG(ERROR) << "Emitting insert for unallocated view. "
LOG(ERROR) << "Emitting insert for unallocated view "
<< newChildShadowView.tag;
(maintainMutationOrder ? cppCommonMountItems
: cppUpdatePropsMountItems)
@@ -157,6 +157,11 @@ void FabricUIManagerBinding::startSurfaceWithSurfaceHandler(
}
scheduler->registerSurface(surfaceHandler);
auto mountingManager = getMountingManager("startSurfaceWithSurfaceHandler");
if (mountingManager != nullptr) {
mountingManager->onSurfaceStart(surfaceId);
}
surfaceHandler.start();
if (ReactNativeFeatureFlags::enableLayoutAnimationsOnAndroid()) {
@@ -167,14 +172,8 @@ void FabricUIManagerBinding::startSurfaceWithSurfaceHandler(
{
std::unique_lock lock(surfaceHandlerRegistryMutex_);
surfaceHandlerRegistry_.emplace(
surfaceHandler.getSurfaceId(), jni::make_weak(surfaceHandlerBinding));
surfaceId, jni::make_weak(surfaceHandlerBinding));
}
auto mountingManager = getMountingManager("startSurfaceWithSurfaceHandler");
if (!mountingManager) {
return;
}
mountingManager->onSurfaceStart(surfaceHandler.getSurfaceId());
}
// Used by non-bridgeless+Fabric
@@ -206,6 +205,11 @@ void FabricUIManagerBinding::startSurface(
scheduler->registerSurface(surfaceHandler);
auto mountingManager = getMountingManager("startSurface");
if (mountingManager != nullptr) {
mountingManager->onSurfaceStart(surfaceId);
}
surfaceHandler.start();
if (ReactNativeFeatureFlags::enableLayoutAnimationsOnAndroid()) {
@@ -214,17 +218,9 @@ void FabricUIManagerBinding::startSurface(
}
{
SystraceSection s2("FabricUIManagerBinding::startSurface::surfaceId::lock");
std::unique_lock lock(surfaceHandlerRegistryMutex_);
SystraceSection s3("FabricUIManagerBinding::startSurface::surfaceId");
surfaceHandlerRegistry_.emplace(surfaceId, std::move(surfaceHandler));
}
auto mountingManager = getMountingManager("startSurface");
if (!mountingManager) {
return;
}
mountingManager->onSurfaceStart(surfaceId);
}
// Used by non-bridgeless+Fabric
@@ -278,6 +274,11 @@ void FabricUIManagerBinding::startSurfaceWithConstraints(
scheduler->registerSurface(surfaceHandler);
auto mountingManager = getMountingManager("startSurfaceWithConstraints");
if (mountingManager != nullptr) {
mountingManager->onSurfaceStart(surfaceId);
}
surfaceHandler.start();
if (ReactNativeFeatureFlags::enableLayoutAnimationsOnAndroid()) {
@@ -286,19 +287,9 @@ void FabricUIManagerBinding::startSurfaceWithConstraints(
}
{
SystraceSection s2(
"FabricUIManagerBinding::startSurfaceWithConstraints::surfaceId::lock");
std::unique_lock lock(surfaceHandlerRegistryMutex_);
SystraceSection s3(
"FabricUIManagerBinding::startSurfaceWithConstraints::surfaceId");
surfaceHandlerRegistry_.emplace(surfaceId, std::move(surfaceHandler));
}
auto mountingManager = getMountingManager("startSurfaceWithConstraints");
if (!mountingManager) {
return;
}
mountingManager->onSurfaceStart(surfaceId);
}
// Used by non-bridgeless+Fabric
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<e51d7efeeff83508fa5f1a7a46ee859d>>
* @generated SignedSource<<869d22f5b2b35741b171a7257e91f114>>
*/
/**
@@ -14,7 +14,7 @@
* packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js.
*
* To regenerate this code, run the following script from the repo root:
* yarn featureflags-update
* yarn featureflags --update
*/
#include "JReactNativeFeatureFlagsCxxInterop.h"
@@ -267,6 +267,12 @@ class ReactNativeFeatureFlagsProviderHolder
return method(javaProvider_);
}
bool useAlwaysAvailableJSErrorHandling() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("useAlwaysAvailableJSErrorHandling");
return method(javaProvider_);
}
bool useFabricInterop() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("useFabricInterop");
@@ -509,6 +515,11 @@ bool JReactNativeFeatureFlagsCxxInterop::traceTurboModulePromiseRejectionsOnAndr
return ReactNativeFeatureFlags::traceTurboModulePromiseRejectionsOnAndroid();
}
bool JReactNativeFeatureFlagsCxxInterop::useAlwaysAvailableJSErrorHandling(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::useAlwaysAvailableJSErrorHandling();
}
bool JReactNativeFeatureFlagsCxxInterop::useFabricInterop(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::useFabricInterop();
@@ -694,6 +705,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
makeNativeMethod(
"traceTurboModulePromiseRejectionsOnAndroid",
JReactNativeFeatureFlagsCxxInterop::traceTurboModulePromiseRejectionsOnAndroid),
makeNativeMethod(
"useAlwaysAvailableJSErrorHandling",
JReactNativeFeatureFlagsCxxInterop::useAlwaysAvailableJSErrorHandling),
makeNativeMethod(
"useFabricInterop",
JReactNativeFeatureFlagsCxxInterop::useFabricInterop),
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<161df10ef8d0b49dce49c9d0e9354279>>
* @generated SignedSource<<344f9c1de8883c4b72c124dd626f6489>>
*/
/**
@@ -14,7 +14,7 @@
* packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js.
*
* To regenerate this code, run the following script from the repo root:
* yarn featureflags-update
* yarn featureflags --update
*/
#pragma once
@@ -144,6 +144,9 @@ class JReactNativeFeatureFlagsCxxInterop
static bool traceTurboModulePromiseRejectionsOnAndroid(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static bool useAlwaysAvailableJSErrorHandling(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static bool useFabricInterop(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
@@ -1,127 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.react.views.text
import android.graphics.Paint
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlagsForTests
import com.facebook.react.views.text.internal.span.CustomLineHeightSpan
import org.assertj.core.api.Assertions.assertThat
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
@RunWith(RobolectricTestRunner::class)
class CustomLineHeightSpanTest {
@Before
fun setUp() {
ReactNativeFeatureFlagsForTests.setUp()
}
@Test
fun evenLineHeightShouldIncreaseAllMetricsProportionally() {
val customLineHeightSpan = CustomLineHeightSpan(22f)
val fm =
Paint.FontMetricsInt().apply {
top = -10
ascent = -5
descent = 5
bottom = 10
}
customLineHeightSpan.chooseHeight("Hi", 0, 2, 0, 0, fm)
assertThat(fm.top).isEqualTo(-11)
assertThat(fm.ascent).isEqualTo(-11)
assertThat(fm.descent).isEqualTo(11)
assertThat(fm.bottom).isEqualTo(11)
assertThat(fm.bottom - fm.top).isEqualTo(22)
}
@Test
fun oddLineHeightShouldAlsoWork() {
val customLineHeightSpan = CustomLineHeightSpan(23f)
val fm =
Paint.FontMetricsInt().apply {
top = -10
ascent = -5
descent = 5
bottom = 10
}
customLineHeightSpan.chooseHeight("Hi", 0, 2, 0, 0, fm)
assertThat(fm.descent - fm.ascent).isEqualTo(23)
assertThat(fm.bottom - fm.top).isEqualTo(23)
}
@Test
fun shouldReduceTopFirst() {
val customLineHeightSpan = CustomLineHeightSpan(19f)
val fm =
Paint.FontMetricsInt().apply {
top = -10
ascent = -5
descent = 5
bottom = 10
}
customLineHeightSpan.chooseHeight("Hi", 0, 2, 0, 0, fm)
assertThat(fm.top).isEqualTo(-9)
assertThat(fm.ascent).isEqualTo(-5)
assertThat(fm.descent).isEqualTo(5)
assertThat(fm.bottom).isEqualTo(10)
}
@Test
fun shouldReduceBottomSecond() {
val customLineHeightSpan = CustomLineHeightSpan(14f)
val fm =
Paint.FontMetricsInt().apply {
top = -10
ascent = -5
descent = 5
bottom = 10
}
customLineHeightSpan.chooseHeight("Hi", 0, 2, 0, 0, fm)
assertThat(fm.top).isEqualTo(-5)
assertThat(fm.ascent).isEqualTo(-5)
assertThat(fm.descent).isEqualTo(5)
assertThat(fm.bottom).isEqualTo(9)
}
@Test
fun shouldReduceAscentThird() {
val customLineHeightSpan = CustomLineHeightSpan(9f)
val fm =
Paint.FontMetricsInt().apply {
top = -10
ascent = -5
descent = 5
bottom = 10
}
customLineHeightSpan.chooseHeight("Hi", 0, 2, 0, 0, fm)
assertThat(fm.top).isEqualTo(-4)
assertThat(fm.ascent).isEqualTo(-4)
assertThat(fm.descent).isEqualTo(5)
assertThat(fm.bottom).isEqualTo(5)
}
@Test
fun shouldReduceDescentLast() {
val customLineHeightSpan = CustomLineHeightSpan(4f)
val fm =
Paint.FontMetricsInt().apply {
top = -10
ascent = -5
descent = 5
bottom = 10
}
customLineHeightSpan.chooseHeight("Hi", 0, 2, 0, 0, fm)
assertThat(fm.top).isEqualTo(0)
assertThat(fm.ascent).isEqualTo(0)
assertThat(fm.descent).isEqualTo(4)
assertThat(fm.bottom).isEqualTo(4)
}
}
@@ -62,6 +62,22 @@ jsi::Object wrapInErrorIfNecessary(
: Error.callAsConstructor(runtime, value).getObject(runtime);
return error;
}
class SetFalseOnDestruct {
std::shared_ptr<bool> _value;
public:
SetFalseOnDestruct(const SetFalseOnDestruct&) = delete;
SetFalseOnDestruct& operator=(const SetFalseOnDestruct&) = delete;
SetFalseOnDestruct(SetFalseOnDestruct&&) = delete;
SetFalseOnDestruct& operator=(SetFalseOnDestruct&&) = delete;
explicit SetFalseOnDestruct(std::shared_ptr<bool> value)
: _value(std::move(value)) {}
~SetFalseOnDestruct() {
*_value = false;
}
};
} // namespace
namespace facebook::react {
@@ -162,7 +178,7 @@ std::ostream& operator<<(
JsErrorHandler::JsErrorHandler(JsErrorHandler::OnJsError onJsError)
: _onJsError(std::move(onJsError)),
_hasHandledFatalError(false){
_inErrorHandler(std::make_shared<bool>(false)){
};
@@ -171,7 +187,8 @@ JsErrorHandler::~JsErrorHandler() {}
void JsErrorHandler::handleError(
jsi::Runtime& runtime,
jsi::JSError& error,
bool isFatal) {
bool isFatal,
bool logToConsole) {
// TODO: Current error parsing works and is stable. Can investigate using
// REGEX_HERMES to get additional Hermes data, though it requires JS setup
if (_isRuntimeReady) {
@@ -191,13 +208,17 @@ void JsErrorHandler::handleError(
}
}
emitError(runtime, error, isFatal);
handleErrorWithCppPipeline(runtime, error, isFatal, logToConsole);
}
void JsErrorHandler::emitError(
void JsErrorHandler::handleErrorWithCppPipeline(
jsi::Runtime& runtime,
jsi::JSError& error,
bool isFatal) {
bool isFatal,
bool logToConsole) {
*_inErrorHandler = true;
SetFalseOnDestruct temp{_inErrorHandler};
auto message = error.getMessage();
auto errorObj = wrapInErrorIfNecessary(runtime, error.value());
auto componentStackValue = errorObj.getProperty(runtime, "componentStack");
@@ -278,6 +299,14 @@ void JsErrorHandler::emitError(
isTruthy(runtime, errorObj.getProperty(runtime, "isComponentError"));
data.setProperty(runtime, "isComponentError", isComponentError);
if (logToConsole) {
auto console = runtime.global().getPropertyAsObject(runtime, "console");
auto errorFn = console.getPropertyAsFunction(runtime, "error");
auto finalMessage =
jsi::String::createFromUtf8(runtime, parsedError.message);
errorFn.callWithThis(runtime, console, finalMessage);
}
std::shared_ptr<bool> shouldPreventDefault = std::make_shared<bool>(false);
auto preventDefault = jsi::Function::createFromHostFunction(
runtime,
@@ -330,4 +359,8 @@ void JsErrorHandler::notifyOfFatalError() {
_hasHandledFatalError = true;
}
bool JsErrorHandler::inErrorHandler() {
return *_inErrorHandler;
}
} // namespace facebook::react
@@ -43,13 +43,18 @@ class JsErrorHandler {
explicit JsErrorHandler(OnJsError onJsError);
~JsErrorHandler();
void handleError(jsi::Runtime& runtime, jsi::JSError& error, bool isFatal);
void handleError(
jsi::Runtime& runtime,
jsi::JSError& error,
bool isFatal,
bool logToConsole = true);
bool hasHandledFatalError();
void registerErrorListener(
const std::function<void(jsi::Runtime&, jsi::Value)>& listener);
void setRuntimeReady();
bool isRuntimeReady();
void notifyOfFatalError();
bool inErrorHandler();
private:
/**
@@ -60,11 +65,16 @@ class JsErrorHandler {
* teardown get reported properly.
**/
OnJsError _onJsError;
bool _hasHandledFatalError;
bool _hasHandledFatalError{};
bool _isRuntimeReady{};
std::shared_ptr<bool> _inErrorHandler;
std::vector<std::function<void(jsi::Runtime&, jsi::Value)>> _errorListeners;
void emitError(jsi::Runtime& runtime, jsi::JSError& error, bool isFatal);
void handleErrorWithCppPipeline(
jsi::Runtime& runtime,
jsi::JSError& error,
bool isFatal,
bool logToConsole);
};
} // namespace facebook::react
@@ -225,6 +225,13 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation {
return plain_.utf8(s);
}
std::u16string utf16(const String& str) override {
return plain_.utf16(str);
}
std::u16string utf16(const PropNameID& sym) override {
return plain_.utf16(sym);
}
Object createObject() override {
return plain_.createObject();
};
@@ -674,6 +681,15 @@ class WithRuntimeDecorator : public RuntimeDecorator<Plain, Base> {
return RD::utf8(s);
}
std::u16string utf16(const String& str) override {
Around around{with_};
return RD::utf16(str);
}
std::u16string utf16(const PropNameID& sym) override {
Around around{with_};
return RD::utf16(sym);
}
Value createValueFromJsonUtf8(const uint8_t* json, size_t length) override {
Around around{with_};
return RD::createValueFromJsonUtf8(json, length);
@@ -62,6 +62,107 @@ Value callGlobalFunction(Runtime& runtime, const char* name, const Value& arg) {
return f.call(runtime, arg);
}
// Given a sequence of UTF8 encoded bytes, advance the input to past where a
// 32-bit unicode codepoint as been decoded and return the codepoint. If the
// UTF8 encoding is invalid, then return the value with the unicode replacement
// character (U+FFFD). This decoder also relies on zero termination at end of
// the input for bound checks.
// \param input char pointer pointing to the current character
// \return Unicode codepoint
uint32_t decodeUTF8(const char*& input) {
uint32_t ch = (unsigned char)input[0];
if (ch <= 0x7f) {
input += 1;
return ch;
}
uint32_t ret;
constexpr uint32_t replacementCharacter = 0xFFFD;
if ((ch & 0xE0) == 0xC0) {
uint32_t ch1 = (unsigned char)input[1];
if ((ch1 & 0xC0) != 0x80) {
input += 1;
return replacementCharacter;
}
ret = ((ch & 0x1F) << 6) | (ch1 & 0x3F);
input += 2;
if (ret <= 0x7F) {
return replacementCharacter;
}
} else if ((ch & 0xF0) == 0xE0) {
uint32_t ch1 = (unsigned char)input[1];
if ((ch1 & 0x40) != 0 || (ch1 & 0x80) == 0) {
input += 1;
return replacementCharacter;
}
uint32_t ch2 = (unsigned char)input[2];
if ((ch2 & 0x40) != 0 || (ch2 & 0x80) == 0) {
input += 2;
return replacementCharacter;
}
ret = ((ch & 0x0F) << 12) | ((ch1 & 0x3F) << 6) | (ch2 & 0x3F);
input += 3;
if (ret <= 0x7FF) {
return replacementCharacter;
}
} else if ((ch & 0xF8) == 0xF0) {
uint32_t ch1 = (unsigned char)input[1];
if ((ch1 & 0x40) != 0 || (ch1 & 0x80) == 0) {
input += 1;
return replacementCharacter;
}
uint32_t ch2 = (unsigned char)input[2];
if ((ch2 & 0x40) != 0 || (ch2 & 0x80) == 0) {
input += 2;
return replacementCharacter;
}
uint32_t ch3 = (unsigned char)input[3];
if ((ch3 & 0x40) != 0 || (ch3 & 0x80) == 0) {
input += 3;
return replacementCharacter;
}
ret = ((ch & 0x07) << 18) | ((ch1 & 0x3F) << 12) | ((ch2 & 0x3F) << 6) |
(ch3 & 0x3F);
input += 4;
if (ret <= 0xFFFF) {
return replacementCharacter;
}
if (ret > 0x10FFFF) {
return replacementCharacter;
}
} else {
input += 1;
return replacementCharacter;
}
return ret;
}
// Given a valid 32-bit unicode codepoint, encode it as UTF-16 into the output.
void encodeUTF16(std::u16string& out, uint32_t cp) {
if (cp < 0x10000) {
out.push_back((uint16_t)cp);
return;
}
cp -= 0x10000;
uint16_t highSurrogate = 0xD800 + ((cp >> 10) & 0x3FF);
out.push_back(highSurrogate);
uint16_t lowSurrogate = 0xDC00 + (cp & 0x3FF);
out.push_back(lowSurrogate);
}
// Convert the UTF8 encoded string into a UTF16 encoded string. If the
// input is not valid UTF8, the replacement character (U+FFFD) is used to
// represent the invalid sequence.
std::u16string convertUTF8ToUTF16(const std::string& utf8) {
std::u16string ret;
const char* curr = utf8.data();
const char* end = curr + utf8.length();
while (curr < end) {
auto cp = decodeUTF8(curr);
encodeUTF16(ret, cp);
}
return ret;
}
} // namespace
Buffer::~Buffer() = default;
@@ -147,6 +248,16 @@ Value Runtime::createValueFromJsonUtf8(const uint8_t* json, size_t length) {
return parseJson.call(*this, String::createFromUtf8(*this, json, length));
}
std::u16string Runtime::utf16(const PropNameID& sym) {
auto utf8Str = utf8(sym);
return convertUTF8ToUTF16(utf8Str);
}
std::u16string Runtime::utf16(const String& str) {
auto utf8Str = utf8(str);
return convertUTF8ToUTF16(utf8Str);
}
Pointer& Pointer::operator=(Pointer&& other) {
if (ptr_) {
ptr_->invalidate();
@@ -399,6 +399,9 @@ class JSI_EXPORT Runtime {
const jsi::Object& obj,
size_t amount) = 0;
virtual std::u16string utf16(const String& str);
virtual std::u16string utf16(const PropNameID& sym);
// These exist so derived classes can access the private parts of
// Value, Symbol, String, and Object, which are all friends of Runtime.
template <typename T>
@@ -501,6 +504,11 @@ class JSI_EXPORT PropNameID : public Pointer {
return runtime.utf8(*this);
}
/// Copies the data in a PropNameID as utf16 into a C++ string.
std::u16string utf16(Runtime& runtime) const {
return runtime.utf16(*this);
}
static bool compare(
Runtime& runtime,
const jsi::PropNameID& a,
@@ -651,6 +659,11 @@ class JSI_EXPORT String : public Pointer {
return runtime.utf8(*this);
}
/// Copies the data in a JS string as utf16 into a C++ string.
std::u16string utf16(Runtime& runtime) const {
return runtime.utf16(*this);
}
friend class Runtime;
friend class Value;
};
@@ -1576,6 +1576,65 @@ TEST_P(JSITest, UTF8ExceptionTest) {
}
}
TEST_P(JSITest, UTF16Test) {
// This Runtime Decorator is used to test the conversion from UTF-8 to UTF-16
// in the default utf16 method for runtimes that do not provide their own
// utf16 implementation.
class UTF16RD : public RuntimeDecorator<Runtime, Runtime> {
public:
UTF16RD(Runtime& rt) : RuntimeDecorator(rt) {}
std::string utf8(const String&) override {
return utf8Str;
}
std::u16string utf16(const String& str) override {
return Runtime::utf16(str);
}
std::string utf8Str;
};
UTF16RD rd = UTF16RD(rt);
String str = String::createFromUtf8(rd, "placeholder");
rd.utf8Str = "foobar";
EXPECT_EQ(str.utf16(rd), u"foobar");
rd.utf8Str = "你好";
EXPECT_EQ(str.utf16(rd), u"你好");
rd.utf8Str = "👍";
EXPECT_EQ(str.utf16(rd), u"👍");
rd.utf8Str = "foobar👍你好";
EXPECT_EQ(str.utf16(rd), u"foobar👍你好");
// String ended before second byte of the encoding
rd.utf8Str = "\xcf";
EXPECT_EQ(str.utf16(rd), u"\uFFFD");
// Third byte should follow the pattern of 0b10xxxxxx
rd.utf8Str = "\xef\x8f\x29";
EXPECT_EQ(str.utf16(rd), u"\uFFFD\u0029");
// U+2200 should be encoded in 3 bytes as 0xE2 0x88 0x80, not 4 bytes
rd.utf8Str = "\xf0\x82\x88\x80";
EXPECT_EQ(str.utf16(rd), u"\uFFFD");
// Unicode Max Value is U+10FFFF, U+11FFFF is invalid
rd.utf8Str = "\xf4\x9f\xbf\xbf";
EXPECT_EQ(str.utf16(rd), u"\uFFFD");
// Missing the third byte of the 3-byte encoding, followed by 'z'
rd.utf8Str = "\xe1\xa0\x7a";
EXPECT_EQ(str.utf16(rd), u"\uFFFD\u007A");
// First byte is neither ASCII nor a valid continuation byte
rd.utf8Str = "\xea\x7a";
EXPECT_EQ(str.utf16(rd), u"\uFFFD\u007A");
}
INSTANTIATE_TEST_CASE_P(
Runtimes,
JSITest,
@@ -10,9 +10,6 @@
namespace facebook::react {
bool EmptyReactNativeConfig::getBool(const std::string& param) const {
if (param == "react_fabric:enabled_automatic_interop_android") {
return true;
}
return false;
}
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<0b4373e19b66481d17c0a8e81785df23>>
* @generated SignedSource<<f2175cbbe38a66b9aa5c3f0feaa07462>>
*/
/**
@@ -14,7 +14,7 @@
* packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js.
*
* To regenerate this code, run the following script from the repo root:
* yarn featureflags-update
* yarn featureflags --update
*/
#include "ReactNativeFeatureFlags.h"
@@ -178,6 +178,10 @@ bool ReactNativeFeatureFlags::traceTurboModulePromiseRejectionsOnAndroid() {
return getAccessor().traceTurboModulePromiseRejectionsOnAndroid();
}
bool ReactNativeFeatureFlags::useAlwaysAvailableJSErrorHandling() {
return getAccessor().useAlwaysAvailableJSErrorHandling();
}
bool ReactNativeFeatureFlags::useFabricInterop() {
return getAccessor().useFabricInterop();
}

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