Compare commits

..
Author SHA1 Message Date
Simek 6066919eb4 resolve conflict, deduplicate lock again 2025-08-13 20:11:35 +02:00
Rubén NorteandFacebook GitHub Bot d009a02c6c Add benchmark to compare rendering times for View and ViewNativeComponent (#53248)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53248

Changelog: [internal]

This adds a new benchmark that compares the rendering time (only rendering, not committing, mounting, effects, etc.) of `<View>` and `<ViewNativeComponent>`.

Baseline:

| (index) | Task name                                | Latency avg (ns)  | Latency med (ns)   | Throughput avg (ops/s) | Throughput med (ops/s) | Samples |
| ------- | ---------------------------------------- | ----------------- | ------------------ | ---------------------- | ---------------------- | ------- |
| 0       | 'render 100 views (Noop)'                | '333036 ± 0.39%'  | '328452 ± 2393.0'  | '3019 ± 0.18%'         | '3045 ± 22'            | 3003    |
| 1       | 'render 100 views (ViewNativeComponent)' | '1335974 ± 3.45%' | '1228468 ± 7541.5' | '797 ± 0.71%'          | '814 ± 5'              | 1000    |
| 2       | 'render 100 views (View)'                | '2296988 ± 1.60%' | '2170821 ± 12374'  | '449 ± 0.74%'          | '461 ± 3'              | 1000    |

This shows that **`<View>` currently has an overhead of 75% in rendering time**.

I've also tested a modification of `View` such as:

```
component View(...props: ViewProps) {
  return {
    // This tag allows us to uniquely identify this as a React Element
    $$typeof: REACT_ELEMENT_TYPE,
    // Built-in properties that belong on the element
    type: ViewNativeComponent,
    key: undefined,
    // $FlowExpectedError[prop-missing]
    ref: props.ref,
    props,
  };
}
```

This makes `View` basically a no-op component, and the benchmark after this looks like:

| (index) | Task name                                | Latency avg (ns)  | Latency med (ns)  | Throughput avg (ops/s) | Throughput med (ops/s) | Samples |
| ------- | ---------------------------------------- | ----------------- | ----------------- | ---------------------- | ---------------------- | ------- |
| 0       | 'render 100 views (View)'                | '1743010 ± 2.25%' | '1630816 ± 10616' | '600 ± 0.74%'          | '613 ± 4'              | 1000    |
| 1       | 'render 100 views (ViewNativeComponent)' | '1370699 ± 4.04%' | '1242284 ± 14172' | '789 ± 0.74%'          | '805 ± 9'              | 1000    |

This shows that `View`, just for existing as a wrapper component, has an overhead of 31% in rendering time, which means that **the opportunities to reduce the overhead beyond what we already did are limited**.

Reviewed By: rshest

Differential Revision: D80169514

fbshipit-source-id: aa2a1fc3f9d0ee3a60c03dd32555802fa7265251
2025-08-13 10:14:21 -07:00
Rubén NorteandFacebook GitHub Bot e8bf982bac Support overriddenDuration in Fantom benchmarks (#53250)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53250

Changelog: [internal]

This updates the types for Fantom benchmarks to support the new `overriddenDuration` option from `tinybench`.

It also exposes a new method in the benchmark namespace to access the same timestamp used in benchmarks.

Reviewed By: rshest

Differential Revision: D80169515

fbshipit-source-id: 59af197eababbf5b8544ee9f1862b206756dc87d
2025-08-13 10:14:21 -07:00
Rubén NorteandFacebook GitHub Bot c17267ec87 Upgrade tinybench to v4.1.0 (#53249)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53249

Changelog: [internal]

This just upgrades tinybench (used in Fantom benchmarks) to v4.1.0, which contains a feature we need to customize test durations.

Reviewed By: rshest

Differential Revision: D80169516

fbshipit-source-id: 5813b3050843b52d604619a44a5e097e26f54432
2025-08-13 10:14:21 -07:00
SimekandFacebook GitHub Bot 50d5316b1b Workspace: align eslint-plugin-jest with Jest version (#53246)
Summary:
While verifying the lock deduplication changes, I have spotted that `eslint-plugin-jest` package does not match Jest version used within the workspace.

## Changelog:

[INTERNAL][CHANGED] - update `eslint-plugin-jest` package in workspace to align with Jest version used

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

Test Plan: Running `yarn test`, `yarn lint-ci` and `test-typescript` checks does not yield any errors.

Reviewed By: rshest, cortinico

Differential Revision: D80170591

Pulled By: robhogan

fbshipit-source-id: f3ac58bc26cf2d3a34899f8558f872b3df85942d
2025-08-13 09:36:21 -07:00
Mateo GuzmánandFacebook GitHub Bot bc54a06fcb Migrate YogaNative to Kotlin
Summary:
Migrate com.facebook.yoga.YogaNative to Kotlin.

X-link: https://github.com/facebook/yoga/pull/1839

Reviewed By: rshest

Differential Revision: D79897725

Pulled By: cortinico

fbshipit-source-id: 6fc98565368d831b8698464fe26ad47f8fff6a74
2025-08-13 08:56:03 -07:00
riteshshukla04andFacebook GitHub Bot c5956da8c0 Fix: Setting maxLength to 0 in TextInput still allows typing on iOS (#52890)
Summary:
Trying to fix https://github.com/facebook/react-native/issues/52860
## 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
-->
[IOS][FIXED] Setting maxLength to 0 in TextInput still allows typing on iOS

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

Test Plan:
https://github.com/user-attachments/assets/56549e0f-6bbf-461e-815c-794abdee2018

Tested on Android too

Rollback Plan:

Reviewed By: cortinico

Differential Revision: D80095701

Pulled By: cipolleschi

fbshipit-source-id: 5e76f88798e32097e6a619c44ff6240b4f01fc6f
2025-08-13 07:23:30 -07:00
Samuel SuslaandFacebook GitHub Bot 568f59e5b1 use trace section in C++ Animated instead of perfetto (#53223)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53223

changelog: [internal]

remove dependency on perfetto and use TraceSection like we do elsewhere.

Reviewed By: zeyap, rubennorte

Differential Revision: D80087082

fbshipit-source-id: 08d3434985443db9a83189a4dfabc65d6eda8166
2025-08-13 06:52:16 -07:00
Mateo GuzmánandFacebook GitHub Bot 33ca53d9db Migrate YogaConfigFactory to Kotlin
Summary:
Migrate com.facebook.yoga.YogaConfigFactory to Kotlin.

X-link: https://github.com/facebook/yoga/pull/1833

Reviewed By: rshest

Differential Revision: D79897762

Pulled By: cortinico

fbshipit-source-id: 9457b307204f2066a02690f96a88fce6755f915e
2025-08-13 06:46:48 -07:00
Philip HeinserandFacebook GitHub Bot 91e69b5d4c fix crashes on non-UTF8 Info.plist files under local frameworks (#52336)
Summary:
fix: https://github.com/facebook/react-native/issues/52279

## Changelog:

[iOS] [FIXED] - non-UTF8 crashes Info.plist local frameworks

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

Test Plan:
after this change pods install and are working with the new warning:
[!] Failed to read Info.plist at /Users/user/apps/test/ios/promiflash/Frameworks/YouTubeEmbeddedPlayerFramework.framework/Info.plist: invalid byte sequence in UTF-8

Reviewed By: cortinico

Differential Revision: D80096932

Pulled By: cipolleschi

fbshipit-source-id: f60cd67cb99a581d6fbab92422c1adf7b50066eb
2025-08-13 02:51:10 -07:00
Christoph PurrerandFacebook GitHub Bot 9f0d24bb05 Enforce void return type for void return type in JS C++ TM spec (#53214)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53214

Changelog: [General] [Fixed] Enforce void return type for void return type in JS C++ TM spec

Example if you have this spec
```
export interface Spec extends TurboModule {
  +foo: (bar: string) => void;
}
```
We must enforce in C++ that the return type is `void` as e.g.
```
  void foo(jsi::Runtime& rt, const std::string& bar);
```
Right now you can return any type in C++ such as `std::string` which does not make sense

Reviewed By: lenaic

Differential Revision: D79980538

fbshipit-source-id: 9b99ea6b1ac97d1e46cdb9952e83c445ec5503b7
2025-08-12 23:13:16 -07:00
Zeya PengandFacebook GitHub Bot 9f77d421bb make sure to only disable js sync & animate layout when disableFabricCommitInCXXAnimated==false (#53230)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53230

## Changelog:

[Internal] [Changed] - make sure to only disable js sync & animate layout when disableFabricCommitInCXXAnimated==false

Reviewed By: sammy-SC

Differential Revision: D80002015

fbshipit-source-id: 5e6ee4b5908fe8d2ee52b77ca3b78164debc4d59
2025-08-12 14:57:41 -07:00
Alan LeeandFacebook GitHub Bot 1c7925abb0 edit RN change log (#53232)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53232

Remove entry that was reverted for 0.81 release

Changelog: [Internal]

Reviewed By: shwanton, cortinico

Differential Revision: D80108112

fbshipit-source-id: 3176e7e26407ad8c71434b5576c722dc28021d08
2025-08-12 13:41:39 -07:00
Samuel SuslaandFacebook GitHub Bot b44e1839ca fix crash in adjustForMaintainVisibleContentPosition (#53208)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53208

changelog: [internal]

When Fabric View Culling is enabled together with immediate state update, it may lead to a crash inside of `[RCTScrollViewComponentView _adjustForMaintainVisibleContentPosition]`.
When doing immediate state update, we can avoid calling `[RCTScrollViewComponentView _adjustForMaintainVisibleContentPosition]` altogether to avoid the crash.

Reviewed By: lenaic

Differential Revision: D80000362

fbshipit-source-id: 123b70aa31edb14a99bb968648eb8b8aac84afb6
2025-08-12 13:25:16 -07:00
Rubén NorteandFacebook GitHub Bot 4ee326f52c Add documentation for JS memory profiler in Fantom (#53226)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53226

Changelog: [internal]

This adds documentation about how to take JS memory heap snapshots in Fantom.

Reviewed By: lenaic

Differential Revision: D80090283

fbshipit-source-id: 04f66a62aa756d1020b8d8ef6fc0ea7e68341710
2025-08-12 11:08:08 -07:00
Rubén NorteandFacebook GitHub Bot 90804fd088 Add documentation for JS sampling profiler in Fantom (#53227)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53227

Changelog: [internal]

This adds docs for the new JS sampling profiler in Fantom

Reviewed By: lenaic

Differential Revision: D80090284

fbshipit-source-id: 0f7fa498cf141a51ac6fda331522945d42fc494d
2025-08-12 11:08:08 -07:00
Rubén NorteandFacebook GitHub Bot e2035379b6 Add documentation for debugging in Fantom (#53228)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53228

Changelog: [internal]

This adds some documentation about how to debug Fantom tests (C++ and JS).

Reviewed By: lenaic

Differential Revision: D80090286

fbshipit-source-id: 435d2079abfe72e93de0c297347b15dc39b25a89
2025-08-12 11:08:08 -07:00
Rubén NorteandFacebook GitHub Bot 0bf7721862 Use Jest naming for test regex in Fantom docs (#53229)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53229

Changelog: [internal]

Tiny change to align with how Jest refers to this argument in its docs: https://jestjs.io/docs/cli#jest-regexfortestfiles

Reviewed By: lenaic

Differential Revision: D80090285

fbshipit-source-id: 86a4ad75078eb9b7575fca9659cc1a2e678f7a0a
2025-08-12 11:08:08 -07:00
Mateo GuzmánandFacebook GitHub Bot 35d8086881 Migrate DoNotStrip to Kotlin
Summary:
Migrate com.facebook.yoga.annotations.DoNotStrip to Kotlin.

X-link: https://github.com/facebook/yoga/pull/1840

Reviewed By: rshest

Differential Revision: D79897758

Pulled By: cortinico

fbshipit-source-id: 79585e6ab793bd72e04440581d866f7721667db3
2025-08-12 10:54:27 -07:00
Samuel SuslaandFacebook GitHub Bot 65b5a5b25d make glog android only include + declare the dependency on glog (#53224)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53224

changelog: [internal]

glog is only used on Android.

Reviewed By: christophpurrer

Differential Revision: D80085730

fbshipit-source-id: 0dbec7929551f7c16719846c1868b0509b1d519a
2025-08-12 10:30:49 -07:00
Riccardo CipolleschiandFacebook GitHub Bot 27217e8bd6 Initialize props for RCTPullToRefreshViewComponentView (#53231)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53231

The RCTPullToRefreshViewComponentView props are not initialized when the component view is created. this could lead to undefined behaviors and crashes.

This change fixes it.

## Changelog:
[iOS][Fixed] - Properly initialize the RCTPullToRefreshViewComponentView

Reviewed By: sammy-SC

Differential Revision: D80093141

fbshipit-source-id: dac98d56c749b9f5d85338279c8da2a7e5ddb4a3
2025-08-12 10:16:19 -07:00
Mateo GuzmánandFacebook GitHub Bot 7e461003c6 Migrate YogaLayoutType to Kotlin
Summary:
Migrate com.facebook.yoga.YogaLayoutType to Kotlin.

X-link: https://github.com/facebook/yoga/pull/1837

Reviewed By: rshest

Differential Revision: D79897708

Pulled By: cortinico

fbshipit-source-id: e3c8a3cc60f806d151d2be956b26dd98963254a6
2025-08-12 09:49:31 -07:00
Samuel SuslaandFacebook GitHub Bot bd287e8e2c move some C++ Animated headers into internal folder (#52991)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/52991

changelog: [internal]

move internal files only to internal folder in C++ Animated

Reviewed By: rshest

Differential Revision: D79436926

fbshipit-source-id: fb8badefdbf7b54a351e57e457f2b6aaf36dc2a6
2025-08-12 09:32:43 -07:00
Mateo GuzmánandFacebook GitHub Bot db2a9c089c Migrate LayoutPassReason to Kotlin
Summary:
Migrate com.facebook.yoga.LayoutPassReason to Kotlin.

X-link: https://github.com/facebook/yoga/pull/1836

Reviewed By: rshest

Differential Revision: D79897685

Pulled By: cortinico

fbshipit-source-id: 87d2e4b95fbdbfe48d84019e9ffb50deb9286d8c
2025-08-12 09:10:30 -07:00
Mateo GuzmánandFacebook GitHub Bot 40afa75a7c Migrate YogaNodeFactory to Kotlin
Summary:
Migrate com.facebook.yoga.YogaNodeFactory to Kotlin.

X-link: https://github.com/facebook/yoga/pull/1832

Reviewed By: zielinskimz

Differential Revision: D79897733

Pulled By: cortinico

fbshipit-source-id: 3ea4f5635eb8c910719c13d3087356b96b6f0746
2025-08-12 08:57:43 -07:00
Mateo GuzmánandFacebook GitHub Bot 453508ada8 Migrate YogaMeasureOutput to Kotlin
Summary:
Migrate com.facebook.yoga.YogaMeasureOutput to Kotlin.

X-link: https://github.com/facebook/yoga/pull/1842

Reviewed By: rshest

Differential Revision: D79897681

Pulled By: cortinico

fbshipit-source-id: 63280b6aed9bbeeb1e71458a1793c9647dcf0726
2025-08-12 07:55:41 -07:00
Mateo GuzmánandFacebook GitHub Bot 05eddd354e Migrate YogaMeasureFunction to Kotlin
Summary:
Migrate com.facebook.yoga.YogaMeasureFunction to Kotlin.

X-link: https://github.com/facebook/yoga/pull/1835

Reviewed By: mdvacca

Differential Revision: D79897728

Pulled By: cortinico

fbshipit-source-id: 959ae976622838147685cf6088674dce25f5cc99
2025-08-12 07:40:31 -07:00
Ruslan ShestopalyukandFacebook GitHub Bot 641a79dc51 Improve benchmark comparison printout ("slower"->"faster") (#53221)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53221

# Changelog:
[Internal] -

This changes the benchmark test results comparison print the results slightly differently, in particular it now uses the slowest result as a baseline and prints how much faster the other ones are (as opposed to printing "slower" previously).

This arguably brings a more positive vibe when looking into the benchmark results :)

Reviewed By: andrewdacenko

Differential Revision: D80082134

fbshipit-source-id: 7dc9c7c520afe08270d4f5da9031db02261690ba
2025-08-12 06:56:14 -07:00
Nicola CortiandFacebook GitHub Bot f1d014adbb Simplify RNTester Autolinking (#53095)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53095

This change simplifies the RNTesterApplication so that it's looking closer to the template MainApplication file.
In order to do so, I had to create 2 files inside the `metainternal/` folder as those files are
generated as part of the CLI Autolinking

Changelog:
[Internal] [Changed] -

Reviewed By: cipolleschi

Differential Revision: D79722917

fbshipit-source-id: 06852c72ae1e1abed9952b1637515123977bc7b4
2025-08-12 05:49:49 -07:00
Vitali ZaidmanandFacebook GitHub Bot 7bfec89a97 temporary disable perf monitor to fix tests (#53209)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53209

Changelog: Internal

Reviewed By: sammy-SC

Differential Revision: D80000286

fbshipit-source-id: 899cd5e6b193957579e61af65cf8177cd1666473
2025-08-12 05:47:11 -07:00
Rubén NorteandFacebook GitHub Bot 65974e938c Add support for JS debugging in Fantom (#53215)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53215

Changelog: [internal]

This adds a new environment variable to Fantom that allows debugging the JS code in tests.

Usage:

```
FANTOM_DEBUG_JS=1 yarn fantom <test>
```

**Does NOT work in OSS yet**. We need to include a third-party library to send HTTP and WebSocket requests and implement a wrapper on top of it.

Reviewed By: christophpurrer

Differential Revision: D79883372

fbshipit-source-id: d077c373a036033344e61d58274d5cd14028bda4
2025-08-12 05:41:11 -07:00
Rubén NorteandFacebook GitHub Bot 9c201c0f8f Automatically inject debugger statements in tests in preparation for debug mode (#53205)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53205

Changelog: [internal]

This injects a custom Babel transform for Fantom tests that automatically injects `debugger` statements in the generated code. This simplifies debugging by providing a default interruption point in the test setup for the test author to decide what to debug.

This has no effect unless the debugger is opened, which isn't happening yet.

Reviewed By: rshest

Differential Revision: D79996000

fbshipit-source-id: 6153587264d293a067e359edba4f64f41898c506
2025-08-12 05:41:11 -07:00
Rubén NorteandFacebook GitHub Bot 4978385067 Allow custom factories for HTTP and WebSocket clients for DevTools (#53200)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53200

Changelog: [internal]

TSIA. This is necessary for Fantom to use real HTTP and WebSocket connections for DevTools, while still providing stubs for the runtime (the networking and websockets native modules provided to clients).

If there are no specific factories for DevTools provided, we fall back to regular ones (keeping backwards compatibility).

Reviewed By: rshest

Differential Revision: D79806934

fbshipit-source-id: 6d16fa44e11f3c8e304c3c3d31fe952d0ba5811a
2025-08-12 05:41:11 -07:00
Rubén NorteandFacebook GitHub Bot 42db2f8405 Split ReactInstanceConfig.enableDebugging into enableInspector and enableDevMode (#53201)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53201

Changelog: [internal]

This splits the `ReactHost` option `enableDebugging` into more granular options:
- `enableInspector` which enables the connection with the inspector/debugger.
- `enableDevMode` which enables the use of bundles from Metro, reloads, etc.

This allows us to enable the inspector in Fantom without consuming bundles from Metro.

This should be backwards compatible with existing apps.

In the future, we should be able to inject custom `DevSupportManager` instances into the `ReactHost` so we can customize all options with any level of granularity (the same way we do on Android, for example).

Reviewed By: rshest

Differential Revision: D79804006

fbshipit-source-id: c28e788e5006cdbeb1a373d44b4e5aec1acec702
2025-08-12 05:41:11 -07:00
Rubén NorteandFacebook GitHub Bot c2c2e6b7c2 Connect debugger before loading bundle (#53203)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53203

Changelog: [internal]

This makes ReactHost connect the inspector immediately after creating the instance, aligned with how we do it on Android, instead of doing it as part of loading a bundle.

Reviewed By: rshest

Differential Revision: D79804004

fbshipit-source-id: b165520b0feb089fdfaa323413d697939c7ac794
2025-08-12 05:41:11 -07:00
Rubén NorteandFacebook GitHub Bot e0b22e1ebf Rename global variable with Metro server for Fantom (#53202)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53202

Changelog: [internal]

Just a minor refactor to follow the convention of prefixing Fantom-related globals and environment variables.

Reviewed By: rshest

Differential Revision: D79804007

fbshipit-source-id: 0c9a57c1b08ae18ae03cd66d1a6ef9690e0dea42
2025-08-12 05:41:11 -07:00
Rubén NorteandFacebook GitHub Bot 6fb0072f01 Refactor logic to find available port for Metro in Fantom (#53204)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53204

Changelog: [internal]

This changes the logic to find an available port for Metro on Fantom to do this outside Metro. Before, we'd set `0` as the port for Metro to find an available port, but in a following change we'll need to know the port before calling into Metro. This allows that.

Reviewed By: rshest

Differential Revision: D79804005

fbshipit-source-id: 5c2e2f4acbba3a79771586799b65653d46b8fe72
2025-08-12 05:41:11 -07:00
RakaDoankandFacebook GitHub Bot 739dfd2141 Help Codegen to find library's package.json after failure of importing library's package.json due to missing of ./package.json subpath (#53220)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53220

This is fix for some React Native libraries can't be found by Codegen, and will make the libraries unusable in new architecture (Turbo Modules)

Internally in the Codegen script, it will try to import library's package.json file with the `require.resolve`, but for some React Native libraries will throw an error with `ERR_PACKAGE_PATH_NOT_EXPORTED` code due to using the `exports` field in their package.json file while not exposing the package.json file itself. As an example
```json
{
  "exports": {
    ".": {
      "import": {
        "types": "./lib/typescript/module/index.d.ts",
        "default": "./lib/module/index.js"
      },
      "require": {
        "types": "./lib/typescript/commonjs/index.d.ts",
        "default": "./lib/commonjs/index.js"
      }
    },
    "./package.json": "./package.json" <-- here some libraries missed this
  },
  "codegenConfig": {}
}
```

Personally feel weird that library author has to expose their package.json only for the sake of Codegen and i believe library author shouldn't, even the library consumer don't need it.

## Changelog:

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

Pick one each for the category and type tags:

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

[GENERAL] [FIXED] - Help Codegen find library's package.json if some libraries using `exports` field in their package.json file and the `./package.json` subpath is not explicitly defined

bypass-github-export-checks

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

Test Plan:
`require.resolve('library/package.json')` [here](https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/codegen/generate-artifacts-executor/utils.js#L203) will throw an error with `ERR_PACKAGE_PATH_NOT_EXPORTED` code by Node.js. So if it does, help Codegen retry to find closest library's package.json with [`require.main.paths`](https://nodejs.org/api/modules.html#requiremain) search paths

You can init new app React Native CLI app with my sample react native library here [`ping-react-native`](https://github.com/RakaDoank/ping-react-native) v1.2.2.
Due to missing of the `package.json` subpath, before this change, it's autolinked but unusable due to missing of the spec header file. After this change, it works normally.

Rollback Plan:

Reviewed By: cortinico

Differential Revision: D80080243

Pulled By: cipolleschi

fbshipit-source-id: d33bf9eeb385ccf0c076e4d800a0d2840bd91b68
2025-08-12 04:45:07 -07:00
Mateo GuzmánandFacebook GitHub Bot 001736000f Migrate YogaStyleInputs to Kotlin
Summary:
Migrate com.facebook.yoga.YogaStyleInputs to Kotlin.

X-link: https://github.com/facebook/yoga/pull/1830

Reviewed By: rshest

Differential Revision: D79897662

Pulled By: cortinico

fbshipit-source-id: a4063a8c0f608050162cd3707834040e35f9ebf7
2025-08-12 03:34:21 -07:00
Ruslan ShestopalyukandFacebook GitHub Bot 841866c354 Add accessibility props test to the <Text/> component (#53218)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53218

# Changelog:
[Internal] -

Uses the existing generalized accessibility props test suite, recently created by andrewdacenko, to test the corresponding props in the <Text/> component.

Reviewed By: andrewdacenko

Differential Revision: D80000693

fbshipit-source-id: ebbceef8db7b56dc5e4ba1ac7c027a5952b680a7
2025-08-12 00:11:06 -07:00
generatedunixname89002005232357andFacebook GitHub Bot 677ee671d0 Revert D79993649 (#53217)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53217
Changelog: [Internal]
Fix rn-tester jobs

This diff reverts D79993649
(The context such as a Sandcastle job, Task, SEV, etc. was not provided.)

Depends on D79993649

Reviewed By: cortinico

Differential Revision: D80030502

fbshipit-source-id: 1feee2e2ae6a1edbeb755687aecb2a25d9759a90
2025-08-11 15:39:00 -07:00
Nick LefeverandFacebook GitHub Bot cc71f9c550 Create tryDispatchMountItems runnable only when needed (#53196)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53196

In the FabricUIManager, the runnable created for scheduled mounts is only used if currently running on the UI thread.

With this diff the runnable only gets created when needed.

Changelog: [Internal]

Reviewed By: christophpurrer

Differential Revision: D79969412

fbshipit-source-id: ee78890322af8580357389aad8357f7c0d18490f
2025-08-11 14:45:36 -07:00
Andrew DatsenkoandFacebook GitHub Bot 6738dbcc7e Generalize accessibility testing (#53182)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53182

Changelog: [Internal]
Move accessibility tests into reusable test suite.

Reviewed By: rshest

Differential Revision: D79897200

fbshipit-source-id: d98ebc7d16e7fd5c3c81086df4eec07dfdcb2fb0
2025-08-11 13:59:43 -07:00
Andrew DatsenkoandFacebook GitHub Bot 1feb364f72 Add accessibilityState (#53179)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53179

Changelog: [Internal]
Add accessibilityState debug prop

Reviewed By: zeyap

Differential Revision: D79894111

fbshipit-source-id: b9914965b053c239c7f954130a32240b15070b17
2025-08-11 13:59:43 -07:00
Mateo GuzmánandFacebook GitHub Bot a2eb3b299d Migrate YogaBaselineFunction to Kotlin
Summary:
Migrate com.facebook.yoga.YogaBaselineFunction to Kotlin.

X-link: https://github.com/facebook/yoga/pull/1831

Reviewed By: joevilches, mdvacca

Differential Revision: D79897676

Pulled By: cortinico

fbshipit-source-id: 2f175bf60a871c4635d1575faec1096f9c970f48
2025-08-11 10:51:55 -07:00
Vitali ZaidmanandFacebook GitHub Bot 8d998ce96c consolidated all 0.81 rcs entries in the changelog into 0.81 (#53212)
Summary:
Changelog: [Internal]

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

Reviewed By: cortinico

Differential Revision: D80005041

Pulled By: vzaidman

fbshipit-source-id: 93f570d9ddccdf8d4febc9d9f7702646ad7a6b56
2025-08-11 10:22:45 -07:00
RakaDoankandFacebook GitHub Bot 8dcb18d2b3 Help Codegen to find library's package.json after failure of importing library's package.json due to missing of ./package.json subpath (#53195)
Summary:
This is fix for some React Native libraries can't be found by Codegen, and will make the libraries unusable in new architecture (Turbo Modules)

Internally in the Codegen script, it will try to import library's package.json file with the `require.resolve`, but for some React Native libraries will throw an error with `ERR_PACKAGE_PATH_NOT_EXPORTED` code due to using the `exports` field in their package.json file while not exposing the package.json file itself. As an example
```json
{
  "exports": {
    ".": {
      "import": {
        "types": "./lib/typescript/module/index.d.ts",
        "default": "./lib/module/index.js"
      },
      "require": {
        "types": "./lib/typescript/commonjs/index.d.ts",
        "default": "./lib/commonjs/index.js"
      }
    },
    "./package.json": "./package.json" <-- here some libraries missed this
  },
  "codegenConfig": {}
}
```

Personally feel weird that library author has to expose their package.json only for the sake of Codegen and i believe library author shouldn't, even the library consumer don't need it.

## Changelog:

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

Pick one each for the category and type tags:

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

[GENERAL] [FIXED] - Help Codegen find library's package.json if some libraries using `exports` field in their package.json file and the `./package.json` subpath is not explicitly defined

bypass-github-export-checks

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

Test Plan:
`require.resolve('library/package.json')` [here](https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/codegen/generate-artifacts-executor/utils.js#L203) will throw an error with `ERR_PACKAGE_PATH_NOT_EXPORTED` code by Node.js. So if it does, help Codegen retry to find closest library's package.json with [`require.main.paths`](https://nodejs.org/api/modules.html#requiremain) search paths

You can init new app React Native CLI app with my sample react native library here [`ping-react-native`](https://github.com/RakaDoank/ping-react-native) v1.2.2.
Due to missing of the `package.json` subpath, before this change, it's autolinked but unusable due to missing of the spec header file. After this change, it works normally.

Rollback Plan:

Reviewed By: cortinico

Differential Revision: D79993649

Pulled By: cipolleschi

fbshipit-source-id: fa2bbd6178f5e5fef19a14e67f09ee8a727d01de
2025-08-11 10:10:04 -07:00
Andrew DatsenkoandFacebook GitHub Bot 4fa3c00324 Add base test for TouchableWithoutFeedback (#53178)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53178

Changelog: [Internal]
Add base integration test for TouchableWithoutFeedback

Reviewed By: zeyap

Differential Revision: D79889935

fbshipit-source-id: a72a85c647e371e6a6b330cd6eb2c3cc7c71b2f5
2025-08-11 10:03:28 -07:00
Michał PierzchałaandFacebook GitHub Bot fc6d7d4f0f Update RNC CLI in RNTester to v20.0.0 (#53206)
Summary:
Bump CLI to stable v20 for RNTester

## Changelog:

[INTERNAL] [CHANGED] - Update RNC CLI in RNTester to v20.0.0

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

Pick one each for the category and type tags:

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

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

Reviewed By: cortinico

Differential Revision: D79997077

Pulled By: rshest

fbshipit-source-id: 7264d942967fbfbc7fa5704f1089c0e7dbd3eb4b
2025-08-11 09:37:54 -07:00
Richard BarnesandFacebook GitHub Bot 9eb90f8911 Remove unused exception parameter from hermes/unittests/API/CDPAgentTest.cpp (#53213)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53213

`-Wunused-exception-parameter` has identified an unused exception parameter. This diff removes it.

This:
```
try {
    ...
} catch (exception& e) {
    // no use of e
}
```
should instead be written as
```
} catch (exception&) {
```

If the code compiles, this is safe to land.

Reviewed By: dtolnay

Differential Revision: D79968851

fbshipit-source-id: 18f2e6861f099915b1aad6aba58217ba94eb10c8
2025-08-11 09:35:31 -07:00
Riccardo CipolleschiandFacebook GitHub Bot 85b47afb48 Check delegate for getModuleForClass and getModuleInstanceFromClass (#53207)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53207

When restructuring the RCTReactNativeFactory, we forgot to add a couple of methods to check whether the delegate was implementing the RCTTurboModuleManager delegate methods.

This has been reported [here](https://github.com/react-native-community/discussions-and-proposals/issues/916)

This change fixes it.

## Changelog:
[iOS][Fixed] - Ask the delegate for `getModuleForClass` and `getModuleInstanceFromClass`

Reviewed By: cortinico

Differential Revision: D79998104

fbshipit-source-id: 68069a9f93182d4fa416b5799bf4eec4d107552b
2025-08-11 08:51:01 -07:00
Mateo GuzmánandFacebook GitHub Bot 9c9a39b58e Migrate YogaLogger to Kotlin
Summary:
Migrate com.facebook.yoga.YogaLogger to Kotlin.

X-link: https://github.com/facebook/yoga/pull/1834

Reviewed By: rshest

Differential Revision: D79897742

Pulled By: cortinico

fbshipit-source-id: 79b926a7abadce9038fc55ad0f608e92bc77a55a
2025-08-11 08:47:34 -07:00
Riccardo CipolleschiandFacebook GitHub Bot 0af4a1c71f Set up Switch Fantom test (#53134)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53134

This change sets up the Fanto test for the Switch component

## Changelog:
[Internal] -

Reviewed By: rubennorte

Differential Revision: D79719683

fbshipit-source-id: d8a5d127296e3448faf5f841baa98bc34f4f43cb
2025-08-11 08:17:48 -07:00
Ruslan ShestopalyukandFacebook GitHub Bot 749dbe0840 Add test for Text.adjustsFontSizeToFit (#53210)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53210

# Changelog:
[Internal] -

As in the title.

Reviewed By: andrewdacenko

Differential Revision: D80001500

fbshipit-source-id: ab5564b0e9ab728f0825aec9da24539c9e2c5290
2025-08-11 08:14:15 -07:00
Riccardo CipolleschiandFacebook GitHub Bot 1c33774990 Remove setup-xcode-build-cache action (#53177)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53177

This action is used only when running tests for RNTester. Now that we are using prebuilds, this is a liability, because Cocoapods and Xcode would not update the binary if a new one is provided.

With prebuild, this caching does not provide a lot of benefits, so we can remove it.

## Changelog
[Internal] -

Reviewed By: cortinico

Differential Revision: D79893870

fbshipit-source-id: 0773f910f418cf9ebd5d557d563160993084e83a
2025-08-11 08:07:43 -07:00
Peter AbbondanzoandFacebook GitHub Bot 07835d3d67 xplat/js/react-native-github/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.java (#53116)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53116

Converts ReactAccessibilityDelegate to Kotlin

Changelog: [Internal]

Reviewed By: andrewdacenko

Differential Revision: D79749812

fbshipit-source-id: bdfbd61f61339d8332a4fa3f5cc4ccd4b4355323
2025-08-11 07:54:09 -07:00
Vojtech NovakandFacebook GitHub Bot 4c570b5d31 fix cp command in ReactNativeDependencies.podspec (#53136)
Summary:
When running `RCT_USE_PREBUILT_RNCORE=1 RCT_USE_RN_DEP=1 pod install` I'm getting an error: `cp: framework/packages/react-native/..: File exists`

This is not seen consistently by everyone but I've seen in reported one more time at Expo. Could be related to running MacOS 26.

Somehow, apparently, the `..` is being treated as a literal directory name and cp is trying to create a directory named `..` inside `framework/packages/react-native/` which is not what we want. Using `/.` avoids that.

 ---
What also seemed to work(around) was to change `mkdir -p framework/packages/react-native` to `mkdir -p framework/packages/` and then `cp` can create the `framework/packages/react-native/..` folder. But this is definitely more confusing.

## Changelog:

Pick one each for the category and type tags:

[IOS] [FIXED] - fix "file exists" error in `ReactNativeDependencies.podspec`

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

Test Plan: tested locally, and in CI on older macOS: https://github.com/expo/expo/pull/38631 (the ios build succeeds)

Reviewed By: rshest

Differential Revision: D79990895

Pulled By: cipolleschi

fbshipit-source-id: 44ff9034800d3acd4e55ec39aabfb326382372cb
2025-08-11 06:36:15 -07:00
generatedunixname537391475639613andFacebook GitHub Bot fd600a24af xplat/js/react-native-github/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewShadowNode.cpp (#53198)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/53198

Reviewed By: rshest

Differential Revision: D79874231

fbshipit-source-id: 15b2a0c2330e6237b92db68094ce97f3e708f9a6
2025-08-11 06:31:16 -07:00
Rubén NorteandFacebook GitHub Bot 6b05a59a0d Extend PerformanceEventTiming with taskEndTime (#53199)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53199

Changelog: [internal]

This adds a new `taskEndTime` field in the internal C++ representation of `PerformanceEventTiming` so we can distinguish events that waited for mount (because they triggered changes) and events that didn't, so report INP correctly.

Reviewed By: rshest

Differential Revision: D79894702

fbshipit-source-id: f7472bfaecaa69f2126719d0dc3d3b251e3a8f68
2025-08-11 05:26:56 -07:00
Phil PluckthunandFacebook GitHub Bot 94623ca8ec Fix missing path escape patterns in Xcode scripts for projects with spaces (#53194)
Summary:
When running a project in a path that contains any spaces, the scripts have several escape patterns that don't handle this path correctly. For example, `"/absolute/path/with spaces"` may be rendered as `/absolute/path/with spaces` and this shows as an output error such as `No such file or directory /absolute/path/with`

This was likely a longstanding issue, but is unexpected for some beginners that first try out React Native. While it's not recommended to create a path like this, it's certainly not hard to make this mistake.

## Changelog:

[IOS] [FIXED] - fix scripts for paths containing whitespaces

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

Test Plan: tested locally; create a React Native or Expo project in a folder containing a space (e.g. `/my/path/with spaces/new-app` and build the project. With changes applied, the build should succeed. (There's related failures in `expo/expo` that need fixing too)

Reviewed By: robhogan

Differential Revision: D79993537

Pulled By: cipolleschi

fbshipit-source-id: b32697ce2405c403c410b3ceaed7e161e4a48537
2025-08-11 05:12:43 -07:00
David VaccaandFacebook GitHub Bot d3bbbd893a Deprecate com/facebook/react Legacy Architecture classes (#53104)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53104

Deprecate com/facebook/react Legacy Architecture classes

changelog: [Android][Changed] Depreacate CoreModulesPackage and NativeModuleRegistryBuilder legacy architecture classes, these classes unused in the new architecture and will be deleted in the future

Reviewed By: shwanton

Differential Revision: D79676942

fbshipit-source-id: a2c447bee251fdac79d3dc81a17851eaf5271413
2025-08-09 04:39:35 -07:00
David VaccaandFacebook GitHub Bot da74d5da2c Deprecate Legacy Architecture ViewManagers (#53107)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53107

Deprecate Legacy Architecture ViewManagers, these classes are not used as part of the new architecture and will be deleted in the future

changelog: [Android][Changed] Deprecate Legacy Architecture ViewManagers, these classes are not used as part of the new architecture and will be deleted in the future

Reviewed By: shwanton

Differential Revision: D79676585

fbshipit-source-id: 72cb6fe0bbe666cfa317cf28d6aec475f1c38c35
2025-08-09 04:39:35 -07:00
David VaccaandFacebook GitHub Bot 07091a9ae8 Deprecate custom ShadowNode classes included in React Native (#53192)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53192

In this diff I'm deprecating ShadowNode classes included in React Native library

These classes are part of the legacy architecture and will be deleted in the future

changelog: [Android][Changed] Deprecate LegacyArchitecture ShadowNode classes included in React Native

Reviewed By: mlord93

Differential Revision: D79676584

fbshipit-source-id: a39267e6e430fcf4f6a73c96cd28d02eafc88a32
2025-08-09 04:39:35 -07:00
David VaccaandFacebook GitHub Bot c1f7c5e321 Depreacte remaining LegacyArchitecture classes from the bridge package (#53191)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53191

Depreacte remaining LegacyArchitecture classes from the bridge package

changelog: [Android][Changed] Depreacte all LegacyArchitecture classes from the bridge package

Reviewed By: mlord93

Differential Revision: D79674635

fbshipit-source-id: 6a873d05157e17ef0434821e1c8a77959d7f079a
2025-08-09 04:39:35 -07:00
David VaccaandFacebook GitHub Bot b29b86f275 Deprecate LegacyArchitecture class UIManagerProvider (#53190)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53190

Deprecate LegacyArchitecture class UIManagerProvider

changelog: [Android][Changed] Deprecate LegacyArchitecture class UIManagerProvider

Reviewed By: mlord93

Differential Revision: D79674639

fbshipit-source-id: 6802a35c4bd643f138a54b4f22f3804743f89249
2025-08-09 04:39:35 -07:00
David VaccaandFacebook GitHub Bot 25c011eb4d Deprecate BridgeDevSupportManager and JSInstance (#53108)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53108

Deprecate BridgeDevSupportManager and JSInstance

changelog: [Android][Changed] Deprecate BridgeDevSupportManager and JSInstance

Reviewed By: mlord93

Differential Revision: D79674636

fbshipit-source-id: c34c4ed386ab6c130fc12e03659fe2d15b42658d
2025-08-09 04:39:35 -07:00
David VaccaandFacebook GitHub Bot 3306cdbbe9 Update deprecation message for BridgeReactContext class (#53110)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53110

Update deprecation message for BridgeReactContext class

changelog: [internal] internal

Reviewed By: mlord93

Differential Revision: D79674637

fbshipit-source-id: 0942b0c8479cd1eba8e29bd9dcfc4547790910f1
2025-08-09 04:39:35 -07:00
David VaccaandFacebook GitHub Bot 22e4c25211 Deprecate NativeModuleRegistry Legacy Architecture class (#53123)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53123

Deprecate NativeModuleRegistry Legacy Architecture class

changelog: [Android][Changed] Deprecate NativeModuleRegistry Legacy Architecture class

Reviewed By: mlord93

Differential Revision: D79674638

fbshipit-source-id: 7791ceb53545aa456e92f051ed4c1f070305b5fc
2025-08-09 04:39:35 -07:00
David VaccaandFacebook GitHub Bot 78a3ff81eb Deprecate subset of LegacyArchitecture classes in com/facebook/react/bridge (#53106)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53106

Deprecate subset of LegacyArchitecture classes in com/facebook/react/bridge

changelog: [Android][Changed] Deprecate subset of LegacyArchitecture classes in com/facebook/react/bridge

Reviewed By: mlord93

Differential Revision: D79674640

fbshipit-source-id: 58b8fde8bed739fd04272215e399cfbed7a0188a
2025-08-09 04:39:35 -07:00
David VaccaandFacebook GitHub Bot 25f466cc4d Deprecate FrescoBasedReactTextInlineImageShadowNode (#53121)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53121

Deprecate FrescoBasedReactTextInlineImageShadowNode

changelog: [Android][Changed] Deprecate LegacyArchitecture class FrescoBasedReactTextInlineImageShadowNode

Reviewed By: mlord93

Differential Revision: D79672291

fbshipit-source-id: 482939981b735e7f96d7cde874430e2895c0d10c
2025-08-09 04:39:35 -07:00
David VaccaandFacebook GitHub Bot 718126fcf0 Deprecate Legacy Architecture class CallbackImpl (#53105)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53105

Deprecate Legacy Architecture class CallbackImpl

changelog: [Android][Changed] Deprecate Legacy Architecture class CallbackImpl

Reviewed By: mlord93

Differential Revision: D79672292

fbshipit-source-id: d35ae53093f464f2bb088a8247dbbde8591572c6
2025-08-09 04:39:35 -07:00
David VaccaandFacebook GitHub Bot 19a99dd088 Deprecate JavaMethodWrapper (#53124)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53124

Deprecate LegacyArchitecture class JavaMethodWrapperchagelog:

changelog: [Android][Changed] Deprecate LegacyArchitecture class JavaMethodWrapper

Reviewed By: mlord93

Differential Revision: D79672296

fbshipit-source-id: 05432263c4452294c667226cb8e062c50f036931
2025-08-09 04:39:35 -07:00
David VaccaandFacebook GitHub Bot c4715886a9 Deprecate Legacy Architecture ShadowNode classes
Summary:
Deprecate Legacy Architecture ShadowNode classes

Changelog: [Android][Changed] Deprecate Legacy Architecture ShadowNode classes

Reviewed By: mlord93

Differential Revision: D79672295

fbshipit-source-id: e510debd3718e6bc9e42c9b61d6a63858970077d
2025-08-09 04:39:35 -07:00
David VaccaandFacebook GitHub Bot 1a85185cfc Deprecate ShadowNodes on the codegen (#53184)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53184

Deprecate ShadowNodes on the codegen

changelog: [internal] internal

Reviewed By: shwanton

Differential Revision: D79911692

fbshipit-source-id: ad24488d186fd5b82c3953a75f52be03e4770cc2
2025-08-09 04:39:35 -07:00
David VaccaandFacebook GitHub Bot d2912e7997 EZ fix naming in kotlin file (#53109)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53109

EZ fix naming in kotlin file

changelog: [internal] internal

Reviewed By: cortinico, shwanton, mlord93

Differential Revision: D79735705

fbshipit-source-id: b1061a9aa0f245de29efb1b0f3d6c9ada9c43660
2025-08-08 16:43:31 -07:00
Ramanpreet NaraandFacebook GitHub Bot 7d6d0a7735 native modules: Show message in redundant rejection redbox (#53152)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53152

When a redundant reject is called, show the rejection message in the redbox. This can help us pin down the error we need to elminiate in production.

Changelog: [Internal]

Reviewed By: sanjay-io

Differential Revision: D79837541

fbshipit-source-id: 879b5dc42980867051cfab6ccb575304a4a9c4c6
2025-08-08 14:39:42 -07:00
Ramanpreet NaraandFacebook GitHub Bot dc879950d1 native modules: Guard against concurrent resolve/reject calls (#53151)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53151

If the native module calls the resolve/reject, resolve/resolve, reject/resolve, reject/reject concurrently, the turbomodule infra could run into a null pointer exception. This diff mitigates that problem.

Changelog: [iOS][Fixed] - Fix concurrent calls into resolve/reject inside native modules

Reviewed By: sanjay-io

Differential Revision: D79824319

fbshipit-source-id: 675264781f303d12fc1eb9649ecdc78601b7720b
2025-08-08 14:39:42 -07:00
Calix TangandFacebook GitHub Bot e0ea781908 Basic Fantom Tests for Pressable (#53181)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53181

Adds basic Fantom tests for the <Pressable> React Native component.

Following T233710053, adds tests for some of the listed props and refs.

Covered props:
* children
* disabled
* onPress
* style

Ref:
* Pressable is a Native Component and has the correct tag

I did not cover the rest of the listed props due to Fantom not having suitable events to trigger to test them and/or inease of implementing functionality to do so.

## Changelog:

[Internal]

Reviewed By: andrewdacenko

Differential Revision: D79745215

fbshipit-source-id: 26caaabf72ea7ffff3e652616dfd9f0cf7fc2020
2025-08-08 12:56:58 -07:00
Luna WeiandFacebook GitHub Bot b3f397f343 VirtualViewExperimental on iOS (#52852)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/52852

Changelog: [Internal] - Implementation of ScrollView-managed VirtualViews for iOS

In previous diffs we've introduced a "VirtualViewExperimental" which is a clone of VirtualView. This diff updates the experimental version to move interection logic (whether something is visible, in prerender-space, etc.) to the ScrollView so there are less listeners. We now use 1 scroll listener vs. N

Reviewed By: philIip

Differential Revision: D78825701

fbshipit-source-id: d515e3cb2dae53d779b5d3f4c317a2c7a6b25857
2025-08-08 11:12:12 -07:00
Zeya PengandFacebook GitHub Bot 5517c046ab Cache result when RenderOutput::render() is called (#53112)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53112

## Changelog:

[Internal] [Changed] - Cache result when RenderOutput::render() is called

Rreviously, root.getRenderedOutput in fantom doesn't really reflect the result of direct manipulation from native animated (see the test case added here). This stack is enabling it.

* make RenderOutput an instance owned by TestMountingManager that can cache render result
  * why is this needed - native animation's direct manipulation should modify the render result (analog to directly manipulating host views on a platform) instead of props on a StubView
* here i also make sure that `RenderOutput::render()` will only re calculate the render result for a tree after StubViewTree::mutate is called

Reviewed By: andrewdacenko

Differential Revision: D79737991

fbshipit-source-id: ee2193b708e319c1519b06bc672054c4f7105da1
2025-08-08 10:54:05 -07:00
Mateo GuzmánandFacebook GitHub Bot 8ccfff9a46 Migrate ReactBaseTextShadowNode to Kotlin (#52449)
Summary:
Migrate com.facebook.react.views.text.ReactBaseTextShadowNode to Kotlin.

## Changelog:

[Android][Changed] - Migrated ReactBaseTextShadowNode to Kotlin. You might need to update your property access to use camelCase instead of Hungarian notation.

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

Test Plan:
```bash
yarn test-android
yarn android
```

Reviewed By: mdvacca

Differential Revision: D79341403

Pulled By: cortinico

fbshipit-source-id: ff5dd7a8c3e0220812dd3a214d8d680ccd83f4d8
2025-08-08 10:36:32 -07:00
Ruslan ShestopalyukandFacebook GitHub Bot 0aeb26bdfc e2e test for Text.role (#53176)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53176

# Changelog:
[Internal] -

As in the title

Reviewed By: andrewdacenko

Differential Revision: D79891116

fbshipit-source-id: 13042a9b82373b8e0073c8421e532e6e463d60f8
2025-08-08 10:02:57 -07:00
Ruslan ShestopalyukandFacebook GitHub Bot 3d37d2d2ce Add test for Text.maxFontSizeMultiplier (#53171)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53171

# Changelog:
[Internal] -

As in the title.

Reviewed By: andrewdacenko

Differential Revision: D79888839

fbshipit-source-id: 52964ce9484c51dc5ff1065343ef9d2f829425c9
2025-08-08 10:02:57 -07:00
Ruslan ShestopalyukandFacebook GitHub Bot 5a38948034 e2e test for Text.id/nativeID (#53170)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53170

# Changelog:
[Internal] -

As in the title.

Reviewed By: andrewdacenko

Differential Revision: D79887689

fbshipit-source-id: a8a6a16a0fbf3f1481758a2d91c7813d51a4d9d1
2025-08-08 10:02:57 -07:00
Riccardo CipolleschiandFacebook GitHub Bot 1a58fdf172 Add tests for Modal.animiated prop (#53174)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53174

Add Fantom tests for Modal.animiated prop

Notice that animated is deprecated and ignored when rendering.

## Changelog:
[Internal] -

Reviewed By: andrewdacenko

Differential Revision: D79888036

fbshipit-source-id: aa9003d376f356e9934a61a7cfc958b44d9892eb
2025-08-08 08:52:46 -07:00
Riccardo CipolleschiandFacebook GitHub Bot 618254d8e9 Add tests for Modal.allowSwipeDismissal prop (#53173)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53173

Add Fantom tests for Modal.allowSwipeDismissal prop

## Changelog:
[Internal] -

Reviewed By: andrewdacenko

Differential Revision: D79885004

fbshipit-source-id: 9db4bc38c739223a36180d09397bad09ecc67d86
2025-08-08 08:52:46 -07:00
Riccardo CipolleschiandFacebook GitHub Bot 01e3f8d75e Add tests for Modal.visible prop (#53172)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53172

Add Fantom tests for Modal.visible prop

## Changelog:
[Internal] -

Reviewed By: andrewdacenko

Differential Revision: D79884676

fbshipit-source-id: 7c3ca4e16596022096a634a7232b616cf15c79c4
2025-08-08 08:52:46 -07:00
Riccardo CipolleschiandFacebook GitHub Bot 2812e20ecc Add tests for Modal.hardwareAccelerated prop (#53162)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53162

Add Fantom tests for Modal.hardwareAccelerated prop

## Changelog:
[Internal] -

Reviewed By: andrewdacenko

Differential Revision: D79881565

fbshipit-source-id: 80aaeb0659883d536c37996e86231c9d1d9eff49
2025-08-08 08:52:46 -07:00
Riccardo CipolleschiandFacebook GitHub Bot 674fd79eaf Add tests for Modal.navigationBarTranslucent prop (#53157)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53157

Add Fantom tests for Modal.navigationBarTranslucent prop

## Changelog:
[Internal] -

Reviewed By: andrewdacenko

Differential Revision: D79881358

fbshipit-source-id: 75816bf9bb18dc2115477965953fcd88a65d5be5
2025-08-08 08:52:46 -07:00
Riccardo CipolleschiandFacebook GitHub Bot de76f3436c Add tests for Modal.statusBarTranslucent prop (#53158)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53158

Add Fantom tests for Modal.statusBarTranslucent prop

## Changelog:
[Internal] -

Reviewed By: andrewdacenko

Differential Revision: D79881104

fbshipit-source-id: 9ee9edbff67059eeb815be2a7a095eac91ec7420
2025-08-08 08:52:46 -07:00
Riccardo CipolleschiandFacebook GitHub Bot 99ae977345 Add tests for Modal.transparent prop (#53159)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53159

Add Fantom tests for Modal.transparent prop

## Changelog:
[Internal] -

Reviewed By: andrewdacenko

Differential Revision: D79880909

fbshipit-source-id: f597decb29f578433d6c7ac594327b6130945a8e
2025-08-08 08:52:46 -07:00
Riccardo CipolleschiandFacebook GitHub Bot fee81401d7 Add tests for Modal.presentationStyle prop (#53160)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53160

Add Fantom tests for Modal.presentationStyle prop

## Changelog:
[Internal] -

Reviewed By: andrewdacenko

Differential Revision: D79880310

fbshipit-source-id: fda68a481b85e58e5f94d012c71a55cf51b9c8df
2025-08-08 08:52:46 -07:00
Nicola CortiandFacebook GitHub Bot ec9f62865c Update firebase DB url. (#53166)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53166

Our DB doesn't have that suffix, so I'm removing it.

Changelog:
[Internal] [Changed] -

Reviewed By: cipolleschi

Differential Revision: D79883740

fbshipit-source-id: a52ab275129807cbb6e066baefccd71a8ac7398d
2025-08-08 08:05:54 -07:00
Nicola CortiandFacebook GitHub Bot e16def43c9 Reland: Add tests for DisplayMetricsHolder (#53165)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53165

This is a re-land of D78981753
Those tests were OOM-ing because we were using a old version of robolectric.
I've bumped it and this should fix it.

Changelog:
[Internal] [Changed] -

Reviewed By: lenaic

Differential Revision: D79883742

fbshipit-source-id: 4c2c640d6b601ec07d0a4a12cd7b86a879740a41
2025-08-08 07:09:32 -07:00
Ruslan ShestopalyukandFacebook GitHub Bot afb6294335 Add Fantom test for Text.selectable (#53168)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53168

# Changelog:
[Internal]-
Adds Fantom test for `Text.selectable` prop.

Reviewed By: andrewdacenko

Differential Revision: D79885301

fbshipit-source-id: d66895397ee0bbcfedc3f744ae8138d2741b2b1e
2025-08-08 06:49:05 -07:00
Ruslan ShestopalyukandFacebook GitHub Bot 5b9063ed70 E2E test for numberOfLines prop in Text (#53167)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53167

# Changelog
[Internal] -

As in the title.

Reviewed By: andrewdacenko

Differential Revision: D79884649

fbshipit-source-id: fa2d0be9d455449d5a806b06c0480dcefdaaae3e
2025-08-08 06:49:05 -07:00
Ruslan ShestopalyukandFacebook GitHub Bot 404c975ff2 Prop test for Text.allowFontScaling
Summary:
# Changelog:
[Internal] -

Adds Fantom test for `Text.allowFontScaling`.

Reviewed By: andrewdacenko

Differential Revision: D79882955

fbshipit-source-id: b1426c1e7f2667c2db017d749710320ec1e6aadd
2025-08-08 06:49:05 -07:00
Ruslan ShestopalyukandFacebook GitHub Bot 91f9ff042d Create e2e test for Text.ellipsizeMode prop (#53163)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53163

# Changelog:
[Internal] -

Adds a Fantom test that tests the `Text.ellipsizeMode` prop.

It also adds a test for the `<Text/>` component without any props

Reviewed By: andrewdacenko

Differential Revision: D79882336

fbshipit-source-id: f938c85092325374f562d610432781e2d412b88e
2025-08-08 06:49:05 -07:00
Riccardo CipolleschiandFacebook GitHub Bot 20c91f2bd4 Add tests for Modal.animationStyle prop (#53141)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53141

Add Fantom tests for Modal.animationStyle prop

## Changelog:
[Internal] -

Reviewed By: andrewdacenko, rubennorte

Differential Revision: D79808162

fbshipit-source-id: 36ba61bf741dc7cfa7a736fd83a824285304d5b2
2025-08-08 06:47:23 -07:00
Riccardo CipolleschiandFacebook GitHub Bot 7035391b04 Add basic test for Modal (#53140)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53140

As per title, this change adds the boilerplate code for a Fantom test on Modal

## Changelog:
[Internal] -

Reviewed By: andrewdacenko

Differential Revision: D79805808

fbshipit-source-id: c8c77e576a09b346cf29b290d68c75e540d5f146
2025-08-08 06:47:23 -07:00
Riccardo CipolleschiandFacebook GitHub Bot e547f466ee Improve codegen to add getDebugProps to components (#53135)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53135

Our Codegenerated components are not generating code for `getDebugProps`. This change modifies Codegen to add those functions for all the codegen components.

## Changelog:
[General][Added] - Added getDebugProps to codegen

## Facebook:
`getDebugProps` are required by Fantom to write tests. However, we can't generate these function for third party components, because codegen can generate arbitrary structs and we don't have a generic `toString()` method that can be used or automatically generated by C++.

By generating this function only for Core Components, we can ensure that we can write Fantom tests without breaking all the users of React Native.

Reviewed By: rubennorte

Differential Revision: D79805145

fbshipit-source-id: 0e41c65fc30eaa886a05557ca233fb0a9cb18a71
2025-08-08 06:47:23 -07:00
Andrew DatsenkoandFacebook GitHub Bot 8363a4c515 Add static methods tests (#53087)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53087

Changelog: [Internal]
As title

Reviewed By: lenaic

Differential Revision: D79665922

fbshipit-source-id: 024c10960a59e1332aacf2411a68ca85c17142db
2025-08-08 06:00:58 -07:00
generatedunixname89002005287564andFacebook GitHub Bot ec3d9c60f1 Fix CQS signal readability-container-size-empty in xplat/js/react-native-github/packages (#53155)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/53155

Reviewed By: rshest

Differential Revision: D79788547

fbshipit-source-id: a18465d5c16ab1822c4e9f6302767505fe6f5ee5
2025-08-08 04:24:03 -07:00
Rubén NorteandFacebook GitHub Bot 2f33eece41 Fix retry logic in Fantom when requesting bundles from Metro (#53161)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53161

Changelog: [internal]

This fixes a bug in the retry logic in Fantom when requesting bundles from Metro, where we cache the error from a previous attempt and use it to determine we didn't succeed after the attemps.

Reviewed By: rshest

Differential Revision: D79881488

fbshipit-source-id: 566b2d700db2f9653b9ea9acd577d7eb03770b76
2025-08-08 04:22:16 -07:00
generatedunixname1395667395051502andFacebook GitHub Bot 81fdb9dd93 Update React Native DevTools binaries
Summary:
Automated update of React Native DevTools binaries
bypass-github-export-checks
Changelog: [Internal]

Reviewed By: motiz88

Differential Revision: D79836825

fbshipit-source-id: 82484ab99d7813b79bfb75a6c3ad3bd9863f8856
2025-08-08 04:11:28 -07:00
Andrew DatsenkoandFacebook GitHub Bot d4ea32493e Revert resizeMode to Stretch as unset (#53144)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53144

Changelog: [Internal]
This is a fix to "unset" prop value for Image.
In my previous diff D79600137 I have changed this behaviour to have Cover as a default, but it is not "default" value, but rather "unset" value.

Reviewed By: rshest

Differential Revision: D79813759

fbshipit-source-id: cc6d43742e51fb2087d6023bd0ff50a3d54eed49
2025-08-08 03:43:06 -07:00
Nicola CortiandFacebook GitHub Bot ba518bbb30 RNGP - Make sure the newArchEnabled is set to true for all the libs (#53138)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53138

Without this patch, library could break if the user removes the `newArchEnabled=`
property from the `gradle.properties` file.

With this patch instead we hardcode the property to true, so all the libraries can consume
it if they wish.

Changelog:
[Internal] [Changed] -

Reviewed By: cipolleschi

Differential Revision: D79805857

fbshipit-source-id: 88dda707a0d80ac79e96c955ded2ef0823f3d3ff
2025-08-08 03:42:35 -07:00
David VaccaandFacebook GitHub Bot 85610c8b43 Deprecate Legacy Architecture UIManagerModules class (#53122)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53122

Deprecate LegacyArchitecture UIManagerModules class

changelog: [Android][Changed] Deprecate LegacyArchitecture UIManagerModules class

Reviewed By: mlord93

Differential Revision: D79672294

fbshipit-source-id: 8a22df4a4341a2ab501fc003ee213fb0047847fc
2025-08-08 02:52:36 -07:00
David VaccaandFacebook GitHub Bot 7f5b2b8f84 Deprecate Legacy Architecture classes belonging to com/facebook/react/uimanager (#53102)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53102

Deprecate large subset of Legacy Architecture classes belonging to com/facebook/react/uimanager

changelog: [Android][Changed] Deprecate LegacyArchitecture classes from com/facebook/react/uimanager

Reviewed By: mlord93

Differential Revision: D79672293

fbshipit-source-id: 2d32eb885af3ec2928510608330740229abf93db
2025-08-08 02:52:36 -07:00
David VaccaandFacebook GitHub Bot 39d24bade3 Deprecate LegacyArchitecture classes from package com.facebook.react.uimanager (#53120)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53120

Deprecate com.facebook.react.uimanager classes

changelog: [Android][Changed] Deprecate LegacyArchitecture classes from package com.facebook.react.uimanager

Reviewed By: mlord93

Differential Revision: D79660036

fbshipit-source-id: 981f7938e54e40f810caec72fa485cc4a00029f6
2025-08-08 02:52:36 -07:00
David VaccaandFacebook GitHub Bot 9831b03860 Rename BridgeSoLoader -> ReactNativeJNISoLoader (#53153)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53153

In this diff I'm renaming BridgeSoLoader -> ReactNativeJNISoLoader and removing LegacyArchitecture becuase this class loads jni classes that are required in new architecture

changelog: [internal] internal

Reviewed By: RSNara

Differential Revision: D79827295

fbshipit-source-id: 2d02fa1de49b2e4ee838f14e976ae3ab2ca98aef
2025-08-08 01:20:42 -07:00
Alan LeeandFacebook GitHub Bot f21a89078c Revert D79571226: replace getWindowDisplayMetrics with getScreenDisplayMetrics
Differential Revision:
D79571226

Original commit changeset: d90fca36c119

Original Phabricator Diff: D79571226

fbshipit-source-id: 670ae66f9db758d29673134adbac44780569771b
2025-08-08 00:48:14 -07:00
Alan LeeandFacebook GitHub Bot 352e440459 Back out "Fix Dimensions window values on Android < 15" (#53149)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53149

Reverting PR https://github.com/facebook/react-native/pull/52738

Changelog: [Internal]
reverting D78738516

Original commit changeset: fdb22f3cc76b

Original Phabricator Diff: D78738516

Reviewed By: mdvacca, lenaic, Abbondanzo

Differential Revision: D79835424

fbshipit-source-id: 44b5ee34b4df6752e5a6f959a54e104eef20ffca
2025-08-08 00:40:42 -07:00
David VaccaandFacebook GitHub Bot aaf471278c Back out "Add tests for DisplayMetricsHolder" (#53148)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53148

Reverting D78981753 because it's causing tests to OOM
https://github.com/facebook/react-native/commit/384677f58ea0af498f548a043be86e6876af58b1

changelog: [internal] internal

Reviewed By: shwanton

Differential Revision: D79828375

fbshipit-source-id: 3de01dca3d9a9fc4530c84855049eb4ec132a485
2025-08-07 14:33:33 -07:00
Nicola CortiandFacebook GitHub Bot 384677f58e Add tests for DisplayMetricsHolder (#52946)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/52946

This just add a set of unit tests for `DisplayMetricsHolder` as I'm working on this class recently.

Changelog:
[Internal] [Changed] -

Reviewed By: rshest, mdvacca

Differential Revision: D78981753

fbshipit-source-id: 5800d44d3131a58770a0049eb2d08306874b7183
2025-08-07 11:01:37 -07:00
Nicola CortiandFacebook GitHub Bot 2e76fc8e8e Correctly create the first modal state (#52835)
Summary:
There is currently a bug with Modals with New Architecture where the first frame is rendered incorrectly, specifically not accounting for all the vertical insets (only the status bar). This fixes it.

Specifically:
1. I've removed the caching of the statusbar height from `ReactModalHostView` as that was not working correctly. Sometimes the value returned `0` meaning that it was not yet computed when Fabric was asking for it. In the updated implementation we now query `FabricUIManager` given the `surfaceId` of the modal.
2. I've modified the logic to account for all the vertical insets, not just the status bar.

## Changelog:

[ANDROID] [FIXED] - Correctly account for insets on first render of Modals on New Arch

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

Test Plan:
Tested on Marketplace Location Picker and the picker is still working correctly:

 https://pxl.cl/7NjtJ

Reviewed By: mdvacca

Differential Revision: D78975126

Pulled By: cortinico

fbshipit-source-id: d7afb4fa5d2f43a7e33da3860432fa6dfe0dc8d7
2025-08-07 11:01:37 -07:00
Ruslan ShestopalyukandFacebook GitHub Bot 5fc23d7c62 Add type-safe API for passing around benchmark results (#53143)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53143

# Changelog:
[Internal] -

This refactors the way Fantom benchmark test results are passed to the top level, making it type safe and more maintainable.

Reviewed By: andrewdacenko

Differential Revision: D79812707

fbshipit-source-id: d8bfef7e1b0c11b277a08f5e4c810f8c1efd7f89
2025-08-07 10:46:26 -07:00
Nicola CortiandFacebook GitHub Bot e92da16a9b Migrate ClipboardModuleTest to use BridgelessReactContext (#53131)
Summary:
This test was still using the old `BridgeReactContext`, I'm migrating it to `BridgelessReactContext`.

## Changelog:

[INTERNAL] -

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

Test Plan: CI

Reviewed By: mdvacca

Differential Revision: D79801564

Pulled By: cortinico

fbshipit-source-id: 9bb96185505703a773597aeadfeeaeeb194532de
2025-08-07 10:42:26 -07:00
Ruslan LesiutinandFacebook GitHub Bot ae5df7ee35 Bump Electron to 37.2.4 (#53145)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53145

# Changelog: [Internal]

See attached tasks.

Reviewed By: motiz88

Differential Revision: D79563948

fbshipit-source-id: a95b4e63d3a7d0d456c89ec7361e58fea0f5fb66
2025-08-07 10:40:57 -07:00
Sharif MahmoudandFacebook GitHub Bot dacd8f26fd Fix HEADER_SEARCH_PATHS for RuntimeExecutor when USE_FRAMEWORKS is enabled (#53099)
Summary:
`#include <ReactCommon/RuntimeExecutor.h>` stopped working in react-native 0.81 when using frameworks because it is not part of ReactCommon anymore when the split happened for iOS.

to fix this I am including RuntimeExecutor in search headers same way we include ReactCommon.

## Changelog:

[IOS] [FIXED] - Fix import RuntimeExecutor.h with USE_FRAMEWORKS

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

Test Plan:
You can enable USE_FRAMEWORKS and do `#include <react/renderer/uimanager/UIManager.h>` (which react-native-reanimated is doing).
Build will fail complaining that it can't find ReactCommon/RuntimeExecutor.h which is included in UIManager.h
Add my patch, it will work and build successfully

Reviewed By: cortinico

Differential Revision: D79796637

Pulled By: cipolleschi

fbshipit-source-id: f8bb669cfb9f4414653655ed98d2cc6bb431a3e5
2025-08-07 10:12:51 -07:00
Nicola CortiandFacebook GitHub Bot ede037ade7 Cleanup heightOfTallestInlineImage field (#52978)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/52978

This field is never written anywhere (neither in the internal codebase, nor in OSS).
I'm cleaning this us and simplifying the logic:
- Deprecating `effectiveLineHeight`
- Replacing all the usage of `effectiveLineHeight` with just `lineHeight`

Changelog:
[Android] [Changed] - Deprecate the field `TextAttributeProps.effectiveLineHeight`. This field was public but never used in OSS.

Reviewed By: mdvacca

Differential Revision: D79442393

fbshipit-source-id: c424a6def0257264cd160a2d7be48c2d0f47135e
2025-08-07 09:49:46 -07:00
Mateo GuzmánandFacebook GitHub Bot fa921b3c7b Migrate TextAttributeProps to Kotlin (#52452)
Summary:
Migrate com.facebook.react.views.text.TextAttributeProps to Kotlin.

## Changelog:

[Android][Changed] - Migrated TextAttributeProps to Kotlin. You might need to update your property access to use camelCase instead of Hungarian notation.

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

Test Plan:
```bash
yarn test-android
yarn android
```

Reviewed By: rshest

Differential Revision: D79341238

Pulled By: cortinico

fbshipit-source-id: 455c7b48f47a0cf240aaf330e1fa3674798e7237
2025-08-07 09:49:46 -07:00
272 changed files with 7438 additions and 4737 deletions
@@ -1,32 +0,0 @@
name: setup-xcode-build-cache
description: Add caching to iOS jobs to speed up builds
inputs:
hermes-version:
description: The version of hermes
required: true
flavor:
description: The flavor that is going to be built
default: Debug
use-frameworks:
description: Whether we are bulding with DynamicFrameworks or StaticLibraries
default: StaticLibraries
ruby-version:
description: The ruby version we are going to use
default: 2.6.10
runs:
using: composite
steps:
- name: See commands.yml with_xcodebuild_cache
shell: bash
run: echo "See commands.yml with_xcodebuild_cache"
- name: Cache podfile lock
uses: actions/cache@v4
with:
path: packages/rn-tester/Podfile.lock
key: v13-podfilelock-${{ github.job }}-NewArch-${{ inputs.flavor }}-${{ inputs.use-frameworks }}-${{ inputs.ruby-version }}-${{ hashfiles('packages/rn-tester/Podfile') }}-${{ inputs.hermes-version }}
- name: Cache cocoapods
uses: actions/cache@v4
with:
path: packages/rn-tester/Pods
key: v15-cocoapods-${{ github.job }}-NewArch-${{ inputs.flavor }}-${{ inputs.use-frameworks }}-${{ inputs.ruby-version }}-${{ hashfiles('packages/rn-tester/Podfile.lock') }}-${{ hashfiles('packages/rn-tester/Podfile') }}-${{ inputs.hermes-version}}
@@ -102,13 +102,6 @@ runs:
- name: Print ReactCore folder
shell: bash
run: ls -lR /tmp/ReactCore
- name: Setup xcode build cache
uses: ./.github/actions/setup-xcode-build-cache
with:
hermes-version: ${{ inputs.hermes-version }}
use-frameworks: ${{ inputs.use-frameworks }}
flavor: ${{ inputs.flavor }}
ruby-version: ${{ inputs.ruby-version }}
- name: Install CocoaPods dependencies
shell: bash
run: |
@@ -46,9 +46,7 @@ describe('FirebaseClient', () => {
expect(client.password).toBe('testpassword');
expect(client.apiKey).toBe('test-api-key');
expect(client.projectId).toBe('test-project');
expect(client.databaseUrl).toBe(
'test-project-default-rtdb.firebaseio.com',
);
expect(client.databaseUrl).toBe('test-project.firebaseio.com');
expect(client.idToken).toBeNull();
});
});
@@ -230,7 +228,7 @@ describe('FirebaseClient', () => {
expect(result).toEqual(mockData);
expect(global.fetch).toHaveBeenCalledWith(
'https://test-project-default-rtdb.firebaseio.com/nightly-results/2023-12-01.json?auth=existing-token',
'https://test-project.firebaseio.com/nightly-results/2023-12-01.json?auth=existing-token',
{
method: 'GET',
headers: {
@@ -275,7 +273,7 @@ describe('FirebaseClient', () => {
await client.makeDatabaseRequest('2023-12-01', 'PUT', testData);
expect(global.fetch).toHaveBeenCalledWith(
'https://test-project-default-rtdb.firebaseio.com/nightly-results/2023-12-01.json?auth=existing-token',
'https://test-project.firebaseio.com/nightly-results/2023-12-01.json?auth=existing-token',
{
method: 'PUT',
headers: {
@@ -301,7 +299,7 @@ describe('FirebaseClient', () => {
await client.storeResults('2023-12-01', results);
expect(global.fetch).toHaveBeenCalledWith(
'https://test-project-default-rtdb.firebaseio.com/nightly-results/2023-12-01.json?auth=existing-token',
'https://test-project.firebaseio.com/nightly-results/2023-12-01.json?auth=existing-token',
{
method: 'PUT',
headers: {
+1 -1
View File
@@ -15,7 +15,7 @@ class FirebaseClient {
this.password = process.env.FIREBASE_APP_PASS;
this.apiKey = process.env.FIREBASE_APP_APIKEY;
this.projectId = process.env.FIREBASE_APP_PROJECTNAME;
this.databaseUrl = `${this.projectId}-default-rtdb.firebaseio.com`;
this.databaseUrl = `${this.projectId}.firebaseio.com`;
this.idToken = null;
}
+20 -73
View File
@@ -1,71 +1,6 @@
# Changelog
## v0.81.0-rc.5
### Fixed
#### Android specific
- **Runtime:** Fixed `ReactHostImpl.nativeModules` always returning an empty list ([2f46a49](https://github.com/facebook/react-native/commit/2f46a49b8d8a11d5cf4342eee83c469b545c6779) by [@lukmccall](https://github.com/lukmccall))
## v0.81.0-rc.4 - Burned
## v0.81.0-rc.3
### Changed
- **Metro:** Metro to ^0.83.1 ([e247be793c](https://github.com/facebook/react-native/commit/e247be793c70a374955d798d8cbbc6eba58080ec) by [@motiz88](https://github.com/motiz88))
### Fixed
#### Android specific
- **rngp:** Fix a race condition with codegen libraries missing sources ([9013a9e666](https://github.com/facebook/react-native/commit/9013a9e66629677c47e1b69703f9fc8f4cbc1c2c) by [@cortinico](https://github.com/cortinico))
- **API:** Make accessors inside HeadlessJsTaskService open again ([7ef57163cb](https://github.com/facebook/react-native/commit/7ef57163cb016317e43e563da7ea181989f6abca) by [@cortinico](https://github.com/cortinico))
## v0.81.0-rc.2
### Changed
- **API:** `NewAppScreen` no longer internally handles device safe area, use optional `safeAreaInsets` prop (aligned in 0.81 template) ([732bd12dc2](https://github.com/facebook/react-native/commit/732bd12dc21460641ef01b23f2eb722f26b060d5) by [@huntie](https://github.com/huntie))
- **Babel:** Added support to `react-native/babel-preset` for a `hermesParserOptions` option, that expects an object that enables overriding `hermes-parser` options. ([0508eddfe6](https://github.com/facebook/react-native/commit/0508eddfe60df60cb3bfa4074ae199bd0e492d5f) by [@yungsters](https://github.com/yungsters))
### Fixed
#### iOS specific
- **Podspec:** Fixed issue with RNDeps release/debug switch failing ([4ee2b60a1e](https://github.com/facebook/react-native/commit/4ee2b60a1eacca744d58a7ad336ca9d3714289f6) by [@chrfalch](https://github.com/chrfalch))
- **Podspec:** Fixed missing script for resolving prebuilt xcframework when switching between release/debug ([2e55241a90](https://github.com/facebook/react-native/commit/2e55241a901b4cd95917de68ce9078928820a208) by [@chrfalch](https://github.com/chrfalch))
## v0.81.0-rc.1
### Added
#### iOS specific
- **CocoaPods** Add the `ENTERPRISE_REPOSITORY` env variable to cocoapods infra ([23f3bf9239](https://github.com/facebook/react-native/commit/23f3bf9239a849590f1c72b25732d0090780128c) by [@cipolleschi](https://github.com/cipolleschi))
- **Prebuild:** Add release/debug switch script for React-Core-prebuilt ([42d1a7934c](https://github.com/facebook/react-native/commit/42d1a7934cad4b2c92653e3fa7781c2af8f44df4) by [@chrfalch](https://github.com/chrfalch))
- **Prebuild:** Added support for using USE_FRAMEWORKS with prebuilt React Native Core ([40e45f5366](https://github.com/facebook/react-native/commit/40e45f53661ce80c3a6fbbf07f52dc900afcad52) by [@chrfalch](https://github.com/chrfalch))
### Changed
- **Metro:** Bump Metro to 0.83.0 ([6b9f5d622f](https://github.com/facebook/react-native/commit/6b9f5d622ffbe79da8f4e7b7d8094504a480425e) by [@robhogan](https://github.com/robhogan))
#### Android specific
- **Gradle:** Gradle to 8.14.3 ([6892dde363](https://github.com/facebook/react-native/commit/6892dde36373bbef2d0afe535ae818b1a7164f08) by [@cortinico](https://github.com/cortinico))
- **Gradle:** Expose `react_renderer_bridging` headers via prefab ([d1730ff960](https://github.com/facebook/react-native/commit/d1730ff960fcb9a01ee94b9e46e5a9fbb7d73f4a) by [@tomekzaw](https://github.com/tomekzaw))
- **Legacy Arch:** Introduce more deprecation warnings for Legacy Arch classes ([625f69f284](https://github.com/facebook/react-native/commit/625f69f284ddfd9c6beecaa4052a871d092053ef) by [@cortinico](https://github.com/cortinico))
### Fixed
- **Yoga:** Fixed nodes with `display: contents` set being cloned with the wrong owner ([d4b36b0300](https://github.com/facebook/react-native/commit/d4b36b03003eb2de9eaf5b57bb639bae8cc12f20) by [@j-piasecki](https://github.com/j-piasecki))
#### iOS specific
- **Podspec:** Fixed premature return in header file generation from podspec globs ([f2b064c2d4](https://github.com/facebook/react-native/commit/f2b064c2d40c39017ac2a31bf3caf8acef23038c) by [@chrfalch](https://github.com/chrfalch))
## v0.81.0-rc.0
## v0.81.0
### Breaking
@@ -126,6 +61,7 @@
#### iOS specific
- **borderWidth:** Add support for different `borderWidth`s ([70962ef3ed](https://github.com/facebook/react-native/commit/70962ef3ed06a76a96cb2e72c374dc028628c829) by [@a-klotz-p8](https://github.com/a-klotz-p8))
- **CocoaPods:** Add the `ENTERPRISE_REPOSITORY` env variable to cocoapods infra ([23f3bf9239](https://github.com/facebook/react-native/commit/23f3bf9239a849590f1c72b25732d0090780128c) by [@cipolleschi](https://github.com/cipolleschi))
- **Modal:** Allow to interactively swipe down `Modal`s. ([28986a7599](https://github.com/facebook/react-native/commit/28986a7599952a77b8b8e433f72ca837afde310e) by [@okwasniewski](https://github.com/okwasniewski))
- **Package.swift:** Added missing search path to `Package.swift` ([592b09781b](https://github.com/facebook/react-native/commit/592b09781bb94fe6dc00ba49c7a86649980fed5d) by [@chrfalch](https://github.com/chrfalch))
- **Prebuild:** Add more logging around `computeNightlyTarballURL` in ios pre-build ([1a6887bd70](https://github.com/facebook/react-native/commit/1a6887bd70cdefb8fbc421467de841ece74d5c6b) by [@cortinico](https://github.com/cortinico))
@@ -136,13 +72,17 @@
- **Prebuild:** Added building `XCFframework` from the prebuild script ([55534f518a](https://github.com/facebook/react-native/commit/55534f518aab53bcdc3fe12d987ab7ef6e620c77) by [@chrfalch](https://github.com/chrfalch))
- **Prebuild:** Added building swift package from the prebuild script ([3c01b1b6f0](https://github.com/facebook/react-native/commit/3c01b1b6f04d285c97bb182131135903b0c1cdd5) by [@chrfalch](https://github.com/chrfalch))
- **Prebuild:** Added downloading of hermes artifacts when pre-building for iOS. ([41d2b5de0a](https://github.com/facebook/react-native/commit/41d2b5de0af21c72227ef030dcddf208e2eb221a) by [@chrfalch](https://github.com/chrfalch))
- **Prebuild:** Add release/debug switch script for React-Core-prebuilt ([42d1a7934c](https://github.com/facebook/react-native/commit/42d1a7934cad4b2c92653e3fa7781c2af8f44df4) by [@chrfalch](https://github.com/chrfalch))
- **Prebuild:** Added support for using USE_FRAMEWORKS with prebuilt React Native Core ([40e45f5366](https://github.com/facebook/react-native/commit/40e45f53661ce80c3a6fbbf07f52dc900afcad52) by [@chrfalch](https://github.com/chrfalch))
- **runtime:** Added `HERMES_ENABLE_DEBUGGER` to debug configuration for the `reactRuntime` target. ([560ac23001](https://github.com/facebook/react-native/commit/560ac23001b02f19d4c6ca4ea493c17060cfaf5f) by [@chrfalch](https://github.com/chrfalch))
### Changed
- **API:** `NewAppScreen` no longer internally handles device safe area, use optional `safeAreaInsets` prop (aligned in 0.81 template) ([732bd12dc2](https://github.com/facebook/react-native/commit/732bd12dc21460641ef01b23f2eb722f26b060d5) by [@huntie](https://github.com/huntie))
- **Animated:** Animated now always flattens `props.style`, which fixes an error that results from `props.style` objects in which `AnimatedNode` instances are shadowed (i.e. flattened to not exist in the resulting `props.style` object). ([da520848c9](https://github.com/facebook/react-native/commit/da520848c931f356d013623c412af11dce7ff114) by [@yungsters](https://github.com/yungsters))
- **Animated:** Creates a feature flag that changes `Animated` to no longer produce invalid `props.style` if every `AnimatedNode` instance is shadowed via style flattening. ([5c8c5388fc](https://github.com/facebook/react-native/commit/5c8c5388fc53ef2430b0bb6bbbc628479819e23d) by [@yungsters](https://github.com/yungsters))
- **Animated:** Enabled a feature flag that optimizes `Animated` to reduce memory usage. ([2a13d20085](https://github.com/facebook/react-native/commit/2a13d200850e4f161a29b252a0ccedc158e53937) by [@yungsters](https://github.com/yungsters))
- **Babel:** Added support to `react-native/babel-preset` for a `hermesParserOptions` option, that expects an object that enables overriding `hermes-parser` options. ([0508eddfe6](https://github.com/facebook/react-native/commit/0508eddfe60df60cb3bfa4074ae199bd0e492d5f) by [@yungsters](https://github.com/yungsters))
- **Error handling:** Errors will no longer have the "js engine" suffix. ([a293925280](https://github.com/facebook/react-native/commit/a2939252803d5cd4b68340da08820174c30a53e6) by [@yungsters](https://github.com/yungsters))
- **Fibers:** Reduces memory usage, by improving memory management of parent alternate fibers. (Previously, a parent fiber might retain memory associated with shadow nodes from a previous commit.) ([0411c43b3a](https://github.com/facebook/react-native/commit/0411c43b3a239384c778baad22c7b4c501008449) by [@yungsters](https://github.com/yungsters))
- **infoLog:** Removed `infoLog` from `react-native` package ([8a0cfec815](https://github.com/facebook/react-native/commit/8a0cfec81584e966c9e6ea0f5e438022e0129bcd) by [@coado](https://github.com/coado))
@@ -150,24 +90,26 @@
- **Jest:** Improved default mocking for Jest unit tests. ([1fd9508ecc](https://github.com/facebook/react-native/commit/1fd9508ecc499df89b086e0c46035f43f6f78ad9) by [@yungsters](https://github.com/yungsters))
- **LegacyArchitecture:** Raise loglevel for assertion of `LegacyArchitecture` classes ([38a4b62211](https://github.com/facebook/react-native/commit/38a4b6221164d36eb4ac95c9f3bc7f7e7235e383) by [@mdvacca](https://github.com/mdvacca))
- **LegacyArchitecture:** Raise logLevel of `LegacyArchitecture` classes when minimizing of legacy architecture is enabled ([0d1cde7f36](https://github.com/facebook/react-native/commit/0d1cde7f36e9de72c997fc812bba023694c2a369) by [@mdvacca](https://github.com/mdvacca))
- **Metro:** Bump Metro to `^0.82.5` ([083644647e](https://github.com/facebook/react-native/commit/083644647eff502f484b3ba24f9d361d5df56546) by [@robhogan](https://github.com/robhogan))
- **Metro:** Metro to ^0.83.1 ([e247be793c](https://github.com/facebook/react-native/commit/e247be793c70a374955d798d8cbbc6eba58080ec) by [@motiz88](https://github.com/motiz88))
- **React DevTools:** Bumped React DevTools to `6.1.5` ([c302902b1d](https://github.com/facebook/react-native/commit/c302902b1db7e8f8ac5b61472c095dc0755d6d1c) by [@hoxyq](https://github.com/hoxyq))
- **RuntimeExecutor:** `RuntimeExecutor`: Remove noexcept from sync ui thread utils ([7ef278af50](https://github.com/facebook/react-native/commit/7ef278af505deba6b8a47876c6824f9a7fefa427) by [@RSNara](https://github.com/RSNara))
- **Typescript:** Bump `types/react` to `19.1` ([3ae9328571](https://github.com/facebook/react-native/commit/3ae932857174e9c39cd5d9c53922f849aa1401b1) by [@gabrieldonadel](https://github.com/gabrieldonadel))
#### Android specific
- **Android SDK:** Updated targetSdk to 36 in Android. ([477d8df312](https://github.com/facebook/react-native/commit/477d8df3126b325b8cc9b410f1eaeb56b727d4d9) by [@kikoso](https://github.com/kikoso))
- **APIs:** Deprecate `DefaultNewArchitectureEntryPoint.load(Boolean, Boolean, Boolean)` ([efdf73983c](https://github.com/facebook/react-native/commit/efdf73983cef1f371511b6e1efa5e01835ebcabb) by [@cortinico](https://github.com/cortinico))
- **APIs:** Make `com.facebook.react.views.common.ContextUtils` internal ([d1ef8f1fa3](https://github.com/facebook/react-native/commit/d1ef8f1fa36cbfc34d05c409abf693e4e1cac3de) by [@cortinico](https://github.com/cortinico))
- **deps:** Bump `AGP` to `8.11.0` ([04858ecbab](https://github.com/facebook/react-native/commit/04858ecbab808ddca80e20e76f1359619bb5e865) by [@cortinico](https://github.com/cortinico))
- **deps:** Bump `Gradle` to `8.14.2` ([e20bb56f3b](https://github.com/facebook/react-native/commit/e20bb56f3b4db0d3e69154b95b952b1fe8e29959) by [@cortinico](https://github.com/cortinico))
- **deps:** Bump `Gradle` to 8.14.3 ([6892dde363](https://github.com/facebook/react-native/commit/6892dde36373bbef2d0afe535ae818b1a7164f08) by [@cortinico](https://github.com/cortinico))
- **Gradle:** Expose `react_renderer_bridging` headers via prefab ([d1730ff960](https://github.com/facebook/react-native/commit/d1730ff960fcb9a01ee94b9e46e5a9fbb7d73f4a) by [@tomekzaw](https://github.com/tomekzaw))
- **JS FPS:** Hide JS FPS on performance overlay as not accurate ([feec8d0148](https://github.com/facebook/react-native/commit/feec8d014877b2177f1c7dded7eb9664f53ee471) by [@cortinico](https://github.com/cortinico))
- Updated targetSdk to 36 in Android. ([477d8df312](https://github.com/facebook/react-native/commit/477d8df3126b325b8cc9b410f1eaeb56b727d4d9) by [@kikoso](https://github.com/kikoso))
- **Kotlin:** Convert `UIManagerModuleConstantsHelper` to Kotlin ([45fd7feb9f](https://github.com/facebook/react-native/commit/45fd7feb9f083e5c8afc916732aed9795d344e09) by [@cortinico](https://github.com/cortinico))
- **Kotlin:** Migrate `ThemedReactContext` to Kotlin ([78c9671c24](https://github.com/facebook/react-native/commit/78c9671c241a86bedb17862e549842b7e36d77ea) by [@cortinico](https://github.com/cortinico))
- **Kotlin:** Convert `ReactViewGroup` to Kotlin ([48395d346b](https://github.com/facebook/react-native/commit/48395d346bc89f63d38889e58508304df0088e4f) by [@cortinico](https://github.com/cortinico))
- **Kotlin:** Migrate `com.facebook.react.LazyReactPackage` to Kotlin. ([b4ae5c1de1](https://github.com/facebook/react-native/commit/b4ae5c1de1003c343d43c3be1b59ee2b800b9258) by [@Xintre](https://github.com/Xintre))
- **Kotlin:** Apply Collections Kotlin DSL helpers in `ReactAndroid` package ([b2ffd34a39](https://github.com/facebook/react-native/commit/b2ffd34a392de2bddba5ee13248796ccc2db6039) by [@l2hyunwoo](https://github.com/l2hyunwoo))
- **Legacy Arch:** Introduce more deprecation warnings for Legacy Arch classes ([625f69f284](https://github.com/facebook/react-native/commit/625f69f284ddfd9c6beecaa4052a871d092053ef) by [@cortinico](https://github.com/cortinico))
#### iOS specific
@@ -223,19 +165,21 @@
- **Typescript:** Add `ImageSource` type to TypeScript ([42ca46b95c](https://github.com/facebook/react-native/commit/42ca46b95cf9938de00b76dc61948a4ae7116e2b) by [@okwasniewski](https://github.com/okwasniewski))
- **Typescript:** Devtools TS Types ([8f189fce03](https://github.com/facebook/react-native/commit/8f189fce03db367abdceca6ad57ae28b613fdd7d) by [@krystofwoldrich](https://github.com/krystofwoldrich))
- **Yoga:** Fix possible invalid measurements with width or height is zero pixels ([5cc4d0a086](https://github.com/facebook/react-native/commit/5cc4d0a086d450e0f9d8ab6194013348f9de1f58) by [@NickGerleman](https://github.com/NickGerleman))
- **Yoga:** Fixed nodes with `display: contents` set being cloned with the wrong owner ([d4b36b0300](https://github.com/facebook/react-native/commit/d4b36b03003eb2de9eaf5b57bb639bae8cc12f20) by [@j-piasecki](https://github.com/j-piasecki))
#### Android specific
- **API:** Make accessors inside HeadlessJsTaskService open again ([7ef57163cb](https://github.com/facebook/react-native/commit/7ef57163cb016317e43e563da7ea181989f6abca) by [@cortinico](https://github.com/cortinico))
- **BaseViewManager:** Remove focus change listener when dropping/recycling view instances ([94cbf206d6](https://github.com/facebook/react-native/commit/94cbf206d607477257c65039d97565a79e94c7dd) by [@Abbondanzo](https://github.com/Abbondanzo))
- **BoringLayout:** Include fallback line spacing in `BoringLayout` ([2fe6c1a947](https://github.com/facebook/react-native/commit/2fe6c1a94758223a5342fdfa90163971eb588e6a) by [@NickGerleman](https://github.com/NickGerleman))
- **Bridgeless:** Adding `shouldForwardToReactInstance` check in `ReactDelegate` for Bridgeless ([0f7bf66bba](https://github.com/facebook/react-native/commit/0f7bf66bba8498c89384e96ad9219cdad0107b0c) by [@arushikesarwani94](https://github.com/arushikesarwani94))
- **Codegen:** Fix combining schema in Codegen process to exclude platforms correctly ([6104ccdc6e](https://github.com/facebook/react-native/commit/6104ccdc6ef89c2d4da25e60dcc55d73038e023f) by [@arushikesarwani94](https://github.com/arushikesarwani94))
- **Edge To Edge:** Fix `Dimensions` `window` values on Android < 15 when edge-to-edge is enabled ([85d10ed904](https://github.com/facebook/react-native/commit/85d10ed90401a13de1f74aeddd773736195da285) by [@zoontek](https://github.com/zoontek))
- **FBReactNativeSpec:** Extract out `FBReactNativeSpec`'s core components including Unimplemented from auto-generated registry ([b417b0c2d5](https://github.com/facebook/react-native/commit/b417b0c2d56dc37f824c0e77e98d1014d21cd8f8) by [@arushikesarwani94](https://github.com/arushikesarwani94))
- **Gradle:** Fix Gradle v8.0 builds by using .set() for Property ([777397667c](https://github.com/facebook/react-native/commit/777397667c2625aab3fc907b9ef4bd564963d8bb) by [@meghancampbel9](https://github.com/meghancampbel9))
- **ImageFetcher:** Change `free` to `delete` to call destructor of `ImageFetcher` and release `contextContainer`. ([90da666691](https://github.com/facebook/react-native/commit/90da666691745ab9bf3930dc3347d8e51683099f) by [@WoLewicki](https://github.com/WoLewicki))
- **Modal:** Fix `Modal` first frame being rendered on top-left corner ([b950fa2afb](https://github.com/facebook/react-native/commit/b950fa2afb20e2213ff6c733cb1c2465b90406ef) by [@cortinico](https://github.com/cortinico))
- **onTextLayout:** Fix `onTextLayout` metrics not incorporating `ReactTextViewManagerCallback` ([a6a2884d63](https://github.com/facebook/react-native/commit/a6a2884d63717a42ac2bafd2054991ce8b32a2e9) by [@NickGerleman](https://github.com/NickGerleman))
- **RNGP:** Fix a race condition with codegen libraries missing sources ([9013a9e666](https://github.com/facebook/react-native/commit/9013a9e66629677c47e1b69703f9fc8f4cbc1c2c) by [@cortinico](https://github.com/cortinico))
- **Runtime:** Fixed `ReactHostImpl.nativeModules` always returning an empty list ([2f46a49](https://github.com/facebook/react-native/commit/2f46a49b8d8a11d5cf4342eee83c469b545c6779) by [@lukmccall](https://github.com/lukmccall))
- **Text:** Fix more text rounding bugs ([1fe3ff86c3](https://github.com/facebook/react-native/commit/1fe3ff86c364fad023ad1e426f26608699314339) by [@NickGerleman](https://github.com/NickGerleman))
- **Text:** Fix `TextLayoutManager` `MeasureMode` Regression ([99119a2104](https://github.com/facebook/react-native/commit/99119a210487af18983145fd374ff7ebc88931f3) by [@NickGerleman](https://github.com/NickGerleman))
- **TextInput:** Fix bug where focus would jump to top text input upon clearing a separate text input. ([79c47987b7](https://github.com/facebook/react-native/commit/79c47987b74ab044574fc542fd4b13a9f11aa491) by [@joevilches](https://github.com/joevilches))
@@ -243,10 +187,13 @@
#### iOS specific
- **Gradient**: Gradient interpolation for transparent colors ([097d482446](https://github.com/facebook/react-native/commit/097d482446b7a03ca0f8c7e0254f4d770e05c79c) by [@intergalacticspacehighway](https://github.com/intergalacticspacehighway))
- **Prebuild:** Fixed wrong path in prebuild hermes check ([be11f2ee77](https://github.com/facebook/react-native/commit/be11f2ee77fd793efe0a1aa225897a1924163925) by [@chrfalch](https://github.com/chrfalch))
- **Prebuild:** Fixed resolving build type when downloading hermes artifacts ([9371e20192](https://github.com/facebook/react-native/commit/9371e201927fd105e797bf06e43943dd21e04381) by [@chrfalch](https://github.com/chrfalch))
- **Package.swift:** Add missing `React-RCTSettings` to `Package.swift` ([e40c1d265a](https://github.com/facebook/react-native/commit/e40c1d265a2045730dcf751eed4ebf32e099f0c7) by [@chrfalch](https://github.com/chrfalch))
- **Package.swift:** Fixed defines in `Package.swift` ([e2f6ce4ddf](https://github.com/facebook/react-native/commit/e2f6ce4ddfbea5814fc5d8632df14daeae3636d1) by [@chrfalch](https://github.com/chrfalch))
- **Podspec:** Fixed premature return in header file generation from podspec globs ([f2b064c2d4](https://github.com/facebook/react-native/commit/f2b064c2d40c39017ac2a31bf3caf8acef23038c) by [@chrfalch](https://github.com/chrfalch))
- **Podspec:** Fixed issue with RNDeps release/debug switch failing ([4ee2b60a1e](https://github.com/facebook/react-native/commit/4ee2b60a1eacca744d58a7ad336ca9d3714289f6) by [@chrfalch](https://github.com/chrfalch))
- **Podspec:** Fixed missing script for resolving prebuilt xcframework when switching between release/debug ([2e55241a90](https://github.com/facebook/react-native/commit/2e55241a901b4cd95917de68ce9078928820a208) by [@chrfalch](https://github.com/chrfalch))
- **Prebuild:** Fixed wrong path in prebuild hermes check ([be11f2ee77](https://github.com/facebook/react-native/commit/be11f2ee77fd793efe0a1aa225897a1924163925) by [@chrfalch](https://github.com/chrfalch))
- **Prebuild:** Fixed resolving build type when downloading hermes artifacts ([9371e20192](https://github.com/facebook/react-native/commit/9371e201927fd105e797bf06e43943dd21e04381) by [@chrfalch](https://github.com/chrfalch))
- **RCTImage:** Allow for consuming `RCTImage` in Swift codebase by enabling "Defines Module" option ([1d80586730](https://github.com/facebook/react-native/commit/1d8058673085580f402ec3a320fce810db7ad2ef) by [@kkafar](https://github.com/kkafar))
- **RCTImageComponentView:** Fix `RCTImageComponentView` image loading after source props change with no layout invalidation ([cd5d74518b](https://github.com/facebook/react-native/commit/cd5d74518becb3355519373211d2f54ff7dbd208) by Nick Lefever)
- **RCTScreenSize:** Make `RCTScreenSize` take horizontal orientation into account ([50ce8c77a7](https://github.com/facebook/react-native/commit/50ce8c77a74f2f2574030db04dc88c6092e68ba8) by [@okwasniewski](https://github.com/okwasniewski))
@@ -91,7 +91,14 @@ declare module 'tinybench' {
beforeEach?: (this: Task) => void | Promise<void>,
};
export type Fn = () => Promise<mixed> | mixed;
export interface FnReturnedObject {
overriddenDuration?: number;
}
export type Fn = () =>
| Promise<void | FnReturnedObject>
| void
| FnReturnedObject;
declare export class Bench extends EventTarget {
concurrency: null | 'task' | 'bench';
+2 -2
View File
@@ -75,7 +75,7 @@
"eslint-plugin-babel": "^5.3.1",
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-ft-flow": "^2.0.1",
"eslint-plugin-jest": "^27.9.0",
"eslint-plugin-jest": "^29.0.1",
"eslint-plugin-jsx-a11y": "^6.6.0",
"eslint-plugin-react": "^7.30.1",
"eslint-plugin-react-native": "^4.0.0",
@@ -110,7 +110,7 @@
"signedsource": "^1.0.0",
"supports-color": "^7.1.0",
"temp-dir": "^2.0.0",
"tinybench": "^3.1.0",
"tinybench": "^4.1.0",
"typescript": "5.8.3",
"ws": "^6.2.3"
},
@@ -1,58 +1,58 @@
#!/usr/bin/env dotslash
// @generated SignedSource<<686df5695b32a90cd465412d979a1a3f>>
// @generated SignedSource<<14de73ea0ed751d80c7c687c6aeb123f>>
{
"name": "React Native DevTools",
"platforms": {
"linux-aarch64": {
"size": 113511487,
"size": 116120331,
"hash": "sha256",
"digest": "c22f7d5e029357f05055ce7c56cc284a0d441d558e103a7b7ebae118c67d0b95",
"digest": "5a1747bdb50f8140d96e99b31f9a603ceaf52e777e5dd59f65edacd87f8c6348",
"providers": [
{
"type": "http",
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQPRilWDJV8xyKEv9lqYn7Hf2kyZg6nqW8KctGZCXsU95lS_MTFyAmEULrB3J6hGCjqBY2Zl-uq_FjERAIgzbZFWX2eceacTbutBSOKEj6QTZzkVN_L1zPh2lGh24x29MHpkwUzw4E-kAXV43f-11QxqD7orI1QicyOnsmUqeRNKE_QjM9rNRsw6iE8"
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQMRq1ou56GjpsIRFHpozEYiPfCuVvgWQVwiMMPBbwKyBnebit8HDGKof5XgDHbAKCqAZSgC8L22eJETnqIUM3kEAMYNXcHviIGy41rsXKVDYDgyWlGFB1zP2WzHrjWagfD062Pt4q5GqvCG5RVlhz656BOsutU7B4pDXGFCIdry7FveKn0PXGxvd1E"
}
],
"format": "tar.gz",
"path": "React Native DevTools-linux-arm64/React Native DevTools"
},
"linux-x86_64": {
"size": 113244728,
"size": 116056146,
"hash": "sha256",
"digest": "d749aee18d6c969f033511ed631b439c578068cc20786974bc0ee707c6c2f177",
"digest": "b48a3e392ac482de8058917879cf07fd5934dcb84aa901d4fe0d29273b503f54",
"providers": [
{
"type": "http",
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQP8NAAXjHJ-9NJThip1nnmVim4yiS1tdYAXmWl2Remiluq5f13nXA8YEadsmGRLWxXz2WJouHXSK47ea4a30fxewyKeTt0niFn3T-lr_91m3Ve5ZS-FOZ_9CRVCkv5zC-Z1FlXJGOnphfWetIU10Pw9tho3IzjdSNlXle0XTrkJ2AyKSl4cKPaX"
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQOyyb_LXrME2ubBGSkEi1vDw-2hwuHgHwnR-kAGQyhJK7lnELQDXKX1xW_u0joDwbTOhmiptwenq07G2NFkrY3t_AXefb_xTu2qHzpmrsX2YcwJlewbprgbuX7Uvdhqncb_IRAnJ4ogYKHUg6CZBNmLCQsyDsoqmkXtJ9ikJcQeDu2aiqbb-RWJ"
}
],
"format": "tar.gz",
"path": "React Native DevTools-linux-x64/React Native DevTools"
},
"macos-aarch64": {
"size": 108805847,
"size": 110957864,
"hash": "sha256",
"digest": "dc4a6cfa3d2d8646db8793ef497e43ad72be54bb14ed96345d059880ff72ce1e",
"digest": "7964d83c857f12bb741abf4377771f3f3697b81df6283dd88d75ae43991afb73",
"providers": [
{
"type": "http",
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQPuZx9G4h30mUDM0hZ8y74LbzAi7-S6jnOqq8uyfDdIptLwIgpb8CKB8F2tduvaBFMGd7obwXd2NVy01r6XKVdgAK5-QTp8PYUPUE7VSCi6QAqobXcQ2uq_lY-jgyj8XkV4Ua4gA6KR609Bmh-beSTOrSqMymqVodaGqoGjB_9jVwfD99_PfFlex-Ta"
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQM7USVzavWxZkjOO6CasnSfPIfE08jJAkwfVO0qWiYBli136vpzA_HS89ZqsIsAC_GXeT7K-K9BxdON7z5qBoRMUygAay7z4DGT5OZ9YSf9MDCd0JOzah5_6s3ijw2j4eeRu8ZNYzI3aTutDXtPMJAb2KfBHGx2lEiSW5YK9idcB5Y2boAWeDXXX5nb"
}
],
"format": "tar.gz",
"path": "React Native DevTools.app/Contents/MacOS/React Native DevTools"
},
"macos-x86_64": {
"size": 113766610,
"size": 117827315,
"hash": "sha256",
"digest": "74178859ce6a1c26c32055e192b1b123822c76c827ea86a6dfdb5463b89b1ace",
"digest": "bab2fac43def4a82fb88300aac05180eeda24f31cc00402a3ff7ca2e612bd532",
"providers": [
{
"type": "http",
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQN6DjGhr8_L7N_cwrh8pi3cfNcbn9dot_QQpgwe3Vv-780FDgi6JUeMvbo_wbFoT2rogxfHZ0-NbXbKdWYwhGUoGeQuikT57QnVMOYuPUTjlQUgYy0Ng9XPhq3iSEYwlMV1XsUJuPFRUg-hIHcgaaA55JoTLXZ1fLYydhHnmgRxGHc4pxaHvSpTtQ"
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQPYS0ZRQ7RV1S-yy3tut6pRqcKdPcOiKfekrA5AXdd_M-HDaXLwJS57iAFU2K2X-EA_cyg25C3L-5L7O3eyNKPMToZHbV282GiojnNSKFNjsjj9_B737lOwHI_XqbDQEIiNJZ7NjbkZ8_iMKK-LNL-Ydha2ORWWqytuzP4sWQ6sm0XIxsdyQ6bOLw"
}
],
"format": "tar.gz",
+2 -2
View File
@@ -27,11 +27,11 @@
"license": "MIT",
"engines": {
"node": ">= 20.19.4",
"electron": ">=36.3.0"
"electron": ">=37.2.4"
},
"dependencies": {
"cross-spawn": "^7.0.6",
"electron": "36.3.0"
"electron": "37.2.4"
},
"devDependencies": {
"semver": "^7.1.3"
@@ -28,7 +28,7 @@
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-ft-flow": "^2.0.1",
"eslint-plugin-jest": "^27.9.0",
"eslint-plugin-jest": "^29.0.1",
"eslint-plugin-react": "^7.30.1",
"eslint-plugin-react-hooks": "^5.2.0",
"eslint-plugin-react-native": "^4.0.0"
@@ -29,7 +29,6 @@ import com.facebook.react.utils.JdkConfiguratorUtils.configureJavaToolChains
import com.facebook.react.utils.JsonUtils
import com.facebook.react.utils.NdkConfiguratorUtils.configureReactNativeNdk
import com.facebook.react.utils.ProjectUtils.needsCodegenFromPackageJson
import com.facebook.react.utils.PropertyUtils
import com.facebook.react.utils.findPackageJsonFile
import java.io.File
import kotlin.system.exitProcess
@@ -43,7 +42,6 @@ import org.gradle.internal.jvm.Jvm
class ReactPlugin : Plugin<Project> {
override fun apply(project: Project) {
checkJvmVersion(project)
checkLegacyArchProperty(project)
val extension = project.extensions.create("react", ReactExtension::class.java, project)
// We register a private extension on the rootProject so that project wide configs
@@ -116,30 +114,6 @@ class ReactPlugin : Plugin<Project> {
}
}
private fun checkLegacyArchProperty(project: Project) {
if ((project.hasProperty(PropertyUtils.NEW_ARCH_ENABLED) &&
!project.property(PropertyUtils.NEW_ARCH_ENABLED).toString().toBoolean()) ||
(project.hasProperty(PropertyUtils.SCOPED_NEW_ARCH_ENABLED) &&
!project.property(PropertyUtils.SCOPED_NEW_ARCH_ENABLED).toString().toBoolean())) {
project.logger.error(
"""
********************************************************************************
WARNING: Setting `newArchEnabled=false` in your `gradle.properties` file is not
supported anymore since React Native 0.82.
You can remove the line from your `gradle.properties` file.
The application will run with the New Architecture enabled by default.
********************************************************************************
"""
.trimIndent())
}
}
/** This function configures Android resources - in this case just the bundle */
private fun configureResources(project: Project, reactExtension: ReactExtension) {
project.extensions.getByType(ApplicationAndroidComponentsExtension::class.java).finalizeDsl {
@@ -7,8 +7,10 @@
package com.facebook.react
import com.facebook.react.utils.PropertyUtils
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.plugin.extraProperties
/**
* Gradle plugin applied to the `android/build.gradle` file.
@@ -18,13 +20,25 @@ import org.gradle.api.Project
*/
class ReactRootProjectPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.subprojects {
checkLegacyArchProperty(project)
project.subprojects { subproject ->
// As the :app project (i.e. ReactPlugin) configures both namespaces and JVM toolchains
// for libraries, its evaluation must happen before the libraries' evaluation.
// Eventually the configuration of namespace/JVM toolchain can be moved inside this plugin.
if (it.path != ":app") {
it.evaluationDependsOn(":app")
if (subproject.path != ":app") {
subproject.evaluationDependsOn(":app")
}
// We set the New Architecture properties to true for all subprojects. So that
// libraries don't need to be modified and can keep on using the isNewArchEnabled()
// function to check if property is set.
if (subproject.hasProperty(PropertyUtils.SCOPED_NEW_ARCH_ENABLED)) {
subproject.setProperty(PropertyUtils.SCOPED_NEW_ARCH_ENABLED, "true")
}
if (subproject.hasProperty(PropertyUtils.NEW_ARCH_ENABLED)) {
subproject.setProperty(PropertyUtils.NEW_ARCH_ENABLED, "true")
}
subproject.extraProperties.set(PropertyUtils.NEW_ARCH_ENABLED, "true")
subproject.extraProperties.set(PropertyUtils.SCOPED_NEW_ARCH_ENABLED, "true")
}
// We need to make sure that `:app:preBuild` task depends on all other subprojects' preBuild
// tasks. This is necessary in order to have all the codegen generated code before the CMake
@@ -43,4 +57,27 @@ class ReactRootProjectPlugin : Plugin<Project> {
}
}
}
private fun checkLegacyArchProperty(project: Project) {
if ((project.hasProperty(PropertyUtils.NEW_ARCH_ENABLED) &&
!project.property(PropertyUtils.NEW_ARCH_ENABLED).toString().toBoolean()) ||
(project.hasProperty(PropertyUtils.SCOPED_NEW_ARCH_ENABLED) &&
!project.property(PropertyUtils.SCOPED_NEW_ARCH_ENABLED).toString().toBoolean())) {
project.logger.error(
"""
********************************************************************************
WARNING: Setting `newArchEnabled=false` in your `gradle.properties` file is not
supported anymore since React Native 0.82.
You can remove the line from your `gradle.properties` file.
The application will run with the New Architecture enabled by default.
********************************************************************************
"""
.trimIndent())
}
}
}
@@ -717,7 +717,7 @@ InterfaceOnlyNativeComponentViewProps::InterfaceOnlyNativeComponentViewProps(
const InterfaceOnlyNativeComponentViewProps &sourceProps,
const RawProps &rawProps): ViewProps(context, sourceProps, rawProps),
title(convertRawProp(context, rawProps, \\"title\\", sourceProps.title, {\\"\\"})) {}
title(convertRawProp(context, rawProps, \\"title\\", sourceProps.title, {std::string{\\"\\"}})) {}
#ifdef RN_SERIALIZABLE_STATE
ComponentName InterfaceOnlyNativeComponentViewProps::getDiffPropsImplementationTarget() const {
@@ -1060,7 +1060,7 @@ StringPropNativeComponentViewProps::StringPropNativeComponentViewProps(
const StringPropNativeComponentViewProps &sourceProps,
const RawProps &rawProps): ViewProps(context, sourceProps, rawProps),
placeholder(convertRawProp(context, rawProps, \\"placeholder\\", sourceProps.placeholder, {\\"\\"})),
placeholder(convertRawProp(context, rawProps, \\"placeholder\\", sourceProps.placeholder, {std::string{\\"\\"}})),
defaultValue(convertRawProp(context, rawProps, \\"defaultValue\\", sourceProps.defaultValue, {})) {}
#ifdef RN_SERIALIZABLE_STATE
@@ -18,6 +18,7 @@ Object {
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/core/graphicsConversions.h>
#include <react/renderer/core/propsConversions.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/graphics/Color.h>
#include <react/renderer/graphics/Point.h>
#include <react/renderer/graphics/RectangleEdges.h>
@@ -89,6 +90,7 @@ static inline std::string toString(const ArrayPropsNativeComponentViewSizesMaskW
struct ArrayPropsNativeComponentViewObjectStruct {
std::string prop{};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ArrayPropsNativeComponentViewObjectStruct&) const = default;
@@ -133,6 +135,7 @@ struct ArrayPropsNativeComponentViewArrayOfObjectsStruct {
Float prop1{0.0};
int prop2{0};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ArrayPropsNativeComponentViewArrayOfObjectsStruct&) const = default;
@@ -203,6 +206,8 @@ class ArrayPropsNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -225,6 +230,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -243,6 +249,8 @@ class BooleanPropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -265,6 +273,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/graphics/Color.h>
namespace facebook::react {
@@ -283,6 +292,8 @@ class ColorPropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -306,6 +317,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/core/graphicsConversions.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <yoga/Yoga.h>
namespace facebook::react {
@@ -324,6 +336,8 @@ class DimensionPropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -346,6 +360,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -363,6 +378,8 @@ class EdgeInsetsPropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -385,6 +402,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -468,6 +486,8 @@ class EnumPropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -490,6 +510,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -507,6 +528,8 @@ class EventNestedObjectPropsNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -529,6 +552,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -546,6 +570,8 @@ class EventPropsNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -568,6 +594,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -591,6 +618,8 @@ class FloatPropsNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -613,6 +642,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/imagemanager/primitives.h>
namespace facebook::react {
@@ -631,6 +661,8 @@ class ImagePropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -653,6 +685,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -672,6 +705,8 @@ class IntegerPropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -694,6 +729,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -704,13 +740,15 @@ class InterfaceOnlyNativeComponentViewProps final : public ViewProps {
#pragma mark - Props
std::string title{\\"\\"};
std::string title{std::string{\\"\\"}};
#ifdef RN_SERIALIZABLE_STATE
ComponentName getDiffPropsImplementationTarget() const override;
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -733,6 +771,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -750,6 +789,8 @@ class MixedPropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -772,6 +813,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/graphics/Color.h>
#include <react/renderer/graphics/Point.h>
#include <react/renderer/imagemanager/primitives.h>
@@ -795,6 +837,8 @@ class MultiNativePropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -817,6 +861,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -834,6 +879,8 @@ class NoPropsNoEventsNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -858,6 +905,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/core/propsConversions.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/graphics/Color.h>
#include <react/renderer/graphics/Point.h>
#include <react/renderer/imagemanager/primitives.h>
@@ -918,13 +966,14 @@ static inline folly::dynamic toDynamic(const ObjectPropsNativeComponentIntEnumPr
}
#endif
struct ObjectPropsNativeComponentObjectPropStruct {
std::string stringProp{\\"\\"};
std::string stringProp{std::string{\\"\\"}};
bool booleanProp{false};
Float floatProp{0.0};
int intProp{0};
ObjectPropsNativeComponentStringEnumProp stringEnumProp{ObjectPropsNativeComponentStringEnumProp::Small};
ObjectPropsNativeComponentIntEnumProp intEnumProp{ObjectPropsNativeComponentIntEnumProp::IntEnumProp0};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ObjectPropsNativeComponentObjectPropStruct&) const = default;
@@ -983,6 +1032,7 @@ static inline folly::dynamic toDynamic(const ObjectPropsNativeComponentObjectPro
struct ObjectPropsNativeComponentObjectArrayPropStruct {
std::vector<std::string> array{};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ObjectPropsNativeComponentObjectArrayPropStruct&) const = default;
@@ -1018,6 +1068,7 @@ struct ObjectPropsNativeComponentObjectPrimitiveRequiredPropStruct {
SharedColor color{};
Point point{};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ObjectPropsNativeComponentObjectPrimitiveRequiredPropStruct&) const = default;
@@ -1073,6 +1124,8 @@ class ObjectPropsNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -1095,6 +1148,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/graphics/Point.h>
namespace facebook::react {
@@ -1113,6 +1167,8 @@ class PointPropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -1135,6 +1191,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -1145,7 +1202,7 @@ class StringPropNativeComponentViewProps final : public ViewProps {
#pragma mark - Props
std::string placeholder{\\"\\"};
std::string placeholder{std::string{\\"\\"}};
std::string defaultValue{};
#ifdef RN_SERIALIZABLE_STATE
@@ -1153,6 +1210,8 @@ class StringPropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -20,6 +20,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class ArrayPropsNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & ArrayPropsNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public ArrayPropsNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -94,6 +95,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class BooleanPropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & BooleanPropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public BooleanPropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -136,6 +138,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class ColorPropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & ColorPropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public ColorPropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -175,6 +178,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class DimensionPropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & DimensionPropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public DimensionPropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -213,6 +217,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class EdgeInsetsPropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & EdgeInsetsPropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public EdgeInsetsPropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -245,6 +250,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class EnumPropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & EnumPropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public EnumPropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -286,6 +292,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class EventNestedObjectPropsNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & EventNestedObjectPropsNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public EventNestedObjectPropsNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -324,6 +331,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class EventPropsNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & EventPropsNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public EventPropsNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -362,6 +370,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class FloatPropsNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & FloatPropsNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public FloatPropsNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -419,6 +428,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class ImagePropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & ImagePropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public ImagePropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -457,6 +467,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class IntegerPropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & IntegerPropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public IntegerPropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -501,6 +512,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class InterfaceOnlyNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & InterfaceOnlyNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public InterfaceOnlyNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -540,6 +552,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class MixedPropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & MixedPropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public MixedPropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -580,6 +593,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class MultiNativePropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & MultiNativePropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public MultiNativePropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -627,6 +641,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class NoPropsNoEventsNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & NoPropsNoEventsNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public NoPropsNoEventsNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -660,6 +675,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class ObjectPropsNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & ObjectPropsNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public ObjectPropsNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -705,6 +721,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class PointPropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & PointPropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public PointPropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -743,6 +760,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class StringPropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & StringPropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public StringPropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -717,7 +717,7 @@ InterfaceOnlyNativeComponentViewProps::InterfaceOnlyNativeComponentViewProps(
const InterfaceOnlyNativeComponentViewProps &sourceProps,
const RawProps &rawProps): ViewProps(context, sourceProps, rawProps),
title(convertRawProp(context, rawProps, \\"title\\", sourceProps.title, {\\"\\"})) {}
title(convertRawProp(context, rawProps, \\"title\\", sourceProps.title, {std::string{\\"\\"}})) {}
#ifdef RN_SERIALIZABLE_STATE
ComponentName InterfaceOnlyNativeComponentViewProps::getDiffPropsImplementationTarget() const {
@@ -1060,7 +1060,7 @@ StringPropNativeComponentViewProps::StringPropNativeComponentViewProps(
const StringPropNativeComponentViewProps &sourceProps,
const RawProps &rawProps): ViewProps(context, sourceProps, rawProps),
placeholder(convertRawProp(context, rawProps, \\"placeholder\\", sourceProps.placeholder, {\\"\\"})),
placeholder(convertRawProp(context, rawProps, \\"placeholder\\", sourceProps.placeholder, {std::string{\\"\\"}})),
defaultValue(convertRawProp(context, rawProps, \\"defaultValue\\", sourceProps.defaultValue, {})) {}
#ifdef RN_SERIALIZABLE_STATE
@@ -18,6 +18,7 @@ Object {
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/core/graphicsConversions.h>
#include <react/renderer/core/propsConversions.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/graphics/Color.h>
#include <react/renderer/graphics/Point.h>
#include <react/renderer/graphics/RectangleEdges.h>
@@ -89,6 +90,7 @@ static inline std::string toString(const ArrayPropsNativeComponentViewSizesMaskW
struct ArrayPropsNativeComponentViewObjectStruct {
std::string prop{};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ArrayPropsNativeComponentViewObjectStruct&) const = default;
@@ -133,6 +135,7 @@ struct ArrayPropsNativeComponentViewArrayOfObjectsStruct {
Float prop1{0.0};
int prop2{0};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ArrayPropsNativeComponentViewArrayOfObjectsStruct&) const = default;
@@ -203,6 +206,8 @@ class ArrayPropsNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -225,6 +230,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -243,6 +249,8 @@ class BooleanPropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -265,6 +273,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/graphics/Color.h>
namespace facebook::react {
@@ -283,6 +292,8 @@ class ColorPropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -306,6 +317,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/core/graphicsConversions.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <yoga/Yoga.h>
namespace facebook::react {
@@ -324,6 +336,8 @@ class DimensionPropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -346,6 +360,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -363,6 +378,8 @@ class EdgeInsetsPropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -385,6 +402,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -468,6 +486,8 @@ class EnumPropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -490,6 +510,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -507,6 +528,8 @@ class EventNestedObjectPropsNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -529,6 +552,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -546,6 +570,8 @@ class EventPropsNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -568,6 +594,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -591,6 +618,8 @@ class FloatPropsNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -613,6 +642,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/imagemanager/primitives.h>
namespace facebook::react {
@@ -631,6 +661,8 @@ class ImagePropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -653,6 +685,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -672,6 +705,8 @@ class IntegerPropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -694,6 +729,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -704,13 +740,15 @@ class InterfaceOnlyNativeComponentViewProps final : public ViewProps {
#pragma mark - Props
std::string title{\\"\\"};
std::string title{std::string{\\"\\"}};
#ifdef RN_SERIALIZABLE_STATE
ComponentName getDiffPropsImplementationTarget() const override;
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -733,6 +771,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -750,6 +789,8 @@ class MixedPropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -772,6 +813,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/graphics/Color.h>
#include <react/renderer/graphics/Point.h>
#include <react/renderer/imagemanager/primitives.h>
@@ -795,6 +837,8 @@ class MultiNativePropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -817,6 +861,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -834,6 +879,8 @@ class NoPropsNoEventsNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -858,6 +905,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/core/propsConversions.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/graphics/Color.h>
#include <react/renderer/graphics/Point.h>
#include <react/renderer/imagemanager/primitives.h>
@@ -918,13 +966,14 @@ static inline folly::dynamic toDynamic(const ObjectPropsNativeComponentIntEnumPr
}
#endif
struct ObjectPropsNativeComponentObjectPropStruct {
std::string stringProp{\\"\\"};
std::string stringProp{std::string{\\"\\"}};
bool booleanProp{false};
Float floatProp{0.0};
int intProp{0};
ObjectPropsNativeComponentStringEnumProp stringEnumProp{ObjectPropsNativeComponentStringEnumProp::Small};
ObjectPropsNativeComponentIntEnumProp intEnumProp{ObjectPropsNativeComponentIntEnumProp::IntEnumProp0};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ObjectPropsNativeComponentObjectPropStruct&) const = default;
@@ -983,6 +1032,7 @@ static inline folly::dynamic toDynamic(const ObjectPropsNativeComponentObjectPro
struct ObjectPropsNativeComponentObjectArrayPropStruct {
std::vector<std::string> array{};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ObjectPropsNativeComponentObjectArrayPropStruct&) const = default;
@@ -1018,6 +1068,7 @@ struct ObjectPropsNativeComponentObjectPrimitiveRequiredPropStruct {
SharedColor color{};
Point point{};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ObjectPropsNativeComponentObjectPrimitiveRequiredPropStruct&) const = default;
@@ -1073,6 +1124,8 @@ class ObjectPropsNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -1095,6 +1148,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/graphics/Point.h>
namespace facebook::react {
@@ -1113,6 +1167,8 @@ class PointPropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -1135,6 +1191,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -1145,7 +1202,7 @@ class StringPropNativeComponentViewProps final : public ViewProps {
#pragma mark - Props
std::string placeholder{\\"\\"};
std::string placeholder{std::string{\\"\\"}};
std::string defaultValue{};
#ifdef RN_SERIALIZABLE_STATE
@@ -1153,6 +1210,8 @@ class StringPropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -20,6 +20,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class ArrayPropsNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & ArrayPropsNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public ArrayPropsNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -94,6 +95,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class BooleanPropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & BooleanPropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public BooleanPropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -136,6 +138,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class ColorPropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & ColorPropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public ColorPropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -175,6 +178,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class DimensionPropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & DimensionPropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public DimensionPropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -213,6 +217,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class EdgeInsetsPropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & EdgeInsetsPropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public EdgeInsetsPropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -245,6 +250,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class EnumPropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & EnumPropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public EnumPropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -286,6 +292,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class EventNestedObjectPropsNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & EventNestedObjectPropsNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public EventNestedObjectPropsNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -324,6 +331,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class EventPropsNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & EventPropsNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public EventPropsNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -362,6 +370,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class FloatPropsNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & FloatPropsNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public FloatPropsNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -419,6 +428,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class ImagePropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & ImagePropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public ImagePropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -457,6 +467,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class IntegerPropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & IntegerPropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public IntegerPropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -501,6 +512,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class InterfaceOnlyNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & InterfaceOnlyNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public InterfaceOnlyNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -540,6 +552,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class MixedPropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & MixedPropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public MixedPropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -580,6 +593,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class MultiNativePropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & MultiNativePropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public MultiNativePropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -627,6 +641,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class NoPropsNoEventsNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & NoPropsNoEventsNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public NoPropsNoEventsNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -660,6 +675,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class ObjectPropsNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & ObjectPropsNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public ObjectPropsNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -705,6 +721,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class PointPropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & PointPropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public PointPropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -743,6 +760,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class StringPropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & StringPropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public StringPropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -46,9 +46,17 @@ try {
} catch (err) {
throw new Error(`Can't parse schema to JSON. ${schemaPath}`);
}
const includeGetDebugPropsImplementation: boolean =
libraryName.includes('FBReactNativeSpec');
RNCodegen.generate(
{libraryName, schema, outputDirectory, packageName, assumeNonnull},
{
libraryName,
schema,
outputDirectory,
packageName,
assumeNonnull,
includeGetDebugPropsImplementation,
},
{
generators: [
'descriptors',
@@ -81,6 +81,7 @@ export type GenerateFunction = (
packageName?: string,
assumeNonnull: boolean,
headerPrefix?: string,
includeGetDebugPropsImplementation?: boolean,
) => FilesOutput;
export type LibraryGeneratorsFunctions = $ReadOnly<{
@@ -94,6 +95,7 @@ export type LibraryOptions = $ReadOnly<{
packageName?: string, // Some platforms have a notion of package, which should be configurable.
assumeNonnull: boolean,
useLocalIncludePaths?: boolean,
includeGetDebugPropsImplementation?: boolean,
libraryGenerators?: LibraryGeneratorsFunctions,
}>;
@@ -255,6 +257,7 @@ module.exports = {
packageName,
assumeNonnull,
useLocalIncludePaths,
includeGetDebugPropsImplementation = false,
libraryGenerators = LIBRARY_GENERATORS,
}: LibraryOptions,
{generators, test}: LibraryConfig,
@@ -299,6 +302,7 @@ module.exports = {
packageName,
assumeNonnull,
headerPrefix,
includeGetDebugPropsImplementation,
).forEach((contents: string, fileName: string) => {
generatedFiles.push({
name: fileName,
@@ -190,7 +190,7 @@ function convertDefaultTypeToString(
if (typeAnnotation.default == null) {
return '';
}
return `"${typeAnnotation.default}"`;
return `std::string{"${typeAnnotation.default}"}`;
case 'Int32TypeAnnotation':
return String(typeAnnotation.default);
case 'DoubleTypeAnnotation':
@@ -61,6 +61,7 @@ module.exports = {
packageName?: string,
assumeNonnull: boolean = false,
headerPrefix?: string,
includeGetDebugPropsImplementation?: boolean = false,
): FilesOutput {
const fileName = 'ComponentDescriptors.cpp';
@@ -63,6 +63,7 @@ module.exports = {
packageName?: string,
assumeNonnull: boolean = false,
headerPrefix?: string,
includeGetDebugPropsImplementation?: boolean = false,
): FilesOutput {
const fileName = 'ComponentDescriptors.h';
@@ -381,6 +381,7 @@ module.exports = {
packageName?: string,
assumeNonnull: boolean = false,
headerPrefix?: string,
includeGetDebugPropsImplementation?: boolean = false,
): FilesOutput {
const fileName = 'RCTComponentViewHelpers.h';
@@ -413,6 +413,7 @@ module.exports = {
packageName?: string,
assumeNonnull: boolean = false,
headerPrefix?: string,
includeGetDebugPropsImplementation?: boolean = false,
): FilesOutput {
const moduleComponents: ComponentCollection = Object.keys(schema.modules)
.map(moduleName => {
@@ -320,6 +320,7 @@ module.exports = {
packageName?: string,
assumeNonnull: boolean = false,
headerPrefix?: string,
includeGetDebugPropsImplementation?: boolean = false,
): FilesOutput {
const moduleComponents: ComponentCollection = Object.keys(schema.modules)
.map(moduleName => {
@@ -77,6 +77,8 @@ function generatePropsDiffString(
className: string,
componentName: string,
component: ComponentShape,
debugProps: string = '',
includeGetDebugPropsImplementation?: boolean = false,
) {
const diffProps = component.props
.map(prop => {
@@ -134,6 +136,12 @@ function generatePropsDiffString(
})
.join('\n' + ' ');
const getDebugPropsString = `#if RN_DEBUG_STRING_CONVERTIBLE
SharedDebugStringConvertibleList ${className}::getDebugProps() const {
return ViewProps::getDebugProps()${debugProps && debugProps.length > 0 ? ` +\n\t\tSharedDebugStringConvertibleList{${debugProps}\n\t}` : ''};
}
#endif`;
return `
#ifdef RN_SERIALIZABLE_STATE
ComponentName ${className}::getDiffPropsImplementationTarget() const {
@@ -153,8 +161,11 @@ folly::dynamic ${className}::getDiffProps(
${diffProps}
return result;
}
#endif`;
#endif
${includeGetDebugPropsImplementation ? getDebugPropsString : ''}
`;
}
function generatePropsString(componentName: string, component: ComponentShape) {
return component.props
.map(prop => {
@@ -170,6 +181,24 @@ function generatePropsString(componentName: string, component: ComponentShape) {
.join(',\n' + ' ');
}
function generateDebugPropsString(
componentName: string,
component: ComponentShape,
) {
return component.props
.map(prop => {
if (prop.typeAnnotation.type === 'ObjectTypeAnnotation') {
// Skip ObjectTypeAnnotation because there is no generic `toString`
// method for it. We would have to define an interface that the structs implement.
return '';
}
const defaultValue = convertDefaultTypeToString(componentName, prop);
return `\n\t\t\tdebugStringConvertibleItem("${prop.name}", ${prop.name}${defaultValue ? `, ${defaultValue}` : ''})`;
})
.join(',');
}
function getClassExtendString(component: ComponentShape): string {
const extendString =
' ' +
@@ -202,6 +231,7 @@ module.exports = {
packageName?: string,
assumeNonnull: boolean = false,
headerPrefix?: string,
includeGetDebugPropsImplementation?: boolean = false,
): FilesOutput {
const fileName = 'Props.cpp';
const allImports: Set<string> = new Set([
@@ -209,6 +239,13 @@ module.exports = {
'#include <react/renderer/core/PropsParserContext.h>',
]);
if (includeGetDebugPropsImplementation) {
allImports.add('#include <react/renderer/core/graphicsConversions.h>');
allImports.add(
'#include <react/renderer/debug/debugStringConvertibleUtils.h>',
);
}
const componentProps = Object.keys(schema.modules)
.map(moduleName => {
const module = schema.modules[moduleName];
@@ -229,10 +266,15 @@ module.exports = {
const propsString = generatePropsString(componentName, component);
const extendString = getClassExtendString(component);
const debugProps = includeGetDebugPropsImplementation
? generateDebugPropsString(componentName, component)
: '';
const diffPropsString = generatePropsDiffString(
newName,
componentName,
component,
debugProps,
includeGetDebugPropsImplementation,
);
const imports = getImports(component.props);
@@ -65,14 +65,20 @@ const ClassTemplate = ({
className,
props,
extendClasses,
includeGetDebugPropsImplementation,
}: {
enums: string,
structs: string,
className: string,
props: string,
extendClasses: string,
}) =>
`
includeGetDebugPropsImplementation: boolean,
}) => {
const getDebugPropsString = `#if RN_DEBUG_STRING_CONVERTIBLE
SharedDebugStringConvertibleList getDebugProps() const override;
#endif`;
return `
${enums}
${structs}
class ${className} final${extendClasses} {
@@ -89,8 +95,11 @@ class ${className} final${extendClasses} {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
${includeGetDebugPropsImplementation ? getDebugPropsString : ''}
};
`.trim();
};
const EnumTemplate = ({
enumName,
@@ -178,6 +187,7 @@ const StructTemplate = ({
`struct ${structName} {
${fields}
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ${structName}&) const = default;
@@ -536,6 +546,7 @@ function getExtendsImports(
const imports: Set<string> = new Set();
imports.add('#include <react/renderer/core/PropsParserContext.h>');
imports.add('#include <react/renderer/debug/DebugStringConvertible.h>');
extendsProps.forEach(extendProps => {
switch (extendProps.type) {
@@ -783,6 +794,7 @@ module.exports = {
packageName?: string,
assumeNonnull: boolean = false,
headerPrefix?: string,
includeGetDebugPropsImplementation?: boolean = false,
): FilesOutput {
const fileName = 'Props.h';
@@ -831,6 +843,7 @@ module.exports = {
className: newName,
extendClasses: extendString,
props: propsString,
includeGetDebugPropsImplementation,
});
return replacedTemplate;
@@ -55,6 +55,7 @@ package ${packageName};
${imports}
@SuppressWarnings("deprecation")
public class ${className}<T extends ${extendClasses}, U extends BaseViewManager<T, ? extends LayoutShadowNode> & ${interfaceClassName}<T>> extends BaseViewManagerDelegate<T, U> {
public ${className}(U viewManager) {
super(viewManager);
@@ -299,6 +300,7 @@ module.exports = {
packageName?: string,
assumeNonnull: boolean = false,
headerPrefix?: string,
includeGetDebugPropsImplementation?: boolean = false,
): FilesOutput {
// TODO: This doesn't support custom package name yet.
const normalizedPackageName = 'com.facebook.react.viewmanagers';
@@ -238,6 +238,7 @@ module.exports = {
packageName?: string,
assumeNonnull: boolean = false,
headerPrefix?: string,
includeGetDebugPropsImplementation?: boolean = false,
): FilesOutput {
// TODO: This doesn't support custom package name yet.
const normalizedPackageName = 'com.facebook.react.viewmanagers';
@@ -54,6 +54,7 @@ module.exports = {
packageName?: string,
assumeNonnull: boolean = false,
headerPrefix?: string,
includeGetDebugPropsImplementation?: boolean = false,
): FilesOutput {
const fileName = 'ShadowNodes.cpp';
@@ -74,6 +74,7 @@ module.exports = {
packageName?: string,
assumeNonnull: boolean = false,
headerPrefix?: string,
includeGetDebugPropsImplementation?: boolean = false,
): FilesOutput {
const fileName = 'ShadowNodes.h';
@@ -50,6 +50,7 @@ module.exports = {
packageName?: string,
assumeNonnull: boolean = false,
headerPrefix?: string,
includeGetDebugPropsImplementation?: boolean = false,
): FilesOutput {
const fileName = 'States.cpp';
@@ -57,6 +57,7 @@ module.exports = {
packageName?: string,
assumeNonnull: boolean = false,
headerPrefix?: string,
includeGetDebugPropsImplementation?: boolean = false,
): FilesOutput {
const fileName = 'States.h';
@@ -347,7 +347,7 @@ CommandNativeComponentProps::CommandNativeComponentProps(
const CommandNativeComponentProps &sourceProps,
const RawProps &rawProps): ViewProps(context, sourceProps, rawProps),
accessibilityHint(convertRawProp(context, rawProps, \\"accessibilityHint\\", sourceProps.accessibilityHint, {\\"\\"})) {}
accessibilityHint(convertRawProp(context, rawProps, \\"accessibilityHint\\", sourceProps.accessibilityHint, {std::string{\\"\\"}})) {}
#ifdef RN_SERIALIZABLE_STATE
ComponentName CommandNativeComponentProps::getDiffPropsImplementationTarget() const {
@@ -1168,7 +1168,7 @@ InterfaceOnlyComponentProps::InterfaceOnlyComponentProps(
const InterfaceOnlyComponentProps &sourceProps,
const RawProps &rawProps): ViewProps(context, sourceProps, rawProps),
accessibilityHint(convertRawProp(context, rawProps, \\"accessibilityHint\\", sourceProps.accessibilityHint, {\\"\\"})) {}
accessibilityHint(convertRawProp(context, rawProps, \\"accessibilityHint\\", sourceProps.accessibilityHint, {std::string{\\"\\"}})) {}
#ifdef RN_SERIALIZABLE_STATE
ComponentName InterfaceOnlyComponentProps::getDiffPropsImplementationTarget() const {
@@ -1554,7 +1554,7 @@ StringPropComponentProps::StringPropComponentProps(
const StringPropComponentProps &sourceProps,
const RawProps &rawProps): ViewProps(context, sourceProps, rawProps),
accessibilityHint(convertRawProp(context, rawProps, \\"accessibilityHint\\", sourceProps.accessibilityHint, {\\"\\"})),
accessibilityHint(convertRawProp(context, rawProps, \\"accessibilityHint\\", sourceProps.accessibilityHint, {std::string{\\"\\"}})),
accessibilityRole(convertRawProp(context, rawProps, \\"accessibilityRole\\", sourceProps.accessibilityRole, {})) {}
#ifdef RN_SERIALIZABLE_STATE
@@ -18,6 +18,7 @@ Map {
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/core/graphicsConversions.h>
#include <react/renderer/core/propsConversions.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/graphics/Color.h>
#include <react/renderer/graphics/Point.h>
#include <react/renderer/imagemanager/primitives.h>
@@ -86,7 +87,8 @@ static inline std::string toString(const ArrayPropsNativeComponentSizesMaskWrapp
return result;
}
struct ArrayPropsNativeComponentObjectStruct {
std::string stringProp{\\"\\"};
std::string stringProp{std::string{\\"\\"}};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ArrayPropsNativeComponentObjectStruct&) const = default;
@@ -129,7 +131,8 @@ static inline void fromRawValue(const PropsParserContext& context, const RawValu
struct ArrayPropsNativeComponentArrayObjectStruct {
std::string stringProp{\\"\\"};
std::string stringProp{std::string{\\"\\"}};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ArrayPropsNativeComponentArrayObjectStruct&) const = default;
@@ -174,6 +177,7 @@ static inline void fromRawValue(const PropsParserContext& context, const RawValu
struct ArrayPropsNativeComponentArrayStruct {
std::vector<ArrayPropsNativeComponentArrayObjectStruct> object{};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ArrayPropsNativeComponentArrayStruct&) const = default;
@@ -215,7 +219,8 @@ static inline void fromRawValue(const PropsParserContext& context, const RawValu
struct ArrayPropsNativeComponentArrayOfArrayOfObjectStruct {
std::string stringProp{\\"\\"};
std::string stringProp{std::string{\\"\\"}};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ArrayPropsNativeComponentArrayOfArrayOfObjectStruct&) const = default;
@@ -286,6 +291,8 @@ class ArrayPropsNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -310,6 +317,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/core/propsConversions.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/graphics/Color.h>
#include <react/renderer/graphics/Point.h>
#include <react/renderer/imagemanager/primitives.h>
@@ -322,6 +330,7 @@ struct ArrayPropsNativeComponentNativePrimitivesStruct {
std::vector<ImageSource> srcs{};
std::vector<Point> points{};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ArrayPropsNativeComponentNativePrimitivesStruct&) const = default;
@@ -385,6 +394,8 @@ class ArrayPropsNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -407,6 +418,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -424,6 +436,8 @@ class BooleanPropNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -446,6 +460,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/graphics/Color.h>
namespace facebook::react {
@@ -464,6 +479,8 @@ class ColorPropNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -486,6 +503,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -503,6 +521,8 @@ class CommandNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -525,6 +545,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -535,13 +556,15 @@ class CommandNativeComponentProps final : public ViewProps {
#pragma mark - Props
std::string accessibilityHint{\\"\\"};
std::string accessibilityHint{std::string{\\"\\"}};
#ifdef RN_SERIALIZABLE_STATE
ComponentName getDiffPropsImplementationTarget() const override;
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -565,6 +588,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/core/graphicsConversions.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <yoga/Yoga.h>
namespace facebook::react {
@@ -583,6 +607,8 @@ class DimensionPropNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -605,6 +631,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -627,6 +654,8 @@ class DoublePropNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -649,6 +678,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -666,6 +696,8 @@ class EventsNestedObjectNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -688,6 +720,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -705,6 +738,8 @@ class EventsNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -727,6 +762,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -744,6 +780,8 @@ class InterfaceOnlyComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -766,6 +804,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -783,6 +822,8 @@ class ExcludedAndroidComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -805,6 +846,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -822,6 +864,8 @@ class ExcludedAndroidIosComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -844,6 +888,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -861,6 +906,8 @@ class ExcludedIosComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
class MultiFileIncludedNativeComponentProps final : public ViewProps {
@@ -877,6 +924,8 @@ class MultiFileIncludedNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -899,6 +948,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -921,6 +971,8 @@ class FloatPropNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -943,6 +995,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/imagemanager/primitives.h>
namespace facebook::react {
@@ -961,6 +1014,8 @@ class ImagePropNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -983,6 +1038,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/graphics/RectangleEdges.h>
namespace facebook::react {
@@ -1001,6 +1057,8 @@ class InsetsPropNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -1023,6 +1081,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -1077,6 +1136,8 @@ class Int32EnumPropsNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -1099,6 +1160,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -1118,6 +1180,8 @@ class IntegerPropNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -1140,6 +1204,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -1150,13 +1215,15 @@ class InterfaceOnlyComponentProps final : public ViewProps {
#pragma mark - Props
std::string accessibilityHint{\\"\\"};
std::string accessibilityHint{std::string{\\"\\"}};
#ifdef RN_SERIALIZABLE_STATE
ComponentName getDiffPropsImplementationTarget() const override;
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -1179,6 +1246,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -1196,6 +1264,8 @@ class MixedPropNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -1218,6 +1288,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/graphics/Color.h>
#include <react/renderer/graphics/Point.h>
#include <react/renderer/imagemanager/primitives.h>
@@ -1241,6 +1312,8 @@ class ImageColorPropNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -1263,6 +1336,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -1280,6 +1354,8 @@ class NoPropsNoEventsComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -1304,6 +1380,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/core/propsConversions.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/graphics/Color.h>
#include <react/renderer/graphics/Point.h>
#include <react/renderer/imagemanager/primitives.h>
@@ -1359,6 +1436,7 @@ static inline folly::dynamic toDynamic(const ObjectPropsIntEnumProp &value) {
struct ObjectPropsObjectPropObjectArrayPropStruct {
std::vector<std::string> array{};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ObjectPropsObjectPropObjectArrayPropStruct&) const = default;
@@ -1394,6 +1472,7 @@ struct ObjectPropsObjectPropObjectPrimitiveRequiredPropStruct {
SharedColor color{};
Point point{};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ObjectPropsObjectPropObjectPrimitiveRequiredPropStruct&) const = default;
@@ -1435,7 +1514,8 @@ static inline folly::dynamic toDynamic(const ObjectPropsObjectPropObjectPrimitiv
#endif
struct ObjectPropsObjectPropNestedPropANestedPropBStruct {
std::string nestedPropC{\\"\\"};
std::string nestedPropC{std::string{\\"\\"}};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ObjectPropsObjectPropNestedPropANestedPropBStruct&) const = default;
@@ -1470,6 +1550,7 @@ static inline folly::dynamic toDynamic(const ObjectPropsObjectPropNestedPropANes
struct ObjectPropsObjectPropNestedPropAStruct {
ObjectPropsObjectPropNestedPropANestedPropBStruct nestedPropB{};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ObjectPropsObjectPropNestedPropAStruct&) const = default;
@@ -1501,7 +1582,8 @@ static inline folly::dynamic toDynamic(const ObjectPropsObjectPropNestedPropAStr
#endif
struct ObjectPropsObjectPropNestedArrayAsPropertyArrayPropStruct {
std::string stringProp{\\"\\"};
std::string stringProp{std::string{\\"\\"}};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ObjectPropsObjectPropNestedArrayAsPropertyArrayPropStruct&) const = default;
@@ -1546,6 +1628,7 @@ static inline void fromRawValue(const PropsParserContext& context, const RawValu
struct ObjectPropsObjectPropNestedArrayAsPropertyStruct {
std::vector<ObjectPropsObjectPropNestedArrayAsPropertyArrayPropStruct> arrayProp{};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ObjectPropsObjectPropNestedArrayAsPropertyStruct&) const = default;
@@ -1577,11 +1660,11 @@ static inline folly::dynamic toDynamic(const ObjectPropsObjectPropNestedArrayAsP
#endif
struct ObjectPropsObjectPropStruct {
std::string stringProp{\\"\\"};
std::string stringProp{std::string{\\"\\"}};
bool booleanProp{false};
Float floatProp{0.0};
int intProp{0};
std::string stringUserDefaultProp{\\"user_default\\"};
std::string stringUserDefaultProp{std::string{\\"user_default\\"}};
bool booleanUserDefaultProp{true};
Float floatUserDefaultProp{3.14};
int intUserDefaultProp{9999};
@@ -1592,6 +1675,7 @@ struct ObjectPropsObjectPropStruct {
ObjectPropsObjectPropNestedPropAStruct nestedPropA{};
ObjectPropsObjectPropNestedArrayAsPropertyStruct nestedArrayAsProperty{};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ObjectPropsObjectPropStruct&) const = default;
@@ -1700,6 +1784,8 @@ class ObjectPropsProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -1722,6 +1808,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/graphics/Point.h>
namespace facebook::react {
@@ -1740,6 +1827,8 @@ class PointPropNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -1762,6 +1851,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -1803,6 +1893,8 @@ class StringEnumPropsNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -1825,6 +1917,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -1835,7 +1928,7 @@ class StringPropComponentProps final : public ViewProps {
#pragma mark - Props
std::string accessibilityHint{\\"\\"};
std::string accessibilityHint{std::string{\\"\\"}};
std::string accessibilityRole{};
#ifdef RN_SERIALIZABLE_STATE
@@ -1843,6 +1936,8 @@ class StringPropComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -1865,6 +1960,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -1882,6 +1978,8 @@ class MultiFile1NativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
class MultiFile2NativeComponentProps final : public ViewProps {
@@ -1898,6 +1996,8 @@ class MultiFile2NativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -1920,6 +2020,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -1937,6 +2038,8 @@ class MultiComponent1NativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
class MultiComponent2NativeComponentProps final : public ViewProps {
@@ -1953,6 +2056,8 @@ class MultiComponent2NativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -20,6 +20,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class ArrayPropsNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & ArrayPropsNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public ArrayPropsNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -95,6 +96,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class ArrayPropsNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & ArrayPropsNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public ArrayPropsNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -133,6 +135,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class BooleanPropNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & BooleanPropNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public BooleanPropNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -172,6 +175,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class ColorPropNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & ColorPropNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public ColorPropNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -211,6 +215,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class CommandNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & CommandNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public CommandNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -256,6 +261,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class CommandNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & CommandNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public CommandNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -310,6 +316,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class DimensionPropNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & DimensionPropNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public DimensionPropNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -348,6 +355,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class DoublePropNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & DoublePropNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public DoublePropNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -401,6 +409,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class EventsNestedObjectNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & EventsNestedObjectNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public EventsNestedObjectNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -439,6 +448,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class EventsNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & EventsNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public EventsNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -477,6 +487,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class InterfaceOnlyComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & InterfaceOnlyComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public InterfaceOnlyComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -513,6 +524,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class ExcludedIosComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & ExcludedIosComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public ExcludedIosComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -540,6 +552,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class MultiFileIncludedNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & MultiFileIncludedNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public MultiFileIncludedNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -578,6 +591,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class FloatPropNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & FloatPropNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public FloatPropNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -632,6 +646,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class ImagePropNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & ImagePropNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public ImagePropNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -671,6 +686,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class InsetsPropNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & InsetsPropNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public InsetsPropNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -709,6 +725,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class Int32EnumPropsNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & Int32EnumPropsNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public Int32EnumPropsNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -747,6 +764,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class IntegerPropNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & IntegerPropNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public IntegerPropNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -791,6 +809,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class InterfaceOnlyComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & InterfaceOnlyComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public InterfaceOnlyComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -830,6 +849,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class MixedPropNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & MixedPropNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public MixedPropNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -870,6 +890,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class ImageColorPropNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & ImageColorPropNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public ImageColorPropNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -917,6 +938,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class NoPropsNoEventsComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & NoPropsNoEventsComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public NoPropsNoEventsComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -950,6 +972,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class ObjectPropsManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & ObjectPropsManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public ObjectPropsManagerDelegate(U viewManager) {
super(viewManager);
@@ -989,6 +1012,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class PointPropNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & PointPropNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public PointPropNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -1027,6 +1051,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class StringEnumPropsNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & StringEnumPropsNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public StringEnumPropsNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -1065,6 +1090,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class StringPropComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & StringPropComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public StringPropComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -1106,6 +1132,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class MultiFile1NativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & MultiFile1NativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public MultiFile1NativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -1139,6 +1166,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class MultiFile2NativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & MultiFile2NativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public MultiFile2NativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -1177,6 +1205,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class MultiComponent1NativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & MultiComponent1NativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public MultiComponent1NativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -1210,6 +1239,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class MultiComponent2NativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & MultiComponent2NativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public MultiComponent2NativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -150,12 +150,11 @@ export default class Animation {
if (value != null) {
animatedValue.__onAnimatedValueUpdateReceived(value, offset);
if (
!(
ReactNativeFeatureFlags.cxxNativeAnimatedEnabled() &&
ReactNativeFeatureFlags.cxxNativeAnimatedRemoveJsSync()
)
) {
const isJsSyncRemoved =
ReactNativeFeatureFlags.cxxNativeAnimatedEnabled() &&
!ReactNativeFeatureFlags.disableFabricCommitInCXXAnimated() &&
ReactNativeFeatureFlags.cxxNativeAnimatedRemoveJsSync();
if (!isJsSyncRemoved) {
if (this.__isLooping === true) {
return;
}
@@ -146,6 +146,12 @@ using namespace facebook::react;
#if RN_DISABLE_OSS_PLUGIN_HEADER
return RCTTurboModulePluginClassProvider(name);
#else
if ([_delegate respondsToSelector:@selector(getModuleClassFromName:)]) {
Class moduleClass = [_delegate getModuleClassFromName:name];
if (moduleClass != nil) {
return moduleClass;
}
}
return RCTCoreModulesClassProvider(name);
#endif
}
@@ -176,7 +182,12 @@ using namespace facebook::react;
format:@"Delegate must provide a valid dependencyProvider"];
}
#endif
if ([_delegate respondsToSelector:@selector(getModuleInstanceFromClass:)]) {
id<RCTTurboModule> moduleInstance = [_delegate getModuleInstanceFromClass:moduleClass];
if (moduleInstance != nil) {
return moduleInstance;
}
}
return RCTAppSetupDefaultModuleFromClass(moduleClass, self.delegate.dependencyProvider);
}
@@ -0,0 +1,196 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
* @oncall react_native
*/
import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
import type {AccessibilityProps, HostInstance} from 'react-native';
import * as Fantom from '@react-native/fantom';
import * as React from 'react';
import {createRef} from 'react';
import {Pressable} from 'react-native';
import {Text} from 'react-native';
import accessibilityPropsSuite from 'react-native/src/private/__tests__/utilities/accessibilityPropsSuite';
import ensureInstance from 'react-native/src/private/__tests__/utilities/ensureInstance';
import ReactNativeElement from 'react-native/src/private/webapis/dom/nodes/ReactNativeElement';
describe('<Pressable>', () => {
describe('props', () => {
describe('style', () => {
it('can be set with ViewStyle', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(
<Pressable
style={{
width: 100,
height: 50,
backgroundColor: 'blue',
borderColor: 'red',
borderWidth: 3,
opacity: 40,
}}
/>,
);
});
expect(root.getRenderedOutput().toJSX()).toEqual(
<rn-view
accessible="true"
accessibilityState="{disabled:false,selected:false,checked:None,busy:false,expanded:null}"
backgroundColor="rgba(0, 0, 255, 1)"
borderWidth="3.000000"
height="50.000000"
opacity="40"
width="100.000000"
/>,
);
});
it('function that receives a boolean reflecting whether the component is currently pressed ', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(
<Pressable
style={({pressed}) => ({
backgroundColor: pressed ? 'red' : 'gray',
})}
/>,
);
});
expect(root.getRenderedOutput().toJSX()).toEqual(
<rn-view
accessible="true"
accessibilityState="{disabled:false,selected:false,checked:None,busy:false,expanded:null}"
backgroundColor="rgba(128, 128, 128, 1)"
/>,
);
});
});
describe('onPress', () => {
it('triggers callback when the element is pressed', () => {
const elementRef = createRef<HostInstance>();
const onPressCallback = jest.fn();
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(
<Pressable
ref={elementRef}
onPress={onPressCallback}
style={{height: 100}}
/>,
);
});
const element = ensureInstance(elementRef.current, ReactNativeElement);
Fantom.dispatchNativeEvent(element, 'click');
expect(onPressCallback).toHaveBeenCalledTimes(1);
});
});
describe('disabled', () => {
it('cannot be pressed', () => {
const elementRef = createRef<HostInstance>();
const root = Fantom.createRoot();
const onPressCallback = jest.fn();
Fantom.runTask(() => {
root.render(
<Pressable
ref={elementRef}
onPress={onPressCallback}
disabled={true}
/>,
);
});
const element = ensureInstance(elementRef.current, ReactNativeElement);
Fantom.dispatchNativeEvent(element, 'change', {value: true});
expect(onPressCallback).toHaveBeenCalledTimes(0);
});
});
describe('children', () => {
it('adds children to the component', () => {
const elementRef = createRef<HostInstance>();
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(
<Pressable ref={elementRef}>
<Text>the quick brown fox</Text>
</Pressable>,
);
});
const element = ensureInstance(elementRef.current, ReactNativeElement);
expect(element.childNodes.length).toBe(1);
expect(root.getRenderedOutput().toJSX()).toEqual(
<rn-view
accessible="true"
accessibilityState="{disabled:false,selected:false,checked:None,busy:false,expanded:null}">
<rn-paragraph
allowFontScaling="true"
ellipsizeMode="tail"
fontSize="NaN"
fontSizeMultiplier="NaN"
foregroundColor="rgba(0, 0, 0, 0)">
the quick brown fox
</rn-paragraph>
</rn-view>,
);
});
});
component ComponentWithAccessibilityProps(...props: AccessibilityProps) {
return <Pressable {...props} />;
}
accessibilityPropsSuite(ComponentWithAccessibilityProps);
});
describe('ref', () => {
describe('instance', () => {
it('is an element node', () => {
const elementRef = createRef<HostInstance>();
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Pressable ref={elementRef} />);
});
expect(elementRef.current).toBeInstanceOf(ReactNativeElement);
});
it('uses the "RN:View" tag name', () => {
const elementRef = createRef<HostInstance>();
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Pressable ref={elementRef} />);
});
const element = ensureInstance(elementRef.current, ReactNativeElement);
// Pressable is implemented with a <View> under the hood
expect(element.tagName).toBe('RN:View');
});
});
});
});
@@ -0,0 +1,47 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
import type {HostInstance} from 'react-native';
import * as Fantom from '@react-native/fantom';
import * as React from 'react';
import {createRef} from 'react';
import {Switch} from 'react-native';
import ensureInstance from 'react-native/src/private/__tests__/utilities/ensureInstance';
import ReactNativeElement from 'react-native/src/private/webapis/dom/nodes/ReactNativeElement';
describe('<ExampleComponent>', () => {
describe('props', () => {
describe('exampleProp', () => {
// more describe('<context>') or tests with it('<behaviour>')
});
// ... more props
});
describe('ref', () => {
describe('exampleMethod()', () => {
// more describe('<context>') or tests with it('<behaviour>')
});
// ... more methods
describe('instance', () => {
it('uses the "RN:Switch" tag name', () => {
const elementRef = createRef<HostInstance>();
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Switch ref={elementRef} />);
});
expect(elementRef.current).toBeInstanceOf(ReactNativeElement);
const element = ensureInstance(elementRef.current, ReactNativeElement);
expect(element.tagName).toBe('RN:Switch');
});
});
});
});
@@ -0,0 +1,92 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
import type {AccessibilityProps} from 'react-native';
import * as Fantom from '@react-native/fantom';
import * as React from 'react';
import {Text, TouchableWithoutFeedback, View} from 'react-native';
import accessibilityPropsSuite from 'react-native/src/private/__tests__/utilities/accessibilityPropsSuite';
import ensureInstance from 'react-native/src/private/__tests__/utilities/ensureInstance';
import ReactNativeElement from 'react-native/src/private/webapis/dom/nodes/ReactNativeElement';
describe('<TouchableWithoutFeedback>', () => {
describe('props', () => {
describe('empty props', () => {
it('renders without any props', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(
<TouchableWithoutFeedback>
<Text>Touchable</Text>
</TouchableWithoutFeedback>,
);
});
expect(
root.getRenderedOutput({props: ['isPressable']}).toJSX(),
).toEqual(<rn-paragraph isPressable="true">Touchable</rn-paragraph>);
});
});
component ComponentWithAccessibilityProps(...props: AccessibilityProps) {
return (
<TouchableWithoutFeedback {...props}>
<Text>Touchable</Text>
</TouchableWithoutFeedback>
);
}
accessibilityPropsSuite(ComponentWithAccessibilityProps);
});
describe('ref', () => {
describe('instance', () => {
it('is backed by its child', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(
<TouchableWithoutFeedback>
<Text>Touchable</Text>
</TouchableWithoutFeedback>,
);
});
expect(
ensureInstance(
root.document.documentElement.firstElementChild,
ReactNativeElement,
).tagName,
).toBe('RN:Paragraph');
Fantom.runTask(() => {
root.render(
<TouchableWithoutFeedback>
<View>
<Text>Touchable</Text>
</View>
</TouchableWithoutFeedback>,
);
});
expect(
ensureInstance(
root.document.documentElement.firstElementChild,
ReactNativeElement,
).tagName,
).toBe('RN:View');
});
});
});
});
@@ -0,0 +1,60 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
import measureRenderTime from '../../../../src/private/__tests__/utilities/measureRenderTime';
import ViewNativeComponent from '../ViewNativeComponent';
import * as Fantom from '@react-native/fantom';
import * as React from 'react';
import {View} from 'react-native';
let root;
let testViews: React.MixedElement;
const NUMBER_OF_VIEWS = 100;
const NUMBER_OF_ITERATIONS = 1000;
component Noop(children: React.Node, style?: mixed) {
return children;
}
Noop.displayName = 'Noop';
Fantom.unstable_benchmark
.suite('View vs. ViewNativeComponent', {minIterations: NUMBER_OF_ITERATIONS})
.test.each(
[Noop, ViewNativeComponent, View],
Component =>
`render ${NUMBER_OF_VIEWS} views (${Component.displayName ?? Component.name ?? 'ViewNativeComponent'})`,
() => {
return {
overriddenDuration: measureRenderTime(root, testViews),
};
},
Component => ({
beforeAll: () => {
let views: React.Node = null;
for (let i = 0; i < NUMBER_OF_VIEWS; i++) {
views = (
<Component style={{width: i + 1, height: i + 1}}>{views}</Component>
);
}
// $FlowExpectedError[incompatible-type]
testViews = views;
},
beforeEach: () => {
root = Fantom.createRoot();
},
afterEach: () => {
root.destroy();
},
}),
);
+212 -88
View File
@@ -10,13 +10,15 @@
import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
import type {HostInstance} from 'react-native';
import type {AccessibilityProps, HostInstance} from 'react-native';
import * as Fantom from '@react-native/fantom';
import * as React from 'react';
import {createRef} from 'react';
import {Image} from 'react-native';
import accessibilityPropsSuite from 'react-native/src/private/__tests__/utilities/accessibilityPropsSuite';
import ensureInstance from 'react-native/src/private/__tests__/utilities/ensureInstance';
import NativeFantom from 'react-native/src/private/testing/fantom/specs/NativeFantom';
import ReactNativeElement from 'react-native/src/private/webapis/dom/nodes/ReactNativeElement';
const LOGO_SOURCE = {uri: 'https://reactnative.dev/img/tiny_logo.png'};
@@ -33,7 +35,13 @@ describe('<Image>', () => {
});
expect(root.getRenderedOutput().toJSX()).toEqual(
<rn-image overflow="hidden" source-scale="1" source-type="remote" />,
<rn-image
accessibilityState="{disabled:false,selected:false,checked:None,busy:false,expanded:null}"
overflow="hidden"
resizeMode="cover"
source-scale="1"
source-type="remote"
/>,
);
Fantom.runTask(() => {
@@ -41,75 +49,17 @@ describe('<Image>', () => {
});
expect(root.getRenderedOutput().toJSX()).toEqual(
<rn-image overflow="hidden" source-scale="1" source-type="remote" />,
<rn-image
accessibilityState="{disabled:false,selected:false,checked:None,busy:false,expanded:null}"
overflow="hidden"
resizeMode="cover"
source-scale="1"
source-type="remote"
/>,
);
});
});
describe('accessibility', () => {
describe('accessible', () => {
it('indicates that image is an accessibility element', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Image accessible={true} />);
});
expect(
root.getRenderedOutput({props: ['accessible']}).toJSX(),
).toEqual(<rn-image accessible="true" />);
});
});
describe('accessibilityLabel', () => {
it('provides information for screen reader', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Image accessibilityLabel="React Native Logo" />);
});
expect(
root.getRenderedOutput({props: ['accessibilityLabel']}).toJSX(),
).toEqual(<rn-image accessibilityLabel="React Native Logo" />);
});
});
describe('alt', () => {
it('provides information for screen reader', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Image alt="React Native Logo" />);
});
expect(root.getRenderedOutput({props: ['^access']}).toJSX()).toEqual(
<rn-image
accessible="true"
accessibilityLabel="React Native Logo"
/>,
);
});
it('can be set alongside accessibilityLabel, but accessibilityLabel has higher priority', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(
<Image
alt="React Native Logo"
accessibilityLabel="React Native"
/>,
);
});
expect(root.getRenderedOutput({props: ['^access']}).toJSX()).toEqual(
<rn-image accessible="true" accessibilityLabel="React Native" />,
);
});
});
});
describe('blurRadius', () => {
it('provides blur radius for image', () => {
const root = Fantom.createRoot();
@@ -312,35 +262,47 @@ describe('<Image>', () => {
});
expect(root.getRenderedOutput({props: ['resizeMode']}).toJSX()).toEqual(
<rn-image />,
<rn-image resizeMode="cover" />,
);
});
it('can be set to "cover" explicitly', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Image resizeMode="cover" source={LOGO_SOURCE} />);
});
expect(root.getRenderedOutput({props: ['resizeMode']}).toJSX()).toEqual(
<rn-image resizeMode="cover" />,
);
});
it('can be set to "stretch", which is the same as not setting it', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Image resizeMode="stretch" source={LOGO_SOURCE} />);
});
expect(root.getRenderedOutput({props: ['resizeMode']}).toJSX()).toEqual(
<rn-image />,
);
});
(['stretch', 'contain', 'repeat', 'center'] as const).forEach(
resizeMode => {
it(`can be set to "${resizeMode}"`, () => {
const root = Fantom.createRoot();
(['contain', 'repeat', 'center'] as const).forEach(resizeMode => {
it(`can be set to "${resizeMode}"`, () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(
<Image resizeMode={resizeMode} source={LOGO_SOURCE} />,
);
});
expect(
root.getRenderedOutput({props: ['resizeMode']}).toJSX(),
).toEqual(<rn-image resizeMode={resizeMode} />);
Fantom.runTask(() => {
root.render(<Image resizeMode={resizeMode} source={LOGO_SOURCE} />);
});
},
);
expect(
root.getRenderedOutput({props: ['resizeMode']}).toJSX(),
).toEqual(<rn-image resizeMode={resizeMode} />);
});
});
});
describe('source', () => {
@@ -582,15 +544,15 @@ describe('<Image>', () => {
);
});
expect(root.getRenderedOutput().toJSX()).toEqual(
expect(
root
.getRenderedOutput({props: ['width', 'height', 'resizeMode']})
.toJSX(),
).toEqual(
<rn-image
height="100.000000"
overflow="hidden"
resizeMode="contain"
width="100.000000"
source-scale="1"
source-type="remote"
source-uri="https://reactnative.dev/img/tiny_logo.png"
/>,
);
});
@@ -623,6 +585,12 @@ describe('<Image>', () => {
);
});
});
component ComponentWithAccessibilityProps(...props: AccessibilityProps) {
return <Image {...props} source={LOGO_SOURCE} />;
}
accessibilityPropsSuite(ComponentWithAccessibilityProps, false);
});
describe('ref', () => {
@@ -653,4 +621,160 @@ describe('<Image>', () => {
});
});
});
describe('static methods', () => {
afterEach(() => {
NativeFantom.clearAllImages();
});
describe('getSize', () => {
it('returns the size of the image when image is loaded', () => {
const uri = 'https://reactnative.dev/img/tiny_logo.png';
NativeFantom.setImageResponse(uri, {
width: 100,
height: 100,
});
let size;
Fantom.runTask(() => {
Image.getSize(uri, (width, height) => {
size = {width, height};
});
});
expect(size).toEqual({width: 100, height: 100});
});
it('fails when image is not loaded', () => {
const uri = 'https://reactnative.dev/img/tiny_logo.png';
let size;
let err: ?Error;
Fantom.runTask(async () => {
Image.getSize(
uri,
(width, height) => {
size = {width, height};
},
(e: mixed) => {
if (e instanceof Error) {
err = e;
}
},
);
});
expect(size).toBeUndefined();
expect(err).toBeInstanceOf(Error);
expect(err?.message).toBe('image not loaded');
});
});
describe('getSizeWithHeaders', () => {
afterEach(() => {
NativeFantom.clearAllImages();
});
it('returns the size of the image when image is loaded', () => {
const uri = 'https://reactnative.dev/img/tiny_logo.png';
NativeFantom.setImageResponse(uri, {
width: 100,
height: 100,
});
let size;
Fantom.runTask(() => {
Image.getSizeWithHeaders(
uri,
{
Authorization: 'Basic RandomString',
},
(width: number, height: number) => {
size = {width, height};
},
);
});
expect(size).toEqual({width: 100, height: 100});
});
});
describe('prefetch', () => {
it('prefetches the image', () => {
const uri = 'https://reactnative.dev/img/tiny_logo.png';
NativeFantom.setImageResponse(uri, {
width: 100,
height: 100,
});
let result;
Fantom.runTask(async () => {
result = await Image.prefetch(uri);
});
expect(result).toEqual(true);
});
it('can fail to prefetch image', () => {
const uri = 'https://reactnative.dev/img/tiny_logo.png';
NativeFantom.setImageResponse(uri, {
width: 100,
height: 100,
errorMessage: 'Failed to prefetch image',
});
let result;
let error;
Fantom.runTask(async () => {
try {
result = await Image.prefetch(uri);
} catch (e) {
error = e;
}
});
expect(result).toEqual(undefined);
expect(error).toBeInstanceOf(Error);
expect(error?.message).toBe('Failed to prefetch image');
});
});
describe('queryCache', () => {
it('returns empty when image is not cached', () => {
const uri = 'https://reactnative.dev/img/tiny_logo.png';
let result;
Fantom.runTask(async () => {
result = await Image.queryCache([uri]);
});
expect(result).toEqual({});
});
(['disk', 'memory', 'disk/memory'] as const).forEach(cacheStatus => {
it(`returns the '${cacheStatus}' record when image is cached`, () => {
const uri = 'https://reactnative.dev/img/tiny_logo.png';
NativeFantom.setImageResponse(uri, {
width: 100,
height: 100,
cacheStatus,
});
let result;
Fantom.runTask(async () => {
result = await Image.queryCache([uri]);
});
expect(result).toEqual({
[uri]: cacheStatus,
});
});
});
});
});
});
@@ -0,0 +1,370 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
import type {HostInstance} from 'react-native';
import * as Fantom from '@react-native/fantom';
import * as React from 'react';
import {createRef} from 'react';
import {Modal} from 'react-native';
import ensureInstance from 'react-native/src/private/__tests__/utilities/ensureInstance';
import ReactNativeElement from 'react-native/src/private/webapis/dom/nodes/ReactNativeElement';
const DEFAULT_MODAL_CHILD_VIEW = (
<rn-view
backgroundColor="rgba(255, 255, 255, 1)"
flex="1.000000"
left="0.000000"
top="0.000000"
/>
);
describe('<Modal>', () => {
describe('props', () => {
it('renders a Modal with the default values when no props are passed', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Modal />);
});
expect(root.getRenderedOutput().toJSX()).toEqual(
<rn-modalHostView positionType="absolute" visible="true">
{DEFAULT_MODAL_CHILD_VIEW}
</rn-modalHostView>,
);
});
describe('animationType', () => {
it('renders a Modal with animationType="none" by default', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Modal animationType="none" />);
});
expect(
root.getRenderedOutput({props: ['animationType']}).toJSX(),
).toEqual(
<rn-modalHostView>
<rn-view />
</rn-modalHostView>,
);
});
(['slide', 'fade'] as const).forEach(animationType => {
it(`renders a Modal with animationType="${animationType}"`, () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Modal animationType={animationType} />);
});
expect(
root.getRenderedOutput({props: ['animationType']}).toJSX(),
).toEqual(
<rn-modalHostView animationType={animationType}>
<rn-view />
</rn-modalHostView>,
);
});
});
});
describe('presentationStyle', () => {
it('renders a Modal with presentationStyle="fullScreen" by default', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Modal presentationStyle="fullScreen" />);
});
expect(
root.getRenderedOutput({props: ['presentationStyle']}).toJSX(),
).toEqual(
<rn-modalHostView>
<rn-view />
</rn-modalHostView>,
);
});
(['pageSheet', 'formSheet', 'overFullScreen'] as const).forEach(
presentationStyle => {
it(`renders a Modal with presentationStyle="${presentationStyle}"`, () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Modal presentationStyle={presentationStyle} />);
});
expect(
root.getRenderedOutput({props: ['presentationStyle']}).toJSX(),
).toEqual(
<rn-modalHostView presentationStyle={presentationStyle}>
<rn-view />
</rn-modalHostView>,
);
});
},
);
});
describe('transparent', () => {
it('renders a Modal with transparent="true"', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Modal transparent={true} />);
});
expect(
root
.getRenderedOutput({props: ['transparent', 'presentationStyle']})
.toJSX(),
).toEqual(
<rn-modalHostView
transparent="true"
presentationStyle="overFullScreen">
<rn-view />
</rn-modalHostView>,
);
});
it('renders a Modal with transparent="false"', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Modal transparent={false} />);
});
expect(
root
.getRenderedOutput({props: ['transparent', 'presentationStyle']})
.toJSX(),
).toEqual(
<rn-modalHostView>
<rn-view />
</rn-modalHostView>,
);
});
});
describe('statusBarTranslucent', () => {
it('renders a Modal with statusBarTranslucent="true"', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Modal statusBarTranslucent={true} />);
});
expect(
root.getRenderedOutput({props: ['statusBarTranslucent']}).toJSX(),
).toEqual(
<rn-modalHostView statusBarTranslucent="true">
<rn-view />
</rn-modalHostView>,
);
});
it('renders a Modal with statusBarTranslucent="false"', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Modal statusBarTranslucent={false} />);
});
expect(
root.getRenderedOutput({props: ['statusBarTranslucent']}).toJSX(),
).toEqual(
<rn-modalHostView>
<rn-view />
</rn-modalHostView>,
);
});
});
describe('navigationBarTranslucent', () => {
it('renders a Modal with navigationBarTranslucent="true" and statusBarTranslucent="true"', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
// navigationBarTranslucent=true with statusBarTranslucent=false is not supported
// and it emits a warning.
root.render(
<Modal
navigationBarTranslucent={true}
statusBarTranslucent={true}
/>,
);
});
expect(
root
.getRenderedOutput({
props: ['navigationBarTranslucent', 'statusBarTranslucent'],
})
.toJSX(),
).toEqual(
<rn-modalHostView
navigationBarTranslucent="true"
statusBarTranslucent="true">
<rn-view />
</rn-modalHostView>,
);
});
it('renders a Modal with navigationBarTranslucent="false"', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Modal navigationBarTranslucent={false} />);
});
expect(
root
.getRenderedOutput({
props: ['navigationBarTranslucent', 'statusBarTranslucent'],
})
.toJSX(),
).toEqual(
<rn-modalHostView>
<rn-view />
</rn-modalHostView>,
);
});
});
describe('hardwareAccelerated', () => {
it('renders a Modal with hardwareAccelerated="true"', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Modal hardwareAccelerated={true} />);
});
expect(
root.getRenderedOutput({props: ['hardwareAccelerated']}).toJSX(),
).toEqual(
<rn-modalHostView hardwareAccelerated="true">
<rn-view />
</rn-modalHostView>,
);
});
it('renders a Modal with hardwareAccelerated="false"', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Modal hardwareAccelerated={false} />);
});
expect(
root.getRenderedOutput({props: ['hardwareAccelerated']}).toJSX(),
).toEqual(
<rn-modalHostView>
<rn-view />
</rn-modalHostView>,
);
});
});
describe('visible', () => {
it('renders a Modal with visible="true"', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Modal visible={true} />);
});
expect(root.getRenderedOutput({props: ['visible']}).toJSX()).toEqual(
<rn-modalHostView visible="true">
<rn-view />
</rn-modalHostView>,
);
});
it('renders nothing when visible="false"', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Modal visible={false} />);
});
expect(root.getRenderedOutput({props: ['visible']}).toJSX()).toBeNull();
});
});
describe('allowSwipeDismissal', () => {
it('renders a Modal with allowSwipeDismissal="true"', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Modal allowSwipeDismissal={true} />);
});
expect(
root.getRenderedOutput({props: ['allowSwipeDismissal']}).toJSX(),
).toEqual(
<rn-modalHostView allowSwipeDismissal="true">
<rn-view />
</rn-modalHostView>,
);
});
it('renders a Modal with allowSwipeDismissal="false"', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Modal allowSwipeDismissal={false} />);
});
expect(
root.getRenderedOutput({props: ['allowSwipeDismissal']}).toJSX(),
).toEqual(
<rn-modalHostView>
<rn-view />
</rn-modalHostView>,
);
});
});
describe('animated', () => {
[true, false].forEach(animated => {
// The 'animated' prop is deprecated and ignored when the Modal is rendered
// Users should use the 'animationType' prop instead.
it(`[DEPRECATED] renders a Modal with animated="${animated ? 'true' : 'false'}"`, () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Modal animated={animated} />);
});
expect(root.getRenderedOutput({props: ['animated']}).toJSX()).toEqual(
<rn-modalHostView>
<rn-view />
</rn-modalHostView>,
);
});
});
});
// ... more props
});
describe('ref', () => {
describe('exampleMethod()', () => {
// more describe('<context>') or tests with it('<behaviour>')
});
// ... more methods
describe('instance', () => {
it('uses the "RN:ModalHostView" tag name', () => {
const elementRef = createRef<HostInstance>();
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Modal ref={elementRef} />);
});
expect(elementRef.current).toBeInstanceOf(ReactNativeElement);
const element = ensureInstance(elementRef.current, ReactNativeElement);
expect(element.tagName).toBe('RN:ModalHostView');
});
});
});
});
+409 -10
View File
@@ -11,18 +11,412 @@
import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
import type {HostInstance} from 'react-native';
import type {Role} from '../../Components/View/ViewAccessibility';
import type {AccessibilityProps, HostInstance} from 'react-native';
import ensureInstance from '../../../src/private/__tests__/utilities/ensureInstance';
import * as Fantom from '@react-native/fantom';
import * as React from 'react';
import {createRef} from 'react';
import {Text} from 'react-native';
import accessibilityPropsSuite from 'react-native/src/private/__tests__/utilities/accessibilityPropsSuite';
import ReactNativeElement from 'react-native/src/private/webapis/dom/nodes/ReactNativeElement';
import ReadOnlyText from 'react-native/src/private/webapis/dom/nodes/ReadOnlyText';
const TEST_TEXT = 'the text';
describe('<Text>', () => {
describe('props', () => {
describe('empty props', () => {
it('renders an empty element when there are no props', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Text>{TEST_TEXT}</Text>);
});
expect(root.getRenderedOutput().toJSX()).toEqual(
<rn-paragraph
allowFontScaling="true"
ellipsizeMode="tail"
fontSize="NaN"
fontSizeMultiplier="NaN"
foregroundColor="rgba(0, 0, 0, 0)">
{TEST_TEXT}
</rn-paragraph>,
);
});
});
describe('adjustsFontSizeToFit', () => {
it(`can be set to "true"`, () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Text adjustsFontSizeToFit={true}>{TEST_TEXT}</Text>);
});
expect(
root.getRenderedOutput({props: ['adjustsFontSizeToFit']}).toJSX(),
).toEqual(
<rn-paragraph adjustsFontSizeToFit="true">{TEST_TEXT}</rn-paragraph>,
);
});
it(`has 'false' as default`, () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Text>{TEST_TEXT}</Text>);
});
expect(
root.getRenderedOutput({props: ['adjustsFontSizeToFit']}).toJSX(),
).toEqual(<rn-paragraph>{TEST_TEXT}</rn-paragraph>);
});
});
describe('allowFontScaling', () => {
([true, false] as const).forEach(propVal => {
it(`can be set to "${propVal.toString()}"`, () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Text allowFontScaling={propVal}>{TEST_TEXT}</Text>);
});
expect(
root.getRenderedOutput({props: ['allowFontScaling']}).toJSX(),
).toEqual(
<rn-paragraph allowFontScaling={propVal.toString()}>
{TEST_TEXT}
</rn-paragraph>,
);
});
});
it(`has 'true' as default`, () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Text>{TEST_TEXT}</Text>);
});
expect(
root.getRenderedOutput({props: ['allowFontScaling']}).toJSX(),
).toEqual(
<rn-paragraph allowFontScaling={'true'}>{TEST_TEXT}</rn-paragraph>,
);
});
});
describe('ellipsizeMode', () => {
it(`has 'tail' as default on JS side`, () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Text>{TEST_TEXT}</Text>);
});
expect(
root.getRenderedOutput({props: ['ellipsizeMode']}).toJSX(),
).toEqual(
<rn-paragraph ellipsizeMode="tail">{TEST_TEXT}</rn-paragraph>,
);
});
it(`has 'clip' as default on C++ side`, () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Text ellipsizeMode="clip">{TEST_TEXT}</Text>);
});
expect(
root.getRenderedOutput({props: ['ellipsizeMode']}).toJSX(),
).toEqual(<rn-paragraph>{TEST_TEXT}</rn-paragraph>);
});
(['head', 'middle', 'tail'] as const).forEach(propVal => {
it(`can be set to "${propVal}"`, () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Text ellipsizeMode={propVal}>{TEST_TEXT}</Text>);
});
expect(
root.getRenderedOutput({props: ['ellipsizeMode']}).toJSX(),
).toEqual(
<rn-paragraph ellipsizeMode={propVal}>{TEST_TEXT}</rn-paragraph>,
);
});
});
});
describe('id and nativeID', () => {
it(`has 'id' propagated correctly`, () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Text id="alpha">{TEST_TEXT}</Text>);
});
expect(root.getRenderedOutput({props: ['nativeID']}).toJSX()).toEqual(
<rn-paragraph nativeID={'alpha'}>{TEST_TEXT}</rn-paragraph>,
);
});
it(`has 'nativeID' propagated correctly`, () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Text nativeID="alpha">{TEST_TEXT}</Text>);
});
expect(root.getRenderedOutput({props: ['nativeID']}).toJSX()).toEqual(
<rn-paragraph nativeID={'alpha'}>{TEST_TEXT}</rn-paragraph>,
);
});
it(`has a precedence of 'id' over 'nativeID'`, () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(
<Text id="alpha" nativeID="gamma">
{TEST_TEXT}
</Text>,
);
});
expect(
root.getRenderedOutput({props: ['id', 'nativeID']}).toJSX(),
).toEqual(<rn-paragraph nativeID={'alpha'}>{TEST_TEXT}</rn-paragraph>);
});
});
describe('maxFontSizeMultiplier', () => {
it(`propagates valid numbers correctly`, () => {
const root = Fantom.createRoot();
[-1, 0, 1, 3, 1000].forEach(val => {
Fantom.runTask(() => {
root.render(<Text maxFontSizeMultiplier={val}>{TEST_TEXT}</Text>);
});
expect(
root.getRenderedOutput({props: ['maxFontSizeMultiplier']}).toJSX(),
).toEqual(
<rn-paragraph maxFontSizeMultiplier={val.toString()}>
{TEST_TEXT}
</rn-paragraph>,
);
});
});
});
describe('numberOfLines', () => {
let originalConsoleError = null;
afterEach(() => {
if (originalConsoleError != null) {
// $FlowExpectedError[cannot-write]
console.error = originalConsoleError;
originalConsoleError = null;
}
});
it(`doesn't allow negative numbers`, () => {
originalConsoleError = console.error;
// $FlowExpectedError[cannot-write]
console.error = jest.fn();
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Text numberOfLines={-1}>{TEST_TEXT}</Text>);
});
expect(
// NB. "numberOfLines" is mapped to "maximumNumberOfLines" in C++
root.getRenderedOutput({props: ['maximumNumberOfLines']}).toJSX(),
).toEqual(<rn-paragraph>{TEST_TEXT}</rn-paragraph>);
});
it(`has 0 as defult`, () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Text numberOfLines={0}>{TEST_TEXT}</Text>);
});
expect(
root.getRenderedOutput({props: ['maximumNumberOfLines']}).toJSX(),
).toEqual(<rn-paragraph>{TEST_TEXT}</rn-paragraph>);
});
it(`propagates valid numbers correctly`, () => {
const root = Fantom.createRoot();
[3, 1000].forEach(val => {
Fantom.runTask(() => {
root.render(<Text numberOfLines={val}>{TEST_TEXT}</Text>);
});
expect(
root.getRenderedOutput({props: ['maximumNumberOfLines']}).toJSX(),
).toEqual(
<rn-paragraph maximumNumberOfLines={val.toString()}>
{TEST_TEXT}
</rn-paragraph>,
);
});
});
});
describe('role', () => {
it(`has none by default`, () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Text>{TEST_TEXT}</Text>);
});
expect(root.getRenderedOutput({props: ['role']}).toJSX()).toEqual(
<rn-paragraph>{TEST_TEXT}</rn-paragraph>,
);
});
it(`maps invalid values to 'none'`, () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
// $FlowExpectedError[incompatible-type]
root.render(<Text role="__some_invalid_value">{TEST_TEXT}</Text>);
});
expect(root.getRenderedOutput({props: ['role']}).toJSX()).toEqual(
<rn-paragraph role="none">{TEST_TEXT}</rn-paragraph>,
);
});
it(`propagates correctly all possible values`, () => {
const root = Fantom.createRoot();
(
[
'alert',
'alertdialog',
'application',
'article',
'banner',
'button',
'cell',
'checkbox',
'columnheader',
'combobox',
'complementary',
'contentinfo',
'definition',
'dialog',
'directory',
'document',
'feed',
'figure',
'form',
'grid',
'group',
'heading',
'img',
'link',
'list',
'listitem',
'log',
'main',
'marquee',
'math',
'menu',
'menubar',
'menuitem',
'meter',
'navigation',
'none',
'note',
'option',
'presentation',
'progressbar',
'radio',
'radiogroup',
'region',
'row',
'rowgroup',
'rowheader',
'scrollbar',
'searchbox',
'separator',
'slider',
'spinbutton',
'status',
'summary',
'switch',
'tab',
'table',
'tablist',
'tabpanel',
'term',
'timer',
'toolbar',
'tooltip',
'tree',
'treegrid',
'treeitem',
'treeitem',
] as Array<Role>
).forEach(propVal => {
Fantom.runTask(() => {
root.render(<Text role={propVal}>{TEST_TEXT}</Text>);
});
expect(root.getRenderedOutput({props: ['role']}).toJSX()).toEqual(
<rn-paragraph role={propVal}>{TEST_TEXT}</rn-paragraph>,
);
});
});
});
describe('selectable', () => {
it(`can be set to "true"`, () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Text selectable={true}>{TEST_TEXT}</Text>);
});
expect(root.getRenderedOutput({props: ['selectable']}).toJSX()).toEqual(
<rn-paragraph selectable={'true'}>{TEST_TEXT}</rn-paragraph>,
);
});
it(`has 'false' as default`, () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Text>{TEST_TEXT}</Text>);
});
expect(root.getRenderedOutput({props: ['selectable']}).toJSX()).toEqual(
<rn-paragraph>{TEST_TEXT}</rn-paragraph>,
);
Fantom.runTask(() => {
root.render(<Text selectable={false}>{TEST_TEXT}</Text>);
});
expect(root.getRenderedOutput({props: ['selectable']}).toJSX()).toEqual(
<rn-paragraph>{TEST_TEXT}</rn-paragraph>,
);
});
});
describe('style', () => {
describe('writingDirection', () => {
it('propagates to mounting layer', () => {
@@ -30,38 +424,38 @@ describe('<Text>', () => {
Fantom.runTask(() => {
root.render(
<Text style={{writingDirection: 'rtl'}}>dummy text</Text>,
<Text style={{writingDirection: 'rtl'}}>{TEST_TEXT}</Text>,
);
});
expect(
root.getRenderedOutput({props: ['writingDirection']}).toJSX(),
).toEqual(
<rn-paragraph writingDirection="rtl">dummy text</rn-paragraph>,
<rn-paragraph writingDirection="rtl">{TEST_TEXT}</rn-paragraph>,
);
Fantom.runTask(() => {
root.render(
<Text style={{writingDirection: 'ltr'}}>dummy text</Text>,
<Text style={{writingDirection: 'ltr'}}>{TEST_TEXT}</Text>,
);
});
expect(
root.getRenderedOutput({props: ['writingDirection']}).toJSX(),
).toEqual(
<rn-paragraph writingDirection="ltr">dummy text</rn-paragraph>,
<rn-paragraph writingDirection="ltr">{TEST_TEXT}</rn-paragraph>,
);
Fantom.runTask(() => {
root.render(
<Text style={{writingDirection: 'auto'}}>dummy text</Text>,
<Text style={{writingDirection: 'auto'}}>{TEST_TEXT}</Text>,
);
});
expect(
root.getRenderedOutput({props: ['writingDirection']}).toJSX(),
).toEqual(
<rn-paragraph writingDirection="auto">dummy text</rn-paragraph>,
<rn-paragraph writingDirection="auto">{TEST_TEXT}</rn-paragraph>,
);
});
});
@@ -75,7 +469,7 @@ describe('<Text>', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Text ref={elementRef}>Some text</Text>);
root.render(<Text ref={elementRef}>{TEST_TEXT}</Text>);
});
const element = ensureInstance(elementRef.current, ReactNativeElement);
@@ -88,14 +482,14 @@ describe('<Text>', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Text ref={elementRef}>Some text</Text>);
root.render(<Text ref={elementRef}>{TEST_TEXT}</Text>);
});
const element = ensureInstance(elementRef.current, ReactNativeElement);
expect(element.childNodes.length).toBe(1);
const textChild = ensureInstance(element.childNodes[0], ReadOnlyText);
expect(textChild.textContent).toBe('Some text');
expect(textChild.textContent).toBe(TEST_TEXT);
});
it('has text and element child nodes when nested', () => {
@@ -131,4 +525,9 @@ describe('<Text>', () => {
expect(secondChildText.textContent).toBe('also in bold');
});
});
component ComponentWithAccessibilityProps(...props: AccessibilityProps) {
return <Text {...props}>{TEST_TEXT}</Text>;
}
accessibilityPropsSuite(ComponentWithAccessibilityProps, false);
});
@@ -40,6 +40,7 @@ using namespace facebook::react;
// attaching and detaching of a pull-to-refresh view to a scroll view.
// The pull-to-refresh view is not a subview of this view.
self.hidden = YES;
_props = PullToRefreshViewShadowNode::defaultSharedProps();
_recycled = NO;
[self _initializeUIRefreshControl];
}
@@ -13,6 +13,8 @@
#import <React/RCTScrollableProtocol.h>
#import <React/RCTViewComponentView.h>
#import "RCTVirtualViewContainerProtocol.h"
NS_ASSUME_NONNULL_BEGIN
/*
@@ -23,7 +25,8 @@ NS_ASSUME_NONNULL_BEGIN
* keyboard-avoiding functionality and so on. All that complexity must be implemented inside those components in order
* to keep the complexity of this component manageable.
*/
@interface RCTScrollViewComponentView : RCTViewComponentView <RCTMountingTransactionObserving>
@interface RCTScrollViewComponentView
: RCTViewComponentView <RCTMountingTransactionObserving, RCTVirtualViewContainerProtocol>
/*
* Finds and returns the closet RCTScrollViewComponentView component to the given view
@@ -24,6 +24,7 @@
#import "RCTCustomPullToRefreshViewProtocol.h"
#import "RCTEnhancedScrollView.h"
#import "RCTFabricComponentsPlugins.h"
#import "RCTVirtualViewContainerState.h"
using namespace facebook::react;
@@ -117,6 +118,12 @@ RCTSendScrollEventForNativeAnimations_DEPRECATED(UIScrollView *scrollView, NSInt
// It is not restored to the default value in prepareForRecycle.
// Once an accessibility API is used, view culling will be disabled for the entire session.
BOOL _isAccessibilityAPIUsed;
// Flag to temporarily disable maintainVisibleContentPosition adjustments during immediate state updates
// to prevent conflicts between immediate content offset updates and visible content position logic
BOOL _avoidAdjustmentForMaintainVisibleContentPosition;
RCTVirtualViewContainerState *_virtualViewContainerState;
}
+ (RCTScrollViewComponentView *_Nullable)findScrollViewComponentViewForView:(UIView *)view
@@ -637,6 +644,11 @@ static inline UIViewAnimationOptions animationOptionsWithCurve(UIViewAnimationCu
return;
}
BOOL enableImmediateUpdateModeForContentOffsetChanges =
ReactNativeFeatureFlags::enableImmediateUpdateModeForContentOffsetChanges();
_avoidAdjustmentForMaintainVisibleContentPosition = enableImmediateUpdateModeForContentOffsetChanges;
auto contentOffset = RCTPointFromCGPoint(_scrollView.contentOffset);
BOOL isAccessibilityAPIUsed = _isAccessibilityAPIUsed;
_state->updateState(
@@ -652,9 +664,10 @@ static inline UIViewAnimationOptions animationOptionsWithCurve(UIViewAnimationCu
UIAccessibilityIsVoiceOverRunning() || UIAccessibilityIsSwitchControlRunning() || isAccessibilityAPIUsed;
return std::make_shared<const ScrollViewShadowNode::ConcreteState::Data>(newData);
},
ReactNativeFeatureFlags::enableImmediateUpdateModeForContentOffsetChanges()
? EventQueue::UpdateMode::unstable_Immediate
: EventQueue::UpdateMode::Asynchronous);
enableImmediateUpdateModeForContentOffsetChanges ? EventQueue::UpdateMode::unstable_Immediate
: EventQueue::UpdateMode::Asynchronous);
_avoidAdjustmentForMaintainVisibleContentPosition = NO;
}
- (void)prepareForRecycle
@@ -678,6 +691,7 @@ static inline UIViewAnimationOptions animationOptionsWithCurve(UIViewAnimationCu
_contentView = nil;
_prevFirstVisibleFrame = CGRectZero;
_firstVisibleView = nil;
_virtualViewContainerState = nil;
}
#pragma mark - UIScrollViewDelegate
@@ -1053,7 +1067,7 @@ static inline UIViewAnimationOptions animationOptionsWithCurve(UIViewAnimationCu
- (void)_adjustForMaintainVisibleContentPosition
{
const auto &props = static_cast<const ScrollViewProps &>(*_props);
if (!props.maintainVisibleContentPosition) {
if (!props.maintainVisibleContentPosition || _avoidAdjustmentForMaintainVisibleContentPosition) {
return;
}
@@ -1090,6 +1104,16 @@ static inline UIViewAnimationOptions animationOptionsWithCurve(UIViewAnimationCu
}
}
#pragma mark - RCTVirtualViewContainerProtocol
- (RCTVirtualViewContainerState *)virtualViewContainerState
{
if (!_virtualViewContainerState) {
_virtualViewContainerState = [[RCTVirtualViewContainerState alloc] initWithScrollView:self];
}
return _virtualViewContainerState;
}
@end
Class<RCTComponentViewProtocol> RCTScrollViewCls(void)
@@ -0,0 +1,14 @@
/*
* 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.
*/
@class RCTVirtualViewContainerState;
@protocol RCTVirtualViewContainerProtocol
- (RCTVirtualViewContainerState *)virtualViewContainerState;
@end
@@ -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.
*/
#import <Foundation/Foundation.h>
#import "RCTVirtualViewProtocol.h"
@class RCTScrollViewComponentView;
NS_ASSUME_NONNULL_BEGIN
@interface RCTVirtualViewContainerState : NSObject
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)new NS_UNAVAILABLE;
- (instancetype)initWithScrollView:(RCTScrollViewComponentView *)scrollView NS_DESIGNATED_INITIALIZER;
- (void)onChange:(id<RCTVirtualViewProtocol>)virtualView;
- (void)remove:(id<RCTVirtualViewProtocol>)virtualView;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,193 @@
/*
* 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/RCTLog.h>
#import <React/RCTScrollViewComponentView.h>
#import <React/RCTVirtualViewMode.h>
#import <UIKit/UIKit.h>
#import <react/featureflags/ReactNativeFeatureFlags.h>
#import "RCTVirtualViewContainerState.h"
using namespace facebook;
using namespace facebook::react;
#if RCT_DEBUG
static void debugLog(NSString *msg, ...)
{
auto debugEnabled = ReactNativeFeatureFlags::enableVirtualViewDebugFeatures();
if (!debugEnabled) {
return;
}
va_list args;
va_start(args, msg);
NSString *msgString = [[NSString alloc] initWithFormat:msg arguments:args];
RCTLogInfo(@"%@", msgString);
va_end(args); // Don't forget to call va_end to clean up
}
#endif
/**
* Checks whether one CGRect overlaps with another CGRect.
*
* This is different from CGRectIntersectsRect because a CGRect representing
* a line or a point is considered to overlap with another CGRect if the line
* or point is within the rect bounds. However, two CGRects are not considered
* to overlap if they only share a boundary.
*/
static BOOL CGRectOverlaps(CGRect rect1, CGRect rect2)
{
CGFloat minY1 = CGRectGetMinY(rect1);
CGFloat maxY1 = CGRectGetMaxY(rect1);
CGFloat minY2 = CGRectGetMinY(rect2);
CGFloat maxY2 = CGRectGetMaxY(rect2);
if (minY1 >= maxY2 || minY2 >= maxY1) {
// No overlap on the y-axis.
return NO;
}
CGFloat minX1 = CGRectGetMinX(rect1);
CGFloat maxX1 = CGRectGetMaxX(rect1);
CGFloat minX2 = CGRectGetMinX(rect2);
CGFloat maxX2 = CGRectGetMaxX(rect2);
if (minX1 >= maxX2 || minX2 >= maxX1) {
// No overlap on the x-axis.
return NO;
}
return YES;
}
@interface RCTVirtualViewContainerState () <UIScrollViewDelegate>
@end
@interface RCTVirtualViewContainerState () {
NSMutableSet<id<RCTVirtualViewProtocol>> *_virtualViews;
CGRect _emptyRect;
CGRect _prerenderRect;
__weak RCTScrollViewComponentView *_scrollViewComponentView;
CGFloat _prerenderRatio;
}
@end
@implementation RCTVirtualViewContainerState
- (instancetype)initWithScrollView:(RCTScrollViewComponentView *)scrollView
{
self = [super init];
if (self != nil) {
_virtualViews = [NSMutableSet set];
_emptyRect = CGRectZero;
_prerenderRect = CGRectZero;
_scrollViewComponentView = scrollView;
_prerenderRatio = ReactNativeFeatureFlags::virtualViewPrerenderRatio();
[_scrollViewComponentView addScrollListener:self];
#if RCT_DEBUG
debugLog(@"initWithScrollView");
#endif
}
return self;
}
- (void)dealloc
{
#if RCT_DEBUG
debugLog(@"dealloc");
#endif
if (_scrollViewComponentView != nil) {
[_scrollViewComponentView removeScrollListener:self];
_scrollViewComponentView = nil;
}
[_virtualViews removeAllObjects];
}
#pragma mark - Public API
- (void)onChange:(id<RCTVirtualViewProtocol>)virtualView
{
if (![_virtualViews containsObject:virtualView]) {
[_virtualViews addObject:virtualView];
#if RCT_DEBUG
debugLog(@"Add virtualViewID=%@", virtualView.virtualViewID);
#endif
} else {
#if RCT_DEBUG
debugLog(@"Update virtualViewID=%@", virtualView.virtualViewID);
#endif
}
[self _updateModes:virtualView];
}
- (void)remove:(id<RCTVirtualViewProtocol>)virtualView
{
if (![_virtualViews containsObject:virtualView]) {
RCTLogError(@"Attempting to remove non-existent VirtualView: %@", virtualView.virtualViewID);
}
[_virtualViews removeObject:virtualView];
#if RCT_DEBUG
debugLog(@"Remove virtualViewID=%@", virtualView.virtualViewID);
#endif
}
#pragma mark - Private Helpers
- (void)_updateModes:(id<RCTVirtualViewProtocol>)virtualView
{
auto scrollView = _scrollViewComponentView.scrollView;
CGRect visibleRect = CGRectMake(
scrollView.contentOffset.x,
scrollView.contentOffset.y,
scrollView.frame.size.width,
scrollView.frame.size.height);
_prerenderRect = visibleRect;
_prerenderRect = CGRectInset(
_prerenderRect, -_prerenderRect.size.width * _prerenderRatio, -_prerenderRect.size.height * _prerenderRatio);
NSArray<id<RCTVirtualViewProtocol>> *virtualViewsIt =
(virtualView != nullptr) ? @[ virtualView ] : [_virtualViews allObjects];
for (id<RCTVirtualViewProtocol> vv = nullptr in virtualViewsIt) {
CGRect rect = [vv containerRelativeRect:scrollView];
RCTVirtualViewMode mode = RCTVirtualViewModeHidden;
CGRect thresholdRect = _emptyRect;
if (CGRectIsEmpty(rect)) {
mode = RCTVirtualViewModeHidden;
thresholdRect = _emptyRect;
} else if (CGRectOverlaps(rect, visibleRect)) {
thresholdRect = visibleRect;
mode = RCTVirtualViewModeVisible;
} else if (CGRectOverlaps(rect, _prerenderRect)) {
mode = RCTVirtualViewModePrerender;
thresholdRect = _prerenderRect;
}
#if RCT_DEBUG
debugLog(
@"UpdateModes virtualView=%@ mode=%ld rect=%@ thresholdRect=%@",
vv.virtualViewID,
(long)mode,
NSStringFromCGRect(rect),
NSStringFromCGRect(thresholdRect));
#endif
[vv onModeChange:mode targetRect:rect thresholdRect:thresholdRect];
}
}
#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
[self _updateModes:nil];
}
@end
@@ -0,0 +1,20 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <React/RCTVirtualViewMode.h>
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@protocol RCTVirtualViewProtocol <NSObject>
- (NSString *)virtualViewID;
- (CGRect)containerRelativeRect:(UIView *)view;
- (void)onModeChange:(RCTVirtualViewMode)newMode targetRect:(CGRect)targetRect thresholdRect:(CGRect)thresholdRect;
@end
NS_ASSUME_NONNULL_END
@@ -22,6 +22,7 @@
#import "RCTTextInputNativeCommands.h"
#import "RCTTextInputUtils.h"
#import <limits>
#import "RCTFabricComponentsPlugins.h"
/** Native iOS text field bottom keyboard offset amount */
@@ -450,7 +451,7 @@ static NSSet<NSNumber *> *returnKeyTypesSet;
}
}
if (props.maxLength) {
if (props.maxLength < std::numeric_limits<int>::max()) {
NSInteger allowedLength = props.maxLength - _backedTextInputView.attributedText.string.length + range.length;
if (allowedLength > 0 && text.length > allowedLength) {
@@ -571,7 +571,7 @@ const CGFloat BACKGROUND_COLOR_ZPOSITION = -1024.0f;
_backgroundColorLayer.frame = CGRectMake(0, 0, self.layer.bounds.size.width, self.layer.bounds.size.height);
}
if ((_props->transformOrigin.isSet() || _props->transform.operations.size() > 0) &&
if ((_props->transformOrigin.isSet() || !_props->transform.operations.empty()) &&
layoutMetrics.frame.size != oldLayoutMetrics.frame.size) {
auto newTransform = _props->resolveTransform(layoutMetrics);
self.layer.transform = RCTCATransform3DFromTransformMatrix(newTransform);
@@ -8,10 +8,11 @@
#import <UIKit/UIKit.h>
#import <React/RCTViewComponentView.h>
#import <React/RCTVirtualViewProtocol.h>
NS_ASSUME_NONNULL_BEGIN
@interface RCTVirtualViewExperimentalComponentView : RCTViewComponentView
@interface RCTVirtualViewExperimentalComponentView : RCTViewComponentView <RCTVirtualViewProtocol>
+ (instancetype)new NS_UNAVAILABLE;
- (instancetype)init NS_UNAVAILABLE;
@@ -11,6 +11,8 @@
#import <React/RCTConversions.h>
#import <React/RCTScrollViewComponentView.h>
#import <React/RCTScrollableProtocol.h>
#import <React/RCTVirtualViewContainerProtocol.h>
#import <React/RCTVirtualViewContainerState.h>
#import <React/UIView+React.h>
#import <jsi/jsi.h>
@@ -28,50 +30,30 @@
using namespace facebook;
using namespace facebook::react;
/**
* Checks whether one CGRect overlaps with another CGRect.
*
* This is different from CGRectIntersectsRect because a CGRect representing
* a line or a point is considered to overlap with another CGRect if the line
* or point is within the rect bounds. However, two CGRects are not considered
* to overlap if they only share a boundary.
*/
static BOOL CGRectOverlaps(CGRect rect1, CGRect rect2)
{
CGFloat minY1 = CGRectGetMinY(rect1);
CGFloat maxY1 = CGRectGetMaxY(rect1);
CGFloat minY2 = CGRectGetMinY(rect2);
CGFloat maxY2 = CGRectGetMaxY(rect2);
if (minY1 >= maxY2 || minY2 >= maxY1) {
// No overlap on the y-axis.
return NO;
}
CGFloat minX1 = CGRectGetMinX(rect1);
CGFloat maxX1 = CGRectGetMaxX(rect1);
CGFloat minX2 = CGRectGetMinX(rect2);
CGFloat maxX2 = CGRectGetMaxX(rect2);
if (minX1 >= maxX2 || minX2 >= maxX1) {
// No overlap on the x-axis.
return NO;
}
return YES;
@interface RCTVirtualViewExperimentalComponentView () {
NSString *_virtualViewID;
}
@interface RCTVirtualViewExperimentalComponentView () <UIScrollViewDelegate>
@end
@implementation RCTVirtualViewExperimentalComponentView {
RCTScrollViewComponentView *_lastParentScrollViewComponentView;
id<RCTVirtualViewContainerProtocol> _parentVirtualViewContainer;
std::optional<RCTVirtualViewMode> _mode;
RCTVirtualViewRenderState _renderState;
std::optional<CGRect> _targetRect;
NSString *_nativeId;
BOOL _didLayout;
}
#pragma mark - Public API
- (instancetype)initWithFrame:(CGRect)frame
{
if ((self = [super initWithFrame:frame]) != nil) {
_props = VirtualViewExperimentalShadowNode::defaultSharedProps();
_renderState = RCTVirtualViewRenderStateUnknown;
_virtualViewID = [[NSUUID UUID] UUIDString];
_didLayout = NO;
}
return self;
@@ -103,19 +85,11 @@ static BOOL CGRectOverlaps(CGRect rect1, CGRect rect2)
}
}
[super updateProps:props oldProps:oldProps];
}
const auto &newBaseViewProps = static_cast<const ViewProps &>(*props);
const auto nativeId = RCTNSStringFromStringNilIfEmpty(newBaseViewProps.nativeId);
_virtualViewID = nativeId == nil ? _virtualViewID : nativeId;
- (RCTScrollViewComponentView *)getParentScrollViewComponentView
{
UIView *view = self.superview;
while (view != nil) {
if ([view isKindOfClass:[RCTScrollViewComponentView class]]) {
return (RCTScrollViewComponentView *)view;
}
view = view.superview;
}
return nil;
[super updateProps:props oldProps:oldProps];
}
/**
@@ -126,18 +100,6 @@ static BOOL CGRectOverlaps(CGRect rect1, CGRect rect2)
*/
static BOOL sIsAccessibilityUsed = NO;
- (void)_unhideIfNeeded
{
if (!sIsAccessibilityUsed) {
// accessibility is detected for the first time. Make views visible.
sIsAccessibilityUsed = YES;
}
if (self.hidden) {
self.hidden = NO;
}
}
- (NSInteger)accessibilityElementCount
{
// From empirical testing, method `accessibilityElementCount` is called lazily only
@@ -154,19 +116,23 @@ static BOOL sIsAccessibilityUsed = NO;
return [super focusItemsInRect:rect];
}
- (NSString *)virtualViewID
{
// Return a unique identifier for this virtual view
// Using the tag as a unique identifier since it's already unique per view
return _virtualViewID;
}
- (void)prepareForRecycle
{
[super prepareForRecycle];
// No need to remove the scroll listener here since the view is always removed from window before being recycled and
// we do that in didMoveToWindow, which gets called when the view is removed from window.
RCTAssert(
_lastParentScrollViewComponentView == nil,
@"_lastParentScrollViewComponentView should already have been cleared in didMoveToWindow.");
[[_parentVirtualViewContainer virtualViewContainerState] remove:self];
self.hidden = NO;
_didLayout = NO;
_mode.reset();
_targetRect.reset();
_parentVirtualViewContainer = nil;
}
// Handles case when sibling changes size.
@@ -176,84 +142,41 @@ static BOOL sIsAccessibilityUsed = NO;
oldLayoutMetrics:(const LayoutMetrics &)oldLayoutMetrics
{
[super updateLayoutMetrics:layoutMetrics oldLayoutMetrics:_layoutMetrics];
_didLayout = YES;
[self updateState];
}
[self dispatchOnModeChangeIfNeeded:YES];
- (void)updateState
{
[[_parentVirtualViewContainer virtualViewContainerState] onChange:self];
}
- (void)didMoveToWindow
{
[super didMoveToWindow];
// here we will set the pointer to the virtualView container
// and if there was a layout, update
if (_lastParentScrollViewComponentView != nil) {
[_lastParentScrollViewComponentView removeScrollListener:self];
_lastParentScrollViewComponentView = nil;
}
if (RCTScrollViewComponentView *parentScrollViewComponentView = [self getParentScrollViewComponentView]) {
if (self.window != nil) {
// TODO(T202601695): We also want the ScrollView to emit layout changes from didLayoutSubviews so that any event
// that may affect visibily of this view notifies the listeners.
[parentScrollViewComponentView addScrollListener:self];
_lastParentScrollViewComponentView = parentScrollViewComponentView;
// We want to dispatch the event immediately when the view is added to the window before any scrolling occurs.
[self dispatchOnModeChangeIfNeeded:NO];
}
_parentVirtualViewContainer = [self _getParentVirtualViewContainer];
if (_parentVirtualViewContainer != nil && self.window != nil && _didLayout) {
[self updateState];
}
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
- (CGRect)containerRelativeRect:(UIView *)scrollView
{
[self dispatchOnModeChangeIfNeeded:NO];
// Return the view's position relative to its container (the scroll view)
return [self convertRect:self.bounds toView:scrollView];
}
- (void)dispatchOnModeChangeIfNeeded:(BOOL)checkForTargetRectChange
- (void)onModeChange:(RCTVirtualViewMode)newMode targetRect:(CGRect)targetRect thresholdRect:(CGRect)thresholdRect
{
if (_lastParentScrollViewComponentView == nullptr) {
return;
}
UIScrollView *scrollView = _lastParentScrollViewComponentView.scrollView;
CGRect targetRect = [self convertRect:self.bounds toView:scrollView];
// While scrolling, the `targetRect` does not change, so we don't check for changed `targetRect` in that case.
if (checkForTargetRectChange) {
if (_targetRect.has_value() && CGRectEqualToRect(targetRect, _targetRect.value())) {
return;
}
_targetRect = targetRect;
}
RCTVirtualViewMode newMode;
CGRect thresholdRect = CGRectMake(
scrollView.contentOffset.x,
scrollView.contentOffset.y,
scrollView.frame.size.width,
scrollView.frame.size.height);
if (CGRectOverlaps(targetRect, thresholdRect)) {
newMode = RCTVirtualViewModeVisible;
} else {
auto prerender = false;
const CGFloat prerenderRatio = ReactNativeFeatureFlags::virtualViewPrerenderRatio();
if (prerenderRatio > 0) {
thresholdRect = CGRectInset(
thresholdRect, -thresholdRect.size.width * prerenderRatio, -thresholdRect.size.height * prerenderRatio);
prerender = CGRectOverlaps(targetRect, thresholdRect);
}
if (prerender) {
newMode = RCTVirtualViewModePrerender;
} else {
newMode = RCTVirtualViewModeHidden;
thresholdRect = CGRectZero;
}
}
if (_mode.has_value() && newMode == _mode.value()) {
return;
}
// NOTE: Make sure to keep these props in sync with dispatchSyncModeChange below where we have to explicitly copy all
// props.
// NOTE: Make sure to keep these props in sync with dispatchSyncModeChange below where we have to explicitly copy
// all props.
VirtualViewEventEmitter::OnModeChange event = {
.mode = (int)newMode,
.targetRect =
@@ -275,24 +198,24 @@ static BOOL sIsAccessibilityUsed = NO;
case RCTVirtualViewModeVisible:
if (_renderState == RCTVirtualViewRenderStateUnknown) {
// Feature flag is disabled, so use the former logic.
[self dispatchSyncModeChange:event];
[self _dispatchSyncModeChange:event];
} else {
// If the previous mode was prerender and the result of dispatching that event was committed, we do not need to
// dispatch an event for visible.
// If the previous mode was prerender and the result of dispatching that event was committed, we do not need
// to dispatch an event for visible.
const auto wasPrerenderCommitted = oldMode.has_value() && oldMode == RCTVirtualViewModePrerender &&
_renderState == RCTVirtualViewRenderStateRendered;
if (!wasPrerenderCommitted) {
[self dispatchSyncModeChange:event];
[self _dispatchSyncModeChange:event];
}
}
break;
case RCTVirtualViewModePrerender:
if (!oldMode.has_value() || oldMode != RCTVirtualViewModeVisible) {
[self dispatchAsyncModeChange:event];
[self _dispatchAsyncModeChange:event];
}
break;
case RCTVirtualViewModeHidden:
[self dispatchAsyncModeChange:event];
[self _dispatchAsyncModeChange:event];
break;
}
@@ -311,7 +234,33 @@ static BOOL sIsAccessibilityUsed = NO;
}
}
- (void)dispatchAsyncModeChange:(VirtualViewEventEmitter::OnModeChange &)event
#pragma mark - Private API
- (void)_unhideIfNeeded
{
if (!sIsAccessibilityUsed) {
// accessibility is detected for the first time. Make views visible.
sIsAccessibilityUsed = YES;
}
if (self.hidden) {
self.hidden = NO;
}
}
- (id<RCTVirtualViewContainerProtocol>)_getParentVirtualViewContainer
{
UIView *view = self.superview;
while (view != nil) {
if ([view respondsToSelector:@selector(virtualViewContainerState)]) {
return (id<RCTVirtualViewContainerProtocol>)view;
}
view = view.superview;
}
return nil;
}
- (void)_dispatchAsyncModeChange:(VirtualViewEventEmitter::OnModeChange &)event
{
if (!_eventEmitter) {
return;
@@ -322,7 +271,7 @@ static BOOL sIsAccessibilityUsed = NO;
emitter->onModeChange(event);
}
- (void)dispatchSyncModeChange:(VirtualViewEventEmitter::OnModeChange &)event
- (void)_dispatchSyncModeChange:(VirtualViewEventEmitter::OnModeChange &)event
{
if (!_eventEmitter) {
return;
@@ -3348,10 +3348,8 @@ public final class com/facebook/react/uimanager/DisplayMetricsHolder {
public static final fun getDisplayMetricsWritableMap (D)Lcom/facebook/react/bridge/WritableMap;
public static final fun getScreenDisplayMetrics ()Landroid/util/DisplayMetrics;
public static final fun getWindowDisplayMetrics ()Landroid/util/DisplayMetrics;
public static final fun initScreenDisplayMetrics (Landroid/content/Context;)V
public static final fun initScreenDisplayMetricsIfNotInitialized (Landroid/content/Context;)V
public static final fun initWindowDisplayMetrics (Landroid/content/Context;)V
public static final fun initWindowDisplayMetricsIfNotInitialized (Landroid/content/Context;)V
public static final fun initDisplayMetrics (Landroid/content/Context;)V
public static final fun initDisplayMetricsIfNotInitialized (Landroid/content/Context;)V
public static final fun setScreenDisplayMetrics (Landroid/util/DisplayMetrics;)V
public static final fun setWindowDisplayMetrics (Landroid/util/DisplayMetrics;)V
}
@@ -3615,30 +3613,30 @@ public final class com/facebook/react/uimanager/PointerEvents$Companion {
}
public class com/facebook/react/uimanager/ReactAccessibilityDelegate : androidx/customview/widget/ExploreByTouchHelper {
public static final field Companion Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$Companion;
public static final field TOP_ACCESSIBILITY_ACTION_EVENT Ljava/lang/String;
public static final field sActionIdMap Ljava/util/HashMap;
public fun <init> (Landroid/view/View;ZI)V
public static fun createNodeInfoFromView (Landroid/view/View;)Landroidx/core/view/accessibility/AccessibilityNodeInfoCompat;
public static final fun createNodeInfoFromView (Landroid/view/View;)Landroidx/core/view/accessibility/AccessibilityNodeInfoCompat;
public fun getAccessibilityNodeProvider (Landroid/view/View;)Landroidx/core/view/accessibility/AccessibilityNodeProviderCompat;
protected fun getHostView ()Landroid/view/View;
public static fun getTalkbackDescription (Landroid/view/View;Landroidx/core/view/accessibility/AccessibilityNodeInfoCompat;)Ljava/lang/CharSequence;
protected final fun getHostView ()Landroid/view/View;
public static final fun getTalkbackDescription (Landroid/view/View;Landroidx/core/view/accessibility/AccessibilityNodeInfoCompat;)Ljava/lang/CharSequence;
protected fun getVirtualViewAt (FF)I
protected fun getVisibleVirtualViews (Ljava/util/List;)V
public static fun hasNonActionableSpeakingDescendants (Landroidx/core/view/accessibility/AccessibilityNodeInfoCompat;Landroid/view/View;)Z
public static fun hasText (Landroidx/core/view/accessibility/AccessibilityNodeInfoCompat;)Z
public static fun hasValidRangeInfo (Landroidx/core/view/accessibility/AccessibilityNodeInfoCompat;)Z
public static fun isAccessibilityFocusable (Landroidx/core/view/accessibility/AccessibilityNodeInfoCompat;Landroid/view/View;)Z
public static fun isActionableForAccessibility (Landroidx/core/view/accessibility/AccessibilityNodeInfoCompat;)Z
public static fun isSpeakingNode (Landroidx/core/view/accessibility/AccessibilityNodeInfoCompat;Landroid/view/View;)Z
public static final fun hasNonActionableSpeakingDescendants (Landroidx/core/view/accessibility/AccessibilityNodeInfoCompat;Landroid/view/View;)Z
public static final fun hasText (Landroidx/core/view/accessibility/AccessibilityNodeInfoCompat;)Z
public static final fun hasValidRangeInfo (Landroidx/core/view/accessibility/AccessibilityNodeInfoCompat;)Z
public static final fun isAccessibilityFocusable (Landroidx/core/view/accessibility/AccessibilityNodeInfoCompat;Landroid/view/View;)Z
public static final fun isActionableForAccessibility (Landroidx/core/view/accessibility/AccessibilityNodeInfoCompat;)Z
public static final fun isSpeakingNode (Landroidx/core/view/accessibility/AccessibilityNodeInfoCompat;Landroid/view/View;)Z
public fun onInitializeAccessibilityEvent (Landroid/view/View;Landroid/view/accessibility/AccessibilityEvent;)V
public fun onInitializeAccessibilityNodeInfo (Landroid/view/View;Landroidx/core/view/accessibility/AccessibilityNodeInfoCompat;)V
protected fun onPerformActionForVirtualView (IILandroid/os/Bundle;)Z
protected fun onPopulateNodeForVirtualView (ILandroidx/core/view/accessibility/AccessibilityNodeInfoCompat;)V
public fun performAccessibilityAction (Landroid/view/View;ILandroid/os/Bundle;)Z
public static fun resetDelegate (Landroid/view/View;ZI)V
public static fun setDelegate (Landroid/view/View;ZI)V
public static fun setRole (Landroidx/core/view/accessibility/AccessibilityNodeInfoCompat;Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;Landroid/content/Context;)V
public fun superGetAccessibilityNodeProvider (Landroid/view/View;)Landroidx/core/view/accessibility/AccessibilityNodeProviderCompat;
public static final fun resetDelegate (Landroid/view/View;ZI)V
public static final fun setDelegate (Landroid/view/View;ZI)V
public static final fun setRole (Landroidx/core/view/accessibility/AccessibilityNodeInfoCompat;Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;Landroid/content/Context;)V
protected final fun superGetAccessibilityNodeProvider (Landroid/view/View;)Landroidx/core/view/accessibility/AccessibilityNodeProviderCompat;
}
public final class com/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole : java/lang/Enum {
@@ -3647,6 +3645,7 @@ public final class com/facebook/react/uimanager/ReactAccessibilityDelegate$Acces
public static final field BUTTON Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;
public static final field CHECKBOX Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;
public static final field COMBOBOX Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;
public static final field Companion Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole$Companion;
public static final field DRAWERLAYOUT Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;
public static final field DROPDOWNLIST Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;
public static final field GRID Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;
@@ -3681,14 +3680,36 @@ public final class com/facebook/react/uimanager/ReactAccessibilityDelegate$Acces
public static final field TOOLBAR Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;
public static final field VIEWGROUP Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;
public static final field WEBVIEW Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;
public static fun fromRole (Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$Role;)Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;
public static fun fromValue (Ljava/lang/String;)Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;
public static fun fromViewTag (Landroid/view/View;)Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;
public static fun getValue (Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;)Ljava/lang/String;
public static final fun fromRole (Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$Role;)Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;
public static final fun fromValue (Ljava/lang/String;)Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;
public static final fun fromViewTag (Landroid/view/View;)Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;
public static fun getEntries ()Lkotlin/enums/EnumEntries;
public static final fun getValue (Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;)Ljava/lang/String;
public static fun valueOf (Ljava/lang/String;)Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;
public static fun values ()[Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;
}
public final class com/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole$Companion {
public final fun fromRole (Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$Role;)Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;
public final fun fromValue (Ljava/lang/String;)Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;
public final fun fromViewTag (Landroid/view/View;)Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;
public final fun getValue (Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;)Ljava/lang/String;
}
public final class com/facebook/react/uimanager/ReactAccessibilityDelegate$Companion {
public final fun createNodeInfoFromView (Landroid/view/View;)Landroidx/core/view/accessibility/AccessibilityNodeInfoCompat;
public final fun getTalkbackDescription (Landroid/view/View;Landroidx/core/view/accessibility/AccessibilityNodeInfoCompat;)Ljava/lang/CharSequence;
public final fun hasNonActionableSpeakingDescendants (Landroidx/core/view/accessibility/AccessibilityNodeInfoCompat;Landroid/view/View;)Z
public final fun hasText (Landroidx/core/view/accessibility/AccessibilityNodeInfoCompat;)Z
public final fun hasValidRangeInfo (Landroidx/core/view/accessibility/AccessibilityNodeInfoCompat;)Z
public final fun isAccessibilityFocusable (Landroidx/core/view/accessibility/AccessibilityNodeInfoCompat;Landroid/view/View;)Z
public final fun isActionableForAccessibility (Landroidx/core/view/accessibility/AccessibilityNodeInfoCompat;)Z
public final fun isSpeakingNode (Landroidx/core/view/accessibility/AccessibilityNodeInfoCompat;Landroid/view/View;)Z
public final fun resetDelegate (Landroid/view/View;ZI)V
public final fun setDelegate (Landroid/view/View;ZI)V
public final fun setRole (Landroidx/core/view/accessibility/AccessibilityNodeInfoCompat;Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;Landroid/content/Context;)V
}
public final class com/facebook/react/uimanager/ReactAccessibilityDelegate$Role : java/lang/Enum {
public static final field ALERT Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$Role;
public static final field ALERTDIALOG Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$Role;
@@ -3702,6 +3723,7 @@ public final class com/facebook/react/uimanager/ReactAccessibilityDelegate$Role
public static final field COMBOBOX Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$Role;
public static final field COMPLEMENTARY Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$Role;
public static final field CONTENTINFO Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$Role;
public static final field Companion Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$Role$Companion;
public static final field DEFINITION Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$Role;
public static final field DIALOG Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$Role;
public static final field DIRECTORY Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$Role;
@@ -3755,11 +3777,16 @@ public final class com/facebook/react/uimanager/ReactAccessibilityDelegate$Role
public static final field TREE Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$Role;
public static final field TREEGRID Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$Role;
public static final field TREEITEM Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$Role;
public static fun fromValue (Ljava/lang/String;)Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$Role;
public static final fun fromValue (Ljava/lang/String;)Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$Role;
public static fun getEntries ()Lkotlin/enums/EnumEntries;
public static fun valueOf (Ljava/lang/String;)Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$Role;
public static fun values ()[Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$Role;
}
public final class com/facebook/react/uimanager/ReactAccessibilityDelegate$Role$Companion {
public final fun fromValue (Ljava/lang/String;)Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$Role;
}
public final class com/facebook/react/uimanager/ReactAxOrderHelper {
public static final field INSTANCE Lcom/facebook/react/uimanager/ReactAxOrderHelper;
public final fun buildAxOrderList (Landroid/view/View;Landroid/view/View;Ljava/util/List;[Landroid/view/View;)V
@@ -6014,6 +6041,7 @@ public final class com/facebook/react/views/text/DefaultStyleValuesUtil {
}
public abstract class com/facebook/react/views/text/ReactBaseTextShadowNode : com/facebook/react/uimanager/LayoutShadowNode {
public static final field Companion Lcom/facebook/react/views/text/ReactBaseTextShadowNode$Companion;
public static final field DEFAULT_TEXT_SHADOW_COLOR I
public static final field PROP_SHADOW_COLOR Ljava/lang/String;
public static final field PROP_SHADOW_OFFSET Ljava/lang/String;
@@ -6021,61 +6049,86 @@ public abstract class com/facebook/react/views/text/ReactBaseTextShadowNode : co
public static final field PROP_SHADOW_OFFSET_WIDTH Ljava/lang/String;
public static final field PROP_SHADOW_RADIUS Ljava/lang/String;
public static final field PROP_TEXT_TRANSFORM Ljava/lang/String;
protected field mAccessibilityRole Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;
protected field mAdjustsFontSizeToFit Z
protected field mBackgroundColor I
protected field mColor I
protected field mContainsImages Z
protected field mFontFamily Ljava/lang/String;
protected field mFontFeatureSettings Ljava/lang/String;
protected field mFontStyle I
protected field mFontWeight I
protected field mHyphenationFrequency I
protected field mIncludeFontPadding Z
protected field mInlineViews Ljava/util/Map;
protected field mIsBackgroundColorSet Z
protected field mIsColorSet Z
protected field mIsLineThroughTextDecorationSet Z
protected field mIsUnderlineTextDecorationSet Z
protected field mJustificationMode I
protected field mMinimumFontScale F
protected field mNumberOfLines I
protected field mReactTextViewManagerCallback Lcom/facebook/react/views/text/ReactTextViewManagerCallback;
protected field mRole Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$Role;
protected field mTextAlign I
protected field mTextAttributes Lcom/facebook/react/views/text/TextAttributes;
protected field mTextBreakStrategy I
protected field mTextShadowColor I
protected field mTextShadowOffsetDx F
protected field mTextShadowOffsetDy F
protected field mTextShadowRadius F
public fun <init> ()V
public fun <init> (Lcom/facebook/react/views/text/ReactTextViewManagerCallback;)V
public fun setAccessibilityRole (Ljava/lang/String;)V
public fun setAdjustFontSizeToFit (Z)V
public fun setAllowFontScaling (Z)V
public fun setBackgroundColor (Ljava/lang/Integer;)V
public fun setColor (Ljava/lang/Integer;)V
public fun setFontFamily (Ljava/lang/String;)V
public fun setFontSize (F)V
public fun setFontStyle (Ljava/lang/String;)V
public fun setFontVariant (Lcom/facebook/react/bridge/ReadableArray;)V
public fun setFontWeight (Ljava/lang/String;)V
public fun setIncludeFontPadding (Z)V
public fun setLetterSpacing (F)V
public fun setLineHeight (F)V
public fun setMaxFontSizeMultiplier (F)V
public fun setMinimumFontScale (F)V
public fun setNumberOfLines (I)V
public fun setRole (Ljava/lang/String;)V
public fun setTextAlign (Ljava/lang/String;)V
public synthetic fun <init> (Lcom/facebook/react/views/text/ReactTextViewManagerCallback;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
protected final fun getAccessibilityRole ()Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;
protected final fun getAdjustsFontSizeToFit ()Z
protected final fun getBackgroundColor ()I
protected final fun getColor ()I
protected final fun getContainsImages ()Z
protected final fun getFontFamily ()Ljava/lang/String;
protected final fun getFontFeatureSettings ()Ljava/lang/String;
protected final fun getFontStyle ()I
protected final fun getFontWeight ()I
protected final fun getHyphenationFrequency ()I
protected final fun getIncludeFontPadding ()Z
protected final fun getInlineViews ()Ljava/util/Map;
protected final fun getJustificationMode ()I
protected final fun getMinimumFontScale ()F
protected final fun getNumberOfLines ()I
protected final fun getReactTextViewManagerCallback ()Lcom/facebook/react/views/text/ReactTextViewManagerCallback;
protected final fun getRole ()Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$Role;
protected final fun getTextAlign ()I
protected final fun getTextAttributes ()Lcom/facebook/react/views/text/TextAttributes;
protected final fun getTextBreakStrategy ()I
protected final fun getTextShadowColor ()I
protected final fun getTextShadowOffsetDx ()F
protected final fun getTextShadowOffsetDy ()F
protected final fun getTextShadowRadius ()F
protected final fun isBackgroundColorSet ()Z
protected final fun isColorSet ()Z
protected final fun isLineThroughTextDecorationSet ()Z
protected final fun isUnderlineTextDecorationSet ()Z
protected final fun setAccessibilityRole (Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;)V
public final fun setAccessibilityRole (Ljava/lang/String;)V
public final fun setAdjustFontSizeToFit (Z)V
protected final fun setAdjustsFontSizeToFit (Z)V
public final fun setAllowFontScaling (Z)V
protected final fun setBackgroundColor (I)V
public final fun setBackgroundColor (Ljava/lang/Integer;)V
protected final fun setBackgroundColorSet (Z)V
protected final fun setColor (I)V
public final fun setColor (Ljava/lang/Integer;)V
protected final fun setColorSet (Z)V
protected final fun setContainsImages (Z)V
public final fun setFontFamily (Ljava/lang/String;)V
protected final fun setFontFeatureSettings (Ljava/lang/String;)V
public final fun setFontSize (F)V
protected final fun setFontStyle (I)V
public final fun setFontStyle (Ljava/lang/String;)V
public final fun setFontVariant (Lcom/facebook/react/bridge/ReadableArray;)V
protected final fun setFontWeight (I)V
public final fun setFontWeight (Ljava/lang/String;)V
protected final fun setHyphenationFrequency (I)V
public final fun setIncludeFontPadding (Z)V
protected final fun setInlineViews (Ljava/util/Map;)V
protected final fun setJustificationMode (I)V
public final fun setLetterSpacing (F)V
public final fun setLineHeight (F)V
protected final fun setLineThroughTextDecorationSet (Z)V
public final fun setMaxFontSizeMultiplier (F)V
public final fun setMinimumFontScale (F)V
public final fun setNumberOfLines (I)V
protected final fun setReactTextViewManagerCallback (Lcom/facebook/react/views/text/ReactTextViewManagerCallback;)V
protected final fun setRole (Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$Role;)V
public final fun setRole (Ljava/lang/String;)V
public final fun setTextAlign (Ljava/lang/String;)V
protected final fun setTextAttributes (Lcom/facebook/react/views/text/TextAttributes;)V
protected final fun setTextBreakStrategy (I)V
public fun setTextBreakStrategy (Ljava/lang/String;)V
public fun setTextDecorationLine (Ljava/lang/String;)V
public fun setTextShadowColor (I)V
public fun setTextShadowOffset (Lcom/facebook/react/bridge/ReadableMap;)V
public fun setTextShadowRadius (F)V
public fun setTextTransform (Ljava/lang/String;)V
protected fun spannedFromShadowNode (Lcom/facebook/react/views/text/ReactBaseTextShadowNode;Ljava/lang/String;ZLcom/facebook/react/uimanager/NativeViewHierarchyOptimizer;)Landroid/text/Spannable;
public final fun setTextDecorationLine (Ljava/lang/String;)V
public final fun setTextShadowColor (I)V
public final fun setTextShadowOffset (Lcom/facebook/react/bridge/ReadableMap;)V
protected final fun setTextShadowOffsetDx (F)V
protected final fun setTextShadowOffsetDy (F)V
public final fun setTextShadowRadius (F)V
public final fun setTextTransform (Ljava/lang/String;)V
protected final fun setUnderlineTextDecorationSet (Z)V
protected final fun spannedFromShadowNode (Lcom/facebook/react/views/text/ReactBaseTextShadowNode;Ljava/lang/String;ZLcom/facebook/react/uimanager/NativeViewHierarchyOptimizer;)Landroid/text/Spannable;
}
public final class com/facebook/react/views/text/ReactBaseTextShadowNode$Companion {
}
public final class com/facebook/react/views/text/ReactFontManager {
@@ -6213,97 +6266,74 @@ public final class com/facebook/react/views/text/ReactTypefaceUtils {
public static final fun parseFontWeight (Ljava/lang/String;)I
}
public class com/facebook/react/views/text/TextAttributeProps {
public static final field TA_KEY_ACCESSIBILITY_ROLE S
public static final field TA_KEY_ALIGNMENT S
public static final field TA_KEY_ALLOW_FONT_SCALING S
public static final field TA_KEY_BACKGROUND_COLOR S
public static final field TA_KEY_BEST_WRITING_DIRECTION S
public static final field TA_KEY_FONT_FAMILY S
public static final field TA_KEY_FONT_SIZE S
public static final field TA_KEY_FONT_SIZE_MULTIPLIER S
public static final field TA_KEY_FONT_STYLE S
public static final field TA_KEY_FONT_VARIANT S
public static final field TA_KEY_FONT_WEIGHT S
public static final field TA_KEY_FOREGROUND_COLOR S
public static final field TA_KEY_IS_HIGHLIGHTED S
public static final field TA_KEY_LAYOUT_DIRECTION S
public static final field TA_KEY_LETTER_SPACING S
public static final field TA_KEY_LINE_BREAK_STRATEGY S
public static final field TA_KEY_LINE_HEIGHT S
public static final field TA_KEY_MAX_FONT_SIZE_MULTIPLIER S
public static final field TA_KEY_OPACITY S
public static final field TA_KEY_ROLE S
public static final field TA_KEY_TEXT_DECORATION_COLOR S
public static final field TA_KEY_TEXT_DECORATION_LINE S
public static final field TA_KEY_TEXT_DECORATION_STYLE S
public static final field TA_KEY_TEXT_SHADOW_COLOR S
public static final field TA_KEY_TEXT_SHADOW_OFFSET_DX S
public static final field TA_KEY_TEXT_SHADOW_OFFSET_DY S
public static final field TA_KEY_TEXT_SHADOW_RADIUS S
public static final field TA_KEY_TEXT_TRANSFORM S
public final class com/facebook/react/views/text/TextAttributeProps {
public static final field Companion Lcom/facebook/react/views/text/TextAttributeProps$Companion;
public static final field TA_KEY_ACCESSIBILITY_ROLE I
public static final field TA_KEY_ALIGNMENT I
public static final field TA_KEY_ALLOW_FONT_SCALING I
public static final field TA_KEY_BACKGROUND_COLOR I
public static final field TA_KEY_BEST_WRITING_DIRECTION I
public static final field TA_KEY_FONT_FAMILY I
public static final field TA_KEY_FONT_SIZE I
public static final field TA_KEY_FONT_SIZE_MULTIPLIER I
public static final field TA_KEY_FONT_STYLE I
public static final field TA_KEY_FONT_VARIANT I
public static final field TA_KEY_FONT_WEIGHT I
public static final field TA_KEY_FOREGROUND_COLOR I
public static final field TA_KEY_IS_HIGHLIGHTED I
public static final field TA_KEY_LAYOUT_DIRECTION I
public static final field TA_KEY_LETTER_SPACING I
public static final field TA_KEY_LINE_BREAK_STRATEGY I
public static final field TA_KEY_LINE_HEIGHT I
public static final field TA_KEY_MAX_FONT_SIZE_MULTIPLIER I
public static final field TA_KEY_OPACITY I
public static final field TA_KEY_ROLE I
public static final field TA_KEY_TEXT_DECORATION_COLOR I
public static final field TA_KEY_TEXT_DECORATION_LINE I
public static final field TA_KEY_TEXT_DECORATION_STYLE I
public static final field TA_KEY_TEXT_SHADOW_COLOR I
public static final field TA_KEY_TEXT_SHADOW_OFFSET_DX I
public static final field TA_KEY_TEXT_SHADOW_OFFSET_DY I
public static final field TA_KEY_TEXT_SHADOW_RADIUS I
public static final field TA_KEY_TEXT_TRANSFORM I
public static final field UNSET I
protected field mAccessibilityRole Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;
protected field mAllowFontScaling Z
protected field mBackgroundColor I
protected field mColor I
protected field mContainsImages Z
protected field mFontFamily Ljava/lang/String;
protected field mFontFeatureSettings Ljava/lang/String;
protected field mFontSize I
protected field mFontSizeInput F
protected field mFontStyle I
protected field mFontWeight I
protected field mHeightOfTallestInlineImage F
protected field mIncludeFontPadding Z
protected field mIsBackgroundColorSet Z
protected field mIsColorSet Z
protected field mIsLineThroughTextDecorationSet Z
protected field mIsUnderlineTextDecorationSet Z
protected field mLayoutDirection I
protected field mLetterSpacingInput F
protected field mLineHeight F
protected field mLineHeightInput F
protected field mMaxFontSizeMultiplier F
protected field mNumberOfLines I
protected field mOpacity F
protected field mRole Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$Role;
protected field mTextAlign I
protected field mTextShadowColor I
protected field mTextShadowOffsetDx F
protected field mTextShadowOffsetDy F
protected field mTextShadowRadius F
protected field mTextTransform Lcom/facebook/react/views/text/TextTransform;
public static fun fromMapBuffer (Lcom/facebook/react/common/mapbuffer/MapBuffer;)Lcom/facebook/react/views/text/TextAttributeProps;
public static fun fromReadableMap (Lcom/facebook/react/uimanager/ReactStylesDiffMap;)Lcom/facebook/react/views/text/TextAttributeProps;
public fun getAccessibilityRole ()Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;
public fun getBackgroundColor ()I
public fun getColor ()I
public fun getEffectiveFontSize ()I
public fun getEffectiveLetterSpacing ()F
public fun getEffectiveLineHeight ()F
public static fun getEllipsizeMode (Ljava/lang/String;)Landroid/text/TextUtils$TruncateAt;
public fun getFontFamily ()Ljava/lang/String;
public fun getFontFeatureSettings ()Ljava/lang/String;
public fun getFontStyle ()I
public fun getFontWeight ()I
public static fun getHyphenationFrequency (Ljava/lang/String;)I
public static fun getJustificationMode (Lcom/facebook/react/uimanager/ReactStylesDiffMap;I)I
public static fun getLayoutDirection (Ljava/lang/String;)I
public fun getLetterSpacing ()F
public fun getOpacity ()F
public fun getRole ()Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$Role;
public static fun getTextAlignment (Lcom/facebook/react/uimanager/ReactStylesDiffMap;ZI)I
public static fun getTextBreakStrategy (Ljava/lang/String;)I
public fun getTextShadowColor ()I
public fun getTextShadowOffsetDx ()F
public fun getTextShadowOffsetDy ()F
public fun getTextShadowRadius ()F
public fun getTextTransform ()Lcom/facebook/react/views/text/TextTransform;
public fun isBackgroundColorSet ()Z
public fun isColorSet ()Z
public fun isLineThroughTextDecorationSet ()Z
public fun isUnderlineTextDecorationSet ()Z
public final fun getAccessibilityRole ()Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;
public final fun getAllowFontScaling ()Z
public final fun getBackgroundColor ()Ljava/lang/Integer;
public final fun getColor ()Ljava/lang/Integer;
public final fun getEffectiveLetterSpacing ()F
public final fun getEffectiveLineHeight ()F
public final fun getFontFamily ()Ljava/lang/String;
public final fun getFontFeatureSettings ()Ljava/lang/String;
public final fun getFontSize ()I
public final fun getFontStyle ()I
public final fun getFontWeight ()I
public final fun getLayoutDirection ()I
public final fun getLetterSpacing ()F
public final fun getLineHeight ()F
public final fun getMaxFontSizeMultiplier ()F
public final fun getNumberOfLines ()I
public final fun getOpacity ()F
public final fun getRole ()Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$Role;
public final fun getTextShadowColor ()I
public final fun getTextShadowOffsetDx ()F
public final fun getTextShadowOffsetDy ()F
public final fun getTextShadowRadius ()F
public final fun isBackgroundColorSet ()Z
public final fun isColorSet ()Z
public final fun isLineThroughTextDecorationSet ()Z
public final fun isUnderlineTextDecorationSet ()Z
}
public final class com/facebook/react/views/text/TextAttributeProps$Companion {
public final fun fromMapBuffer (Lcom/facebook/react/common/mapbuffer/MapBuffer;)Lcom/facebook/react/views/text/TextAttributeProps;
public final fun fromReadableMap (Lcom/facebook/react/uimanager/ReactStylesDiffMap;)Lcom/facebook/react/views/text/TextAttributeProps;
public final fun getEllipsizeMode (Ljava/lang/String;)Landroid/text/TextUtils$TruncateAt;
public final fun getHyphenationFrequency (Ljava/lang/String;)I
public final fun getJustificationMode (Lcom/facebook/react/uimanager/ReactStylesDiffMap;I)I
public final fun getLayoutDirection (Ljava/lang/String;)I
public final fun getTextAlignment (Lcom/facebook/react/uimanager/ReactStylesDiffMap;ZI)I
public final fun getTextBreakStrategy (Ljava/lang/String;)I
}
public final class com/facebook/react/views/text/TextAttributes {
@@ -630,7 +630,6 @@ dependencies {
api(libs.androidx.autofill)
api(libs.androidx.swiperefreshlayout)
api(libs.androidx.tracing)
api(libs.androidx.window)
api(libs.fbjni)
api(libs.fresco)
@@ -30,7 +30,6 @@ import com.facebook.react.modules.debug.DevSettingsModule
import com.facebook.react.modules.debug.SourceCodeModule
import com.facebook.react.modules.deviceinfo.DeviceInfoModule
import com.facebook.react.modules.systeminfo.AndroidInfoModule
import com.facebook.react.uimanager.UIManagerModule
import com.facebook.react.uimanager.ViewManager
import com.facebook.react.uimanager.ViewManagerResolver
import com.facebook.systrace.Systrace
@@ -38,6 +37,7 @@ import com.facebook.systrace.Systrace
/**
* This is the basic module to support React Native. The debug modules are now in DebugCorePackage.
*/
@Suppress("DEPRECATION")
@ReactModuleList(
// WARNING: If you modify this list, ensure that the list below in method
// getReactModuleInfoByInitialization is also updated
@@ -53,9 +53,11 @@ import com.facebook.systrace.Systrace
HeadlessJsTaskSupportModule::class,
SourceCodeModule::class,
TimingModule::class,
UIManagerModule::class])
com.facebook.react.uimanager.UIManagerModule::class])
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Suppress("DEPRECATION")
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
internal class CoreModulesPackage(
private val reactInstanceManager: ReactInstanceManager,
private val hardwareBackBtnHandler: DefaultHardwareBackBtnHandler,
@@ -103,7 +105,7 @@ internal class CoreModulesPackage(
HeadlessJsTaskSupportModule::class.java,
SourceCodeModule::class.java,
TimingModule::class.java,
UIManagerModule::class.java,
com.facebook.react.uimanager.UIManagerModule::class.java,
)
val reactModuleInfoMap: MutableMap<String, ReactModuleInfo> = HashMap<String, ReactModuleInfo>()
@@ -140,7 +142,7 @@ internal class CoreModulesPackage(
HeadlessJsTaskSupportModule.NAME -> HeadlessJsTaskSupportModule(reactContext)
SourceCodeModule.NAME -> SourceCodeModule(reactContext)
TimingModule.NAME -> TimingModule(reactContext, reactInstanceManager.devSupportManager)
UIManagerModule.NAME -> createUIManager(reactContext)
com.facebook.react.uimanager.UIManagerModule.NAME -> createUIManager(reactContext)
DeviceInfoModule.NAME -> DeviceInfoModule(reactContext)
else ->
throw IllegalArgumentException(
@@ -148,7 +150,9 @@ internal class CoreModulesPackage(
}
}
private fun createUIManager(reactContext: ReactApplicationContext): UIManagerModule {
private fun createUIManager(
reactContext: ReactApplicationContext
): com.facebook.react.uimanager.UIManagerModule {
ReactMarker.logMarker(ReactMarkerConstants.CREATE_UI_MANAGER_MODULE_START)
Systrace.beginSection(Systrace.TRACE_TAG_REACT, "createUIManagerModule")
@@ -165,9 +169,10 @@ internal class CoreModulesPackage(
}
}
return UIManagerModule(reactContext, resolver, minTimeLeftInFrameForNonBatchedOperationMs)
return com.facebook.react.uimanager.UIManagerModule(
reactContext, resolver, minTimeLeftInFrameForNonBatchedOperationMs)
} else {
return UIManagerModule(
return com.facebook.react.uimanager.UIManagerModule(
reactContext,
reactInstanceManager.getOrCreateViewManagers(reactContext),
minTimeLeftInFrameForNonBatchedOperationMs)
@@ -5,6 +5,8 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react
import com.facebook.react.bridge.ModuleHolder
@@ -16,6 +18,9 @@ import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger
/** Helper class to build NativeModuleRegistry. */
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
public class NativeModuleRegistryBuilder(
private val reactApplicationContext: ReactApplicationContext,
) {
@@ -262,11 +262,7 @@ public class ReactInstanceManager {
FLog.d(TAG, "ReactInstanceManager.ctor()");
initializeSoLoaderIfNecessary(applicationContext);
DisplayMetricsHolder.initScreenDisplayMetricsIfNotInitialized(applicationContext);
if (currentActivity != null) {
DisplayMetricsHolder.initWindowDisplayMetricsIfNotInitialized(currentActivity);
}
DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(applicationContext);
// See {@code ReactInstanceManagerBuilder} for description of all flags here.
mApplicationContext = applicationContext;
@@ -931,13 +927,6 @@ public class ReactInstanceManager {
ReactContext currentReactContext = getCurrentReactContext();
if (currentReactContext != null) {
DisplayMetricsHolder.initScreenDisplayMetrics(currentReactContext);
Activity currentActivity = currentReactContext.getCurrentActivity();
if (currentActivity != null) {
DisplayMetricsHolder.initWindowDisplayMetrics(currentActivity);
}
AppearanceModule appearanceModule =
currentReactContext.getNativeModule(AppearanceModule.class);
@@ -136,8 +136,9 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
setRootViewTag(ReactRootViewTagGenerator.getNextRootViewTag());
setClipChildren(false);
DisplayMetricsHolder.initScreenDisplayMetrics(getContext());
DisplayMetricsHolder.initWindowDisplayMetrics(getContext());
if (ReactNativeFeatureFlags.enableFontScaleChangesUpdatingLayout()) {
DisplayMetricsHolder.initDisplayMetrics(getContext().getApplicationContext());
}
}
@Override
@@ -882,8 +883,7 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
private int mDeviceRotation = 0;
/* package */ CustomGlobalLayoutListener() {
DisplayMetricsHolder.initScreenDisplayMetricsIfNotInitialized(getContext());
DisplayMetricsHolder.initWindowDisplayMetricsIfNotInitialized(getContext());
DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(getContext().getApplicationContext());
mVisibleViewArea = new Rect();
mMinKeyboardHeightDetected = (int) PixelUtil.toPixelFromDIP(60);
}
@@ -1006,8 +1006,7 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
return;
}
mDeviceRotation = rotation;
DisplayMetricsHolder.initScreenDisplayMetrics(getContext());
DisplayMetricsHolder.initWindowDisplayMetrics(getContext());
DisplayMetricsHolder.initDisplayMetrics(getContext().getApplicationContext());
emitOrientationChanged(rotation);
}
@@ -28,7 +28,6 @@ import com.facebook.react.modules.core.ReactChoreographer
import com.facebook.react.uimanager.GuardedFrameCallback
import com.facebook.react.uimanager.UIBlock
import com.facebook.react.uimanager.UIManagerHelper
import com.facebook.react.uimanager.UIManagerModule
import com.facebook.react.uimanager.common.UIManagerType
import com.facebook.react.uimanager.common.ViewUtil
import java.util.ArrayList
@@ -74,9 +73,9 @@ import kotlin.concurrent.Volatile
* that coordinates all the action: [NativeAnimatedNodesManager]. Since all the methods from
* [NativeAnimatedNodesManager] need to be called from the UI thread, we we create a queue of
* animated graph operations that is then enqueued to be executed in the UI Thread at the end of the
* batch of JS->native calls (similarly to how it's handled in [UIManagerModule]). This isolates us
* from the problems that may be caused by concurrent updates of animated graph while UI thread is
* "executing" the animation loop.
* batch of JS->native calls (similarly to how it's handled in
* [com.facebook.react.uimanager.UIManagerModule]). This isolates us from the problems that may be
* caused by concurrent updates of animated graph while UI thread is "executing" the animation loop.
*/
@OptIn(UnstableReactNativeAPI::class)
@ReactModule(name = NativeAnimatedModuleSpec.NAME)
@@ -306,6 +305,7 @@ public class NativeAnimatedModule(reactContext: ReactApplicationContext) :
}
// For non-FabricUIManager only
@Suppress("DEPRECATION")
@UiThread
override fun willDispatchViewUpdates(uiManager: UIManager) {
if (operations.isEmpty && preOperations.isEmpty) {
@@ -325,8 +325,8 @@ public class NativeAnimatedModule(reactContext: ReactApplicationContext) :
val operationsUIBlock = UIBlock { operations.executeBatch(frameNo, nodesManager) }
assert(uiManager is UIManagerModule)
val uiManagerModule = uiManager as UIManagerModule
assert(uiManager is com.facebook.react.uimanager.UIManagerModule)
val uiManagerModule = uiManager as com.facebook.react.uimanager.UIManagerModule
uiManagerModule.prependUIBlock(preOperationsUIBlock)
uiManagerModule.addUIBlock(operationsUIBlock)
}
@@ -40,7 +40,8 @@ import java.util.Objects;
*/
@VisibleForTesting
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated
@Deprecated(
since = "This class is part of Legacy Architecture and will be removed in a future release")
@Nullsafe(Nullsafe.Mode.LOCAL)
public class BridgeReactContext extends ReactApplicationContext {
static {
@@ -5,6 +5,8 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.bridge
import com.facebook.react.common.annotations.internal.LegacyArchitecture
@@ -13,6 +15,9 @@ import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger
/** Implementation of javascript callback function that uses Bridge to schedule method execution. */
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
internal class CallbackImpl(private val jsInstance: JSInstance, private val callbackId: Int) :
Callback {
private var invoked = false
@@ -5,6 +5,8 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.bridge
import com.facebook.proguard.annotations.DoNotStrip
@@ -48,9 +48,11 @@ import java.util.concurrent.atomic.AtomicInteger;
*/
@DoNotStrip
@LegacyArchitecture
@Deprecated(
since = "This class is part of Legacy Architecture and will be removed in a future release")
public class CatalystInstanceImpl implements CatalystInstance {
static {
BridgeSoLoader.staticInit();
ReactNativeJNISoLoader.staticInit();
LegacyArchitectureLogger.assertLegacyArchitecture(
"CatalystInstanceImpl", LegacyArchitectureLogLevel.WARNING);
}
@@ -50,7 +50,7 @@ protected constructor(
private companion object {
init {
BridgeSoLoader.staticInit()
ReactNativeJNISoLoader.staticInit()
LegacyArchitectureLogger.assertLegacyArchitecture(
"CxxModuleWrapperBase", LegacyArchitectureLogLevel.WARNING)
}
@@ -49,7 +49,7 @@ private constructor(@Suppress("NoHungarianNotation") private val mHybridData: Hy
public companion object {
init {
BridgeSoLoader.staticInit()
ReactNativeJNISoLoader.staticInit()
}
@JvmStatic
@@ -17,6 +17,9 @@ import com.facebook.systrace.SystraceMessage
import java.lang.reflect.InvocationTargetException
import java.lang.reflect.Method
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
internal class JavaMethodWrapper(
private val moduleWrapper: JavaModuleWrapper,
@@ -26,6 +29,7 @@ internal class JavaMethodWrapper(
private abstract class ArgumentExtractor<T> {
open fun getJSArgumentsNeeded(): Int = 1
@Suppress("DEPRECATION")
abstract fun extractArgument(
jsInstance: JSInstance,
jsArguments: ReadableArray,
@@ -157,6 +161,7 @@ internal class JavaMethodWrapper(
"$startIndex"
}
@Suppress("DEPRECATION")
override fun invoke(jsInstance: JSInstance, parameters: ReadableArray) {
val traceName = moduleWrapper.name + "." + method.name
SystraceMessage.beginSection(TRACE_TAG_REACT, "callJavaModuleMethod")
@@ -240,6 +245,7 @@ internal class JavaMethodWrapper(
private val ARGUMENT_EXTRACTOR_BOOLEAN: ArgumentExtractor<Boolean> =
object : ArgumentExtractor<Boolean>() {
@Suppress("DEPRECATION")
override fun extractArgument(
jsInstance: JSInstance,
jsArguments: ReadableArray,
@@ -249,6 +255,7 @@ internal class JavaMethodWrapper(
private val ARGUMENT_EXTRACTOR_DOUBLE: ArgumentExtractor<Double> =
object : ArgumentExtractor<Double>() {
@Suppress("DEPRECATION")
override fun extractArgument(
jsInstance: JSInstance,
jsArguments: ReadableArray,
@@ -258,6 +265,7 @@ internal class JavaMethodWrapper(
private val ARGUMENT_EXTRACTOR_FLOAT: ArgumentExtractor<Float> =
object : ArgumentExtractor<Float>() {
@Suppress("DEPRECATION")
override fun extractArgument(
jsInstance: JSInstance,
jsArguments: ReadableArray,
@@ -267,6 +275,7 @@ internal class JavaMethodWrapper(
private val ARGUMENT_EXTRACTOR_INTEGER: ArgumentExtractor<Int> =
object : ArgumentExtractor<Int>() {
@Suppress("DEPRECATION")
override fun extractArgument(
jsInstance: JSInstance,
jsArguments: ReadableArray,
@@ -276,6 +285,7 @@ internal class JavaMethodWrapper(
private val ARGUMENT_EXTRACTOR_STRING: ArgumentExtractor<String> =
object : ArgumentExtractor<String>() {
@Suppress("DEPRECATION")
override fun extractArgument(
jsInstance: JSInstance,
jsArguments: ReadableArray,
@@ -285,6 +295,7 @@ internal class JavaMethodWrapper(
private val ARGUMENT_EXTRACTOR_ARRAY: ArgumentExtractor<ReadableArray> =
object : ArgumentExtractor<ReadableArray>() {
@Suppress("DEPRECATION")
override fun extractArgument(
jsInstance: JSInstance,
jsArguments: ReadableArray,
@@ -294,6 +305,7 @@ internal class JavaMethodWrapper(
private val ARGUMENT_EXTRACTOR_DYNAMIC: ArgumentExtractor<Dynamic> =
object : ArgumentExtractor<Dynamic>() {
@Suppress("DEPRECATION")
override fun extractArgument(
jsInstance: JSInstance,
jsArguments: ReadableArray,
@@ -303,6 +315,7 @@ internal class JavaMethodWrapper(
private val ARGUMENT_EXTRACTOR_MAP: ArgumentExtractor<ReadableMap> =
object : ArgumentExtractor<ReadableMap>() {
@Suppress("DEPRECATION")
override fun extractArgument(
jsInstance: JSInstance,
jsArguments: ReadableArray,
@@ -312,6 +325,7 @@ internal class JavaMethodWrapper(
private val ARGUMENT_EXTRACTOR_CALLBACK: ArgumentExtractor<Callback> =
object : ArgumentExtractor<Callback>() {
@Suppress("DEPRECATION")
override fun extractArgument(
jsInstance: JSInstance,
jsArguments: ReadableArray,
@@ -321,7 +335,7 @@ internal class JavaMethodWrapper(
null
} else {
val id = jsArguments.getDouble(atIndex).toInt()
CallbackImpl(jsInstance, id)
@Suppress("DEPRECATION") CallbackImpl(jsInstance, id)
}
}
@@ -329,6 +343,7 @@ internal class JavaMethodWrapper(
object : ArgumentExtractor<Promise>() {
override fun getJSArgumentsNeeded(): Int = 2
@Suppress("DEPRECATION")
override fun extractArgument(
jsInstance: JSInstance,
jsArguments: ReadableArray,
@@ -25,11 +25,11 @@ import java.lang.reflect.Method
@DoNotStrip
@InteropLegacyArchitecture
internal class JavaModuleWrapper(
private val jsInstance: JSInstance,
@Suppress("DEPRECATION") private val jsInstance: JSInstance,
private val moduleHolder: ModuleHolder
) {
interface NativeMethod {
fun invoke(jsInstance: JSInstance, parameters: ReadableArray)
@Suppress("DEPRECATION") fun invoke(jsInstance: JSInstance, parameters: ReadableArray)
val type: String
}
@@ -74,6 +74,7 @@ internal class JavaModuleWrapper(
targetMethod.getAnnotation(ReactMethod::class.java)?.let { annotation ->
val methodName = targetMethod.name
val md = MethodDescriptor()
@Suppress("DEPRECATION")
val method = JavaMethodWrapper(this, targetMethod, annotation.isBlockingSynchronousMethod)
md.name = methodName
md.type = method.type
@@ -13,6 +13,9 @@ import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger
/** Exception thrown when a native module method call receives unexpected arguments from JS. */
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
internal class NativeArgumentsParseException : JSApplicationCausedNativeException {
constructor(detailMessage: String) : super(detailMessage)
@@ -5,6 +5,8 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.bridge
import com.facebook.react.bridge.ReactMarker.logMarker
@@ -19,6 +21,9 @@ import com.facebook.systrace.Systrace.endSection
/** A set of Java APIs to expose to a particular JavaScript instance. */
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
public class NativeModuleRegistry(
private val reactApplicationContext: ReactApplicationContext,
private val modules: MutableMap<String, ModuleHolder>
@@ -12,6 +12,9 @@ import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel
/** Interface for a module that will be notified when a batch of JS->Java calls has finished. */
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
public fun interface OnBatchCompleteListener {
public fun onBatchComplete()
}
@@ -16,6 +16,9 @@ import java.lang.reflect.Method
@DoNotStrip
@LegacyArchitecture
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
internal object ReactCxxErrorHandler {
init {
LegacyArchitectureLogger.assertLegacyArchitecture(
@@ -5,6 +5,8 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.bridge
import com.facebook.jni.HybridData
@@ -17,6 +19,9 @@ import java.util.concurrent.Executor
@DoNotStripAny
@LegacyArchitecture
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
internal class ReactInstanceManagerInspectorTarget(delegate: TargetDelegate) : AutoCloseable {
@DoNotStripAny
@@ -63,7 +68,7 @@ internal class ReactInstanceManagerInspectorTarget(delegate: TargetDelegate) : A
init {
LegacyArchitectureLogger.assertLegacyArchitecture(
"ReactInstanceManagerInspectorTarget", LegacyArchitectureLogLevel.WARNING)
BridgeSoLoader.staticInit()
ReactNativeJNISoLoader.staticInit()
}
}
}
@@ -7,15 +7,9 @@
package com.facebook.react.bridge
import com.facebook.react.common.annotations.internal.LegacyArchitecture
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger
import com.facebook.soloader.SoLoader
@LegacyArchitecture
internal object BridgeSoLoader {
init {
LegacyArchitectureLogger.assertLegacyArchitecture("BridgeSoLoader")
}
internal object ReactNativeJNISoLoader {
@JvmStatic
@Synchronized
@@ -15,6 +15,9 @@ import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel
* Native.
*/
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
public fun interface UIManagerProvider {
/* Provides a [com.facebook.react.bridge.UIManager] for the context received as a parameter. */
@@ -46,6 +46,9 @@ import com.facebook.react.packagerconnection.RequestHandler
* when all the views has been detached from the instance (through `setDevSupportEnabled` method).
*/
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
public class BridgeDevSupportManager(
applicationContext: Context,
reactInstanceManagerHelper: ReactInstanceDevHelper,
@@ -70,6 +70,7 @@ import com.facebook.react.internal.featureflags.ReactNativeNewArchitectureFeatur
import com.facebook.react.internal.interop.InteropEventEmitter;
import com.facebook.react.modules.core.ReactChoreographer;
import com.facebook.react.modules.i18nmanager.I18nUtil;
import com.facebook.react.uimanager.DisplayMetricsHolder;
import com.facebook.react.uimanager.GuardedFrameCallback;
import com.facebook.react.uimanager.IllegalViewOperationException;
import com.facebook.react.uimanager.PixelUtil;
@@ -97,6 +98,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -725,6 +727,23 @@ public class FabricUIManager
return true;
}
/**
* This method is used to get the encoded screen size without vertical insets for a given surface.
* It's used by the Modal component to determine the size of the screen without vertical insets.
* The method is private as it's accessed via JNI from C++.
*
* @param surfaceId The surface ID of the surface for which the Modal is going to render.
* @return The encoded screen size as a long (both width and height) are represented without
* vertical insets.
*/
private long getEncodedScreenSizeWithoutVerticalInsets(int surfaceId) {
SurfaceMountingManager surfaceMountingManager = mMountingManager.getSurfaceManager(surfaceId);
Objects.requireNonNull(surfaceMountingManager);
ThemedReactContext context = Objects.requireNonNull(surfaceMountingManager.getContext());
return DisplayMetricsHolder.getEncodedScreenSizeWithoutVerticalInsets(
context.getCurrentActivity());
}
@Override
public void addUIManagerEventListener(UIManagerListener listener) {
mListeners.add(listener);
@@ -916,14 +935,14 @@ public class FabricUIManager
if (shouldSchedule) {
Assertions.assertNotNull(mountItem, "MountItem is null");
mMountItemDispatcher.addMountItem(mountItem);
Runnable runnable =
new GuardedRunnable(mReactApplicationContext) {
@Override
public void runGuarded() {
mMountItemDispatcher.tryDispatchMountItems();
}
};
if (UiThreadUtil.isOnUiThread()) {
Runnable runnable =
new GuardedRunnable(mReactApplicationContext) {
@Override
public void runGuarded() {
mMountItemDispatcher.tryDispatchMountItems();
}
};
runnable.run();
}
}
@@ -5,6 +5,8 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.fabric
import com.facebook.react.bridge.ReactApplicationContext
@@ -20,6 +22,9 @@ import com.facebook.systrace.Systrace
* @param [componentFactory] The factory for creating components.
* @param [viewManagerRegistry] The registry of view managers.
*/
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
public class FabricUIManagerProviderImpl(
private val componentFactory: ComponentFactory,
private val viewManagerRegistry: ViewManagerRegistry
@@ -11,7 +11,6 @@ import android.view.Choreographer
import com.facebook.react.bridge.ReactContext
import com.facebook.react.bridge.UiThreadUtil
import com.facebook.react.common.build.ReactBuildConfig
import com.facebook.react.uimanager.UIManagerModule
/**
* Each time a frame is drawn, records whether it should have expected any more callbacks since the
@@ -62,7 +61,8 @@ internal class FpsDebugFrameCallback(private val reactContext: ReactContext) :
// removeBridgeIdleDebugListener for Bridgeless
@Suppress("DEPRECATION")
if (!ReactBuildConfig.UNSTABLE_ENABLE_MINIFY_LEGACY_ARCHITECTURE) {
val uiManagerModule = reactContext.getNativeModule(UIManagerModule::class.java)
val uiManagerModule =
reactContext.getNativeModule(com.facebook.react.uimanager.UIManagerModule::class.java)
if (!reactContext.isBridgeless) {
reactContext.catalystInstance.addBridgeIdleDebugListener(didJSUpdateUiDuringFrameDetector)
isRunningOnFabric = false
@@ -83,7 +83,8 @@ internal class FpsDebugFrameCallback(private val reactContext: ReactContext) :
fun stop() {
@Suppress("DEPRECATION")
if (!ReactBuildConfig.UNSTABLE_ENABLE_MINIFY_LEGACY_ARCHITECTURE) {
val uiManagerModule = reactContext.getNativeModule(UIManagerModule::class.java)
val uiManagerModule =
reactContext.getNativeModule(com.facebook.react.uimanager.UIManagerModule::class.java)
if (!reactContext.isBridgeless) {
reactContext.catalystInstance.removeBridgeIdleDebugListener(
didJSUpdateUiDuringFrameDetector)
@@ -15,8 +15,7 @@ import com.facebook.react.bridge.ReactSoftExceptionLogger
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.module.annotations.ReactModule
import com.facebook.react.uimanager.DisplayMetricsHolder.getDisplayMetricsWritableMap
import com.facebook.react.uimanager.DisplayMetricsHolder.initScreenDisplayMetricsIfNotInitialized
import com.facebook.react.uimanager.DisplayMetricsHolder.initWindowDisplayMetricsIfNotInitialized
import com.facebook.react.uimanager.DisplayMetricsHolder.initDisplayMetricsIfNotInitialized
import com.facebook.react.views.view.isEdgeToEdgeFeatureFlagOn
/** Module that exposes Android Constants to JS. */
@@ -27,8 +26,7 @@ internal class DeviceInfoModule(reactContext: ReactApplicationContext) :
private var previousDisplayMetrics: ReadableMap? = null
init {
initScreenDisplayMetricsIfNotInitialized(reactContext)
reactContext.currentActivity?.let { initWindowDisplayMetricsIfNotInitialized(it) }
initDisplayMetricsIfNotInitialized(reactContext)
reactContext.addLifecycleEventListener(this)
}
@@ -61,7 +61,6 @@ import com.facebook.react.runtime.internal.bolts.Task
import com.facebook.react.runtime.internal.bolts.TaskCompletionSource
import com.facebook.react.turbomodule.core.interfaces.CallInvokerHolder
import com.facebook.react.uimanager.DisplayMetricsHolder
import com.facebook.react.uimanager.UIManagerModule
import com.facebook.react.uimanager.events.BlackHoleEventDispatcher
import com.facebook.react.uimanager.events.EventDispatcher
import com.facebook.react.views.imagehelper.ResourceDrawableIdHelper
@@ -523,9 +522,10 @@ public class ReactHostImpl(
internal val nativeModules: Collection<NativeModule>
get() = reactInstance?.nativeModules ?: listOf()
@Suppress("DEPRECATION")
internal fun <T : NativeModule> getNativeModule(nativeModuleInterface: Class<T>): T? {
if (!ReactBuildConfig.UNSTABLE_ENABLE_MINIFY_LEGACY_ARCHITECTURE &&
nativeModuleInterface == UIManagerModule::class.java) {
nativeModuleInterface == com.facebook.react.uimanager.UIManagerModule::class.java) {
ReactSoftExceptionLogger.logSoftExceptionVerbose(
TAG,
ReactNoCrashSoftException(
@@ -625,8 +625,9 @@ public class ReactHostImpl(
override fun onConfigurationChanged(context: Context) {
val currentReactContext = this.currentReactContext
if (currentReactContext != null) {
DisplayMetricsHolder.initScreenDisplayMetrics(currentReactContext)
currentReactContext.currentActivity?.let { DisplayMetricsHolder.initWindowDisplayMetrics(it) }
if (ReactNativeFeatureFlags.enableFontScaleChangesUpdatingLayout()) {
DisplayMetricsHolder.initDisplayMetrics(currentReactContext)
}
val appearanceModule = currentReactContext.getNativeModule(AppearanceModule::class.java)
appearanceModule?.onConfigurationChanged(context)
@@ -917,7 +918,6 @@ public class ReactHostImpl(
val instance =
ReactInstance(
reactContext,
currentActivity,
reactHostDelegate,
componentFactory,
devSupportManager,
@@ -7,7 +7,6 @@
package com.facebook.react.runtime
import android.app.Activity
import android.content.res.AssetManager
import android.view.View
import com.facebook.common.logging.FLog
@@ -89,7 +88,6 @@ import kotlin.jvm.JvmStatic
@UnstableReactNativeAPI
internal class ReactInstance(
private val context: BridgelessReactContext,
private val activity: Activity?,
delegate: ReactHostDelegate,
componentFactory: ComponentFactory,
devSupportManager: DevSupportManager,
@@ -242,8 +240,7 @@ internal class ReactInstance(
FabricUIManager(context, ViewManagerRegistry(viewManagerResolver), eventBeatManager)
// Misc initialization that needs to be done before Fabric init
DisplayMetricsHolder.initScreenDisplayMetricsIfNotInitialized(context)
activity?.let { DisplayMetricsHolder.initWindowDisplayMetricsIfNotInitialized(it) }
DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(context)
val binding = FabricUIManagerBinding()
binding.register(
@@ -56,9 +56,7 @@ import com.facebook.react.views.scroll.ReactScrollViewManager
import com.facebook.react.views.swiperefresh.SwipeRefreshLayoutManager
import com.facebook.react.views.switchview.ReactSwitchManager
import com.facebook.react.views.text.PreparedLayoutTextViewManager
import com.facebook.react.views.text.ReactRawTextManager
import com.facebook.react.views.text.ReactTextViewManager
import com.facebook.react.views.text.ReactVirtualTextViewManager
import com.facebook.react.views.text.frescosupport.FrescoBasedReactTextInlineImageViewManager
import com.facebook.react.views.textinput.ReactTextInputManager
import com.facebook.react.views.unimplementedview.ReactUnimplementedViewManager
@@ -133,6 +131,7 @@ constructor(private val config: MainPackageConfig? = null) :
else -> null
}
@Suppress("DEPRECATION")
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> =
listOf(
ReactDrawerLayoutManager(),
@@ -147,18 +146,19 @@ constructor(private val config: MainPackageConfig? = null) :
FrescoBasedReactTextInlineImageViewManager(),
ReactImageManager(),
ReactModalHostManager(),
ReactRawTextManager(),
com.facebook.react.views.text.ReactRawTextManager(),
ReactTextInputManager(),
if (ReactNativeFeatureFlags.enablePreparedTextLayout()) PreparedLayoutTextViewManager()
else ReactTextViewManager(),
ReactViewManager(),
ReactVirtualTextViewManager(),
com.facebook.react.views.text.ReactVirtualTextViewManager(),
ReactUnimplementedViewManager())
/**
* A map of view managers that should be registered with
* [com.facebook.react.uimanager.UIManagerModule]
*/
@Suppress("DEPRECATION")
@SuppressLint("VisibleForTests")
public val viewManagersMap: Map<String, ModuleSpec> =
mapOf(
@@ -182,7 +182,8 @@ constructor(private val config: MainPackageConfig? = null) :
ReactImageManager.REACT_CLASS to ModuleSpec.viewManagerSpec { ReactImageManager() },
ReactModalHostManager.REACT_CLASS to
ModuleSpec.viewManagerSpec { ReactModalHostManager() },
ReactRawTextManager.REACT_CLASS to ModuleSpec.viewManagerSpec { ReactRawTextManager() },
com.facebook.react.views.text.ReactRawTextManager.REACT_CLASS to
ModuleSpec.viewManagerSpec { com.facebook.react.views.text.ReactRawTextManager() },
ReactTextInputManager.REACT_CLASS to
ModuleSpec.viewManagerSpec { ReactTextInputManager() },
ReactTextViewManager.REACT_CLASS to
@@ -192,8 +193,10 @@ constructor(private val config: MainPackageConfig? = null) :
else ReactTextViewManager()
},
ReactViewManager.REACT_CLASS to ModuleSpec.viewManagerSpec { ReactViewManager() },
ReactVirtualTextViewManager.REACT_CLASS to
ModuleSpec.viewManagerSpec { ReactVirtualTextViewManager() },
com.facebook.react.views.text.ReactVirtualTextViewManager.REACT_CLASS to
ModuleSpec.viewManagerSpec {
com.facebook.react.views.text.ReactVirtualTextViewManager()
},
ReactUnimplementedViewManager.REACT_CLASS to
ModuleSpec.viewManagerSpec { ReactUnimplementedViewManager() })
@@ -20,7 +20,7 @@ import com.facebook.yoga.YogaConstants
* every view should support, such as rotation, background color, etc.
*/
public abstract class BaseViewManagerDelegate<
T : View, U : BaseViewManager<T, out LayoutShadowNode>>(
T : View, @Suppress("DEPRECATION") U : BaseViewManager<T, out LayoutShadowNode>>(
@Suppress("NoHungarianNotation") @JvmField protected val mViewManager: U
) : ViewManagerDelegate<T> {
@Suppress("ACCIDENTAL_OVERRIDE", "DEPRECATION")
@@ -13,20 +13,17 @@ import android.util.DisplayMetrics
import android.view.WindowManager
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.window.layout.WindowMetricsCalculator
import com.facebook.react.bridge.WritableMap
import com.facebook.react.bridge.WritableNativeMap
import com.facebook.react.views.view.isEdgeToEdgeFeatureFlagOn
import com.facebook.react.uimanager.PixelUtil.pxToDp
/**
* Holds an instance of the current DisplayMetrics so we don't have to thread it through all the
* classes that need it.
*/
public object DisplayMetricsHolder {
private const val SCREEN_INITIALIZATION_MISSING_MESSAGE =
"DisplayMetricsHolder must be initialized with initScreenDisplayMetricsIfNotInitialized or initScreenDisplayMetrics"
private const val WINDOW_INITIALIZATION_MISSING_MESSAGE =
"DisplayMetricsHolder must be initialized with initWindowDisplayMetricsIfNotInitialized or initWindowDisplayMetrics"
private const val INITIALIZATION_MISSING_MESSAGE =
"DisplayMetricsHolder must be initialized with initDisplayMetricsIfNotInitialized or initDisplayMetrics"
@JvmStatic private var windowDisplayMetrics: DisplayMetrics? = null
@JvmStatic private var screenDisplayMetrics: DisplayMetrics? = null
@@ -34,7 +31,7 @@ public object DisplayMetricsHolder {
/** The metrics of the window associated to the Context used to initialize ReactNative */
@JvmStatic
public fun getWindowDisplayMetrics(): DisplayMetrics {
checkNotNull(windowDisplayMetrics) { WINDOW_INITIALIZATION_MISSING_MESSAGE }
checkNotNull(windowDisplayMetrics) { INITIALIZATION_MISSING_MESSAGE }
return windowDisplayMetrics as DisplayMetrics
}
@@ -46,7 +43,7 @@ public object DisplayMetricsHolder {
/** Screen metrics returns the metrics of the default screen on the device. */
@JvmStatic
public fun getScreenDisplayMetrics(): DisplayMetrics {
checkNotNull(screenDisplayMetrics) { SCREEN_INITIALIZATION_MISSING_MESSAGE }
checkNotNull(screenDisplayMetrics) { INITIALIZATION_MISSING_MESSAGE }
return screenDisplayMetrics as DisplayMetrics
}
@@ -56,58 +53,33 @@ public object DisplayMetricsHolder {
}
@JvmStatic
public fun initScreenDisplayMetricsIfNotInitialized(context: Context) {
if (screenDisplayMetrics == null) {
initScreenDisplayMetrics(context)
public fun initDisplayMetricsIfNotInitialized(context: Context) {
if (screenDisplayMetrics != null) {
return
}
initDisplayMetrics(context)
}
@JvmStatic
public fun initWindowDisplayMetricsIfNotInitialized(context: Context) {
if (windowDisplayMetrics == null) {
initWindowDisplayMetrics(context)
}
}
@JvmStatic
public fun initScreenDisplayMetrics(context: Context) {
val displayMetrics = DisplayMetrics()
displayMetrics.setTo(context.resources.displayMetrics)
public fun initDisplayMetrics(context: Context) {
val displayMetrics = context.resources.displayMetrics
windowDisplayMetrics = displayMetrics
val screenDisplayMetrics = DisplayMetrics()
screenDisplayMetrics.setTo(displayMetrics)
val wm = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
// Get the real display metrics if we are using API level 17 or higher.
// The real metrics include system decor elements (e.g. soft menu bar).
//
// See:
// http://developer.android.com/reference/android/view/Display.html#getRealMetrics(android.util.DisplayMetrics)
@Suppress("DEPRECATION") wm.defaultDisplay.getRealMetrics(displayMetrics)
screenDisplayMetrics = displayMetrics
}
/*
* NOTE: Unlike [initScreenDisplayMetrics], this method needs a UiContext (Activity of
* InputMethodService) else WindowMetircsCalculator will throw an exception.
*/
@JvmStatic
public fun initWindowDisplayMetrics(context: Context) {
val displayMetrics = DisplayMetrics()
displayMetrics.setTo(context.resources.displayMetrics)
if (isEdgeToEdgeFeatureFlagOn) {
WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(context).let { windowMetrics
->
displayMetrics.widthPixels = windowMetrics.bounds.width()
displayMetrics.heightPixels = windowMetrics.bounds.height()
}
}
windowDisplayMetrics = displayMetrics
@Suppress("DEPRECATION") wm.defaultDisplay.getRealMetrics(screenDisplayMetrics)
DisplayMetricsHolder.screenDisplayMetrics = screenDisplayMetrics
}
@JvmStatic
public fun getDisplayMetricsWritableMap(fontScale: Double): WritableMap {
checkNotNull(windowDisplayMetrics) { WINDOW_INITIALIZATION_MISSING_MESSAGE }
checkNotNull(screenDisplayMetrics) { SCREEN_INITIALIZATION_MISSING_MESSAGE }
checkNotNull(windowDisplayMetrics) { INITIALIZATION_MISSING_MESSAGE }
checkNotNull(screenDisplayMetrics) { INITIALIZATION_MISSING_MESSAGE }
return WritableNativeMap().apply {
putMap(
@@ -140,4 +112,33 @@ public object DisplayMetricsHolder {
WindowInsetsCompat.Type.displayCutout())
.top
}
/**
* Returns the encoded screen size without vertical insets.
*
* This is needed to render components that needs to be correctly positioned on the screen on
* their first frame. Modal is one of such components.
*
* @param activity the [Activity] to get the insets from.
* @return the encoded screen size as a [Long] value, where the first 32 bits represent the width
* and the last 32 bits represent the height in dp (density-independent pixels).
*/
// This annotation can be removed once FabricUIManager is migrated to Kotlin
@JvmName("getEncodedScreenSizeWithoutVerticalInsets")
@JvmStatic
internal fun getEncodedScreenSizeWithoutVerticalInsets(activity: Activity?): Long {
val windowInsets = activity?.window?.decorView?.let(ViewCompat::getRootWindowInsets) ?: return 0
val insets =
windowInsets.getInsets(
WindowInsetsCompat.Type.statusBars() or
WindowInsetsCompat.Type.navigationBars() or
WindowInsetsCompat.Type.displayCutout())
val verticalInsets = insets.top + insets.bottom
return encodeFloatsToLong(
(checkNotNull(screenDisplayMetrics).widthPixels).toFloat().pxToDp(),
(checkNotNull(screenDisplayMetrics).heightPixels - verticalInsets).toFloat().pxToDp())
}
internal fun encodeFloatsToLong(width: Float, height: Float): Long =
(width.toRawBits().toLong()) shl 32 or (height.toRawBits().toLong())
}
@@ -14,6 +14,9 @@ import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger
import com.facebook.yoga.YogaDirection
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
internal object LayoutDirectionUtil {
init {
LegacyArchitectureLogger.assertLegacyArchitecture(
@@ -38,6 +38,8 @@ import com.facebook.yoga.YogaWrap;
* explored, namely using the VirtualText class in JS and setting the correct set of validAttributes
*/
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
since = "This class is part of Legacy Architecture and will be removed in a future release")
public class LayoutShadowNode extends ReactShadowNodeImpl {
static {
LegacyArchitectureLogger.assertLegacyArchitecture(
@@ -14,6 +14,9 @@ import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel
// - `kind == PARENT` checks whether the node can host children in the native tree.
// - `kind != NONE` checks whether the node appears in the native tree.
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
internal enum class NativeKind {
// Node is in the native hierarchy and the HierarchyOptimizer should assume it can host children
// (e.g. because it's a ViewGroup). Note that it's okay if the node doesn't support children. When
@@ -68,6 +68,8 @@ import javax.annotation.concurrent.NotThreadSafe;
*/
@NotThreadSafe
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
since = "This class is part of Legacy Architecture and will be removed in a future release")
public class NativeViewHierarchyManager {
static {
@@ -49,6 +49,8 @@ import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger;
* depending on where the views being added/removed are attached in the optimized hierarchy
*/
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
since = "This class is part of Legacy Architecture and will be removed in a future release")
public class NativeViewHierarchyOptimizer {
static {
@@ -16,6 +16,9 @@ import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger
* associated with it.
*/
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
internal class NoSuchNativeViewException(detailMessage: String) :
IllegalViewOperationException(detailMessage) {
@@ -5,6 +5,8 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.uimanager
import androidx.core.util.Pools.SynchronizedPool
@@ -20,6 +22,9 @@ import com.facebook.react.uimanager.events.Event
/** Event used to notify JS component about changes of its position or dimensions. */
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.WARNING)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
public class OnLayoutEvent private constructor() : Event<OnLayoutEvent>() {
@VisibleForTesting internal var x: Int = 0
@VisibleForTesting internal var y: Int = 0
@@ -20,7 +20,7 @@ public object PixelUtil {
}
return TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, value, DisplayMetricsHolder.getScreenDisplayMetrics())
TypedValue.COMPLEX_UNIT_DIP, value, DisplayMetricsHolder.getWindowDisplayMetrics())
}
/** Convert from DIP to PX */
@@ -37,7 +37,7 @@ public object PixelUtil {
return Float.NaN
}
val displayMetrics = DisplayMetricsHolder.getScreenDisplayMetrics()
val displayMetrics = DisplayMetricsHolder.getWindowDisplayMetrics()
val scaledValue = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, value, displayMetrics)
if (maxFontScale >= 1) {
@@ -60,13 +60,13 @@ public object PixelUtil {
return Float.NaN
}
return value / DisplayMetricsHolder.getScreenDisplayMetrics().density
return value / DisplayMetricsHolder.getWindowDisplayMetrics().density
}
/** @return [Float] that represents the density of the display metrics for device screen. */
@JvmStatic
public fun getDisplayMetricDensity(): Float =
DisplayMetricsHolder.getScreenDisplayMetrics().density
DisplayMetricsHolder.getWindowDisplayMetrics().density
/* Kotlin extensions */
public fun Int.dpToPx(): Float = toPixelFromDIP(this.toFloat())
@@ -0,0 +1,992 @@
/*
* 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.uimanager
import android.content.Context
import android.graphics.Rect
import android.os.Bundle
import android.os.Handler
import android.os.Message
import android.view.View
import android.view.ViewGroup
import android.view.accessibility.AccessibilityEvent
import android.widget.EditText
import androidx.core.view.ViewCompat
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat.CollectionItemInfoCompat
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat.RangeInfoCompat
import androidx.core.view.accessibility.AccessibilityNodeProviderCompat
import androidx.customview.widget.ExploreByTouchHelper
import com.facebook.infer.annotation.Assertions
import com.facebook.react.R
import com.facebook.react.bridge.Arguments.createMap
import com.facebook.react.bridge.ReactContext
import com.facebook.react.bridge.ReactNoCrashSoftException
import com.facebook.react.bridge.ReactSoftExceptionLogger.logSoftException
import com.facebook.react.bridge.ReadableArray
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.bridge.ReadableType
import com.facebook.react.bridge.WritableMap
import com.facebook.react.uimanager.UIManagerHelper.getSurfaceId
import com.facebook.react.uimanager.UIManagerHelper.getUIManager
import com.facebook.react.uimanager.common.ViewUtil.getUIManagerType
import com.facebook.react.uimanager.events.Event
import com.facebook.react.uimanager.util.ReactFindViewUtil.findView
/**
* Utility class that handles the addition of a "role" for accessibility to either a View or
* AccessibilityNodeInfo.
*/
public open class ReactAccessibilityDelegate( // The View this delegate is attached to
protected val hostView: View,
originalFocus: Boolean,
originalImportantForAccessibility: Int
) : ExploreByTouchHelper(hostView) {
@Suppress("DEPRECATION") // TODO: Replace with handler tied to host view's context
private val accessibilityEventHandler: Handler =
object : Handler() {
override fun handleMessage(msg: Message) {
val host = msg.obj as View?
host?.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED)
}
}
private val accessibilityActionsMap = HashMap<Int, String?>()
private var accessibilityLabelledBy: View? = null
init {
// We need to reset these two properties, as ExploreByTouchHelper sets focusable to "true" and
// importantForAccessibility to "Yes" (if it is Auto). If we don't reset these it would force
// every element that has this delegate attached to be focusable, and not allow for
// announcement coalescing.
hostView.isFocusable = originalFocus
hostView.importantForAccessibility = originalImportantForAccessibility
}
override fun onInitializeAccessibilityNodeInfo(host: View, info: AccessibilityNodeInfoCompat) {
super.onInitializeAccessibilityNodeInfo(host, info)
if (host.getTag(R.id.accessibility_state_expanded) != null) {
val accessibilityStateExpanded = host.getTag(R.id.accessibility_state_expanded) as Boolean
info.addAction(
if (accessibilityStateExpanded) AccessibilityNodeInfoCompat.ACTION_COLLAPSE
else AccessibilityNodeInfoCompat.ACTION_EXPAND)
}
val accessibilityRole = AccessibilityRole.fromViewTag(host)
val accessibilityHint = host.getTag(R.id.accessibility_hint) as String?
if (accessibilityRole != null) {
setRole(info, accessibilityRole, host.context)
}
if (accessibilityHint != null) {
info.tooltipText = accessibilityHint
}
val accessibilityLabelledBy = host.getTag(R.id.labelled_by)
if (accessibilityLabelledBy != null) {
this.accessibilityLabelledBy = findView(host.rootView, accessibilityLabelledBy as String)
if (this.accessibilityLabelledBy != null) {
info.setLabeledBy(this.accessibilityLabelledBy)
}
}
// state is changeable.
val accessibilityState = host.getTag(R.id.accessibility_state) as ReadableMap?
if (accessibilityState != null) {
setState(info, accessibilityState)
}
val accessibilityActions = host.getTag(R.id.accessibility_actions) as ReadableArray?
val accessibilityCollectionItem =
host.getTag(R.id.accessibility_collection_item) as ReadableMap?
if (accessibilityCollectionItem != null) {
val rowIndex = accessibilityCollectionItem.getInt("rowIndex")
val columnIndex = accessibilityCollectionItem.getInt("columnIndex")
val rowSpan = accessibilityCollectionItem.getInt("rowSpan")
val columnSpan = accessibilityCollectionItem.getInt("columnSpan")
val heading = accessibilityCollectionItem.getBoolean("heading")
val collectionItemCompat =
CollectionItemInfoCompat.obtain(rowIndex, rowSpan, columnIndex, columnSpan, heading)
info.setCollectionItemInfo(collectionItemCompat)
}
if (accessibilityActions != null) {
for (i in 0..<accessibilityActions.size()) {
val action = accessibilityActions.getMap(i)
require(!(action == null || !action.hasKey("name"))) { "Unknown accessibility action." }
val actionName = action.getString("name")
// AccessibilityActionCompat actionLabel must be non-null
val actionLabel =
if (action.hasKey("label")) Assertions.assertNotNull(action.getString("label")) else ""
val actionId: Int =
actionIdMap.get(actionName)
?: customActionIdMap.getOrPut(actionName) { customActionCounter++ }
accessibilityActionsMap[actionId] = actionName
val accessibilityAction = AccessibilityActionCompat(actionId, actionLabel)
info.addAction(accessibilityAction)
}
}
// Process accessibilityValue
val accessibilityValue = host.getTag(R.id.accessibility_value) as ReadableMap?
if (accessibilityValue != null &&
accessibilityValue.hasKey("min") &&
accessibilityValue.hasKey("now") &&
accessibilityValue.hasKey("max")) {
val minDynamic = accessibilityValue.getDynamic("min")
val nowDynamic = accessibilityValue.getDynamic("now")
val maxDynamic = accessibilityValue.getDynamic("max")
if (minDynamic.type == ReadableType.Number &&
nowDynamic.type == ReadableType.Number &&
maxDynamic.type == ReadableType.Number) {
val min = minDynamic.asInt()
val now = nowDynamic.asInt()
val max = maxDynamic.asInt()
if (max > min && now >= min && max >= now) {
info.rangeInfo =
RangeInfoCompat.obtain(
RangeInfoCompat.RANGE_TYPE_INT, min.toFloat(), max.toFloat(), now.toFloat())
}
}
}
// Expose the testID prop as the resource-id name of the view. Black-box E2E/UI testing
// frameworks, which interact with the UI through the accessibility framework, do not have
// access to view tags. This allows developers/testers to avoid polluting the
// content-description with test identifiers.
val testId = host.getTag(R.id.react_test_id) as String?
if (testId != null) {
info.viewIdResourceName = testId
}
val missingContentDescription = info.contentDescription.isNullOrEmpty()
val missingText = info.text.isNullOrEmpty()
val missingTextAndDescription = missingContentDescription && missingText
val hasContentToAnnounce =
accessibilityActions != null ||
accessibilityState != null ||
accessibilityLabelledBy != null ||
accessibilityRole != null
if (missingTextAndDescription && hasContentToAnnounce) {
info.contentDescription = getTalkbackDescription(host, info)
}
}
override fun onInitializeAccessibilityEvent(host: View, event: AccessibilityEvent) {
super.onInitializeAccessibilityEvent(host, event)
// Set item count and current item index on accessibility events for adjustable
// in order to make Talkback announce the value of the adjustable
val accessibilityValue = host.getTag(R.id.accessibility_value) as ReadableMap?
if (accessibilityValue != null &&
accessibilityValue.hasKey("min") &&
accessibilityValue.hasKey("now") &&
accessibilityValue.hasKey("max")) {
val minDynamic = accessibilityValue.getDynamic("min")
val nowDynamic = accessibilityValue.getDynamic("now")
val maxDynamic = accessibilityValue.getDynamic("max")
if (minDynamic.type == ReadableType.Number &&
nowDynamic.type == ReadableType.Number &&
maxDynamic.type == ReadableType.Number) {
val min = minDynamic.asInt()
val now = nowDynamic.asInt()
val max = maxDynamic.asInt()
if (max > min && now >= min && max >= now) {
event.itemCount = max - min
event.currentItemIndex = now
}
}
}
}
override fun performAccessibilityAction(host: View, action: Int, args: Bundle?): Boolean {
if (action == AccessibilityNodeInfoCompat.ACTION_COLLAPSE) {
host.setTag(R.id.accessibility_state_expanded, false)
}
if (action == AccessibilityNodeInfoCompat.ACTION_EXPAND) {
host.setTag(R.id.accessibility_state_expanded, true)
}
if (accessibilityActionsMap.containsKey(action)) {
val eventData = createMap()
eventData.putString("actionName", accessibilityActionsMap[action])
val reactContext = host.context as ReactContext
if (reactContext.hasActiveReactInstance()) {
val reactTag = host.id
val surfaceId = getSurfaceId(reactContext)
val uiManager = getUIManager(reactContext, getUIManagerType(reactTag))
if (uiManager != null) {
uiManager.eventDispatcher.dispatchEvent(
AccessibilityActionEvent(eventData, surfaceId, reactTag))
}
} else {
logSoftException(
TAG, ReactNoCrashSoftException("Cannot get RCTEventEmitter, no CatalystInstance"))
}
// In order to make Talkback announce the change of the adjustable's value,
// schedule to send a TYPE_VIEW_SELECTED event after performing the scroll actions.
val accessibilityRole = host.getTag(R.id.accessibility_role) as AccessibilityRole
val accessibilityValue = host.getTag(R.id.accessibility_value) as ReadableMap?
if (accessibilityRole == AccessibilityRole.ADJUSTABLE &&
(action == AccessibilityActionCompat.ACTION_SCROLL_FORWARD.id ||
(action == AccessibilityActionCompat.ACTION_SCROLL_BACKWARD.id))) {
if (accessibilityValue != null && !accessibilityValue.hasKey("text")) {
scheduleAccessibilityEventSender(host)
}
return super.performAccessibilityAction(host, action, args)
}
return true
}
return super.performAccessibilityAction(host, action, args)
}
/**
* Schedule a command for sending an accessibility event. Note: A command is used to ensure that
* accessibility events are sent at most one in a given time frame to save system resources while
* the progress changes quickly.
*/
private fun scheduleAccessibilityEventSender(host: View) {
if (accessibilityEventHandler.hasMessages(SEND_EVENT, host)) {
accessibilityEventHandler.removeMessages(SEND_EVENT, host)
}
val msg = accessibilityEventHandler.obtainMessage(SEND_EVENT, host)
accessibilityEventHandler.sendMessageDelayed(msg, TIMEOUT_SEND_ACCESSIBILITY_EVENT.toLong())
}
override fun getVirtualViewAt(x: Float, y: Float): Int {
return INVALID_ID
}
override fun getVisibleVirtualViews(virtualViewIds: MutableList<Int>): Unit = Unit
override fun onPopulateNodeForVirtualView(virtualViewId: Int, node: AccessibilityNodeInfoCompat) {
node.contentDescription = ""
@Suppress("DEPRECATION") // TODO: Remove this
node.setBoundsInParent(Rect(0, 0, 1, 1))
}
override fun onPerformActionForVirtualView(
virtualViewId: Int,
action: Int,
arguments: Bundle?
): Boolean {
return false
}
override fun getAccessibilityNodeProvider(host: View): AccessibilityNodeProviderCompat? {
return null
}
// This exists so classes that extend this can properly call super's impl of this method while
// still being able to override it properly for this class
protected fun superGetAccessibilityNodeProvider(host: View): AccessibilityNodeProviderCompat? {
return super.getAccessibilityNodeProvider(host)
}
/**
* An ARIA Role representable by View's `role` prop. Ordinals should be kept in sync with
* `facebook::react::Role`.
*/
public enum class Role {
ALERT,
ALERTDIALOG,
APPLICATION,
ARTICLE,
BANNER,
BUTTON,
CELL,
CHECKBOX,
COLUMNHEADER,
COMBOBOX,
COMPLEMENTARY,
CONTENTINFO,
DEFINITION,
DIALOG,
DIRECTORY,
DOCUMENT,
FEED,
FIGURE,
FORM,
GRID,
GROUP,
HEADING,
IMG,
LINK,
LIST,
LISTITEM,
LOG,
MAIN,
MARQUEE,
MATH,
MENU,
MENUBAR,
MENUITEM,
METER,
NAVIGATION,
NONE,
NOTE,
OPTION,
PRESENTATION,
PROGRESSBAR,
RADIO,
RADIOGROUP,
REGION,
ROW,
ROWGROUP,
ROWHEADER,
SCROLLBAR,
SEARCHBOX,
SEPARATOR,
SLIDER,
SPINBUTTON,
STATUS,
SUMMARY,
SWITCH,
TAB,
TABLE,
TABLIST,
TABPANEL,
TERM,
TIMER,
TOOLBAR,
TOOLTIP,
TREE,
TREEGRID,
TREEITEM;
public companion object {
@JvmStatic
public fun fromValue(value: String?): Role? {
for (role in entries) {
if (role.name.equals(value, ignoreCase = true)) {
return role
}
}
return null
}
}
}
private class AccessibilityActionEvent(
private val accessibilityEventData: WritableMap,
surfaceId: Int,
viewId: Int
) : Event<AccessibilityActionEvent>(surfaceId, viewId) {
override fun getEventName(): String {
return TOP_ACCESSIBILITY_ACTION_EVENT
}
public override fun getEventData(): WritableMap? {
return accessibilityEventData
}
}
/**
* These roles are defined by Google's TalkBack screen reader, and this list should be kept up to
* date with their implementation. Details can be seen in their source code here:
*
* https://github.com/google/talkback/blob/master/utils/src/main/java/Role.java
*/
public enum class AccessibilityRole {
NONE,
BUTTON,
DROPDOWNLIST,
TOGGLEBUTTON,
LINK,
SEARCH,
IMAGE,
IMAGEBUTTON,
KEYBOARDKEY,
TEXT,
ADJUSTABLE,
SUMMARY,
HEADER,
ALERT,
CHECKBOX,
COMBOBOX,
MENU,
MENUBAR,
MENUITEM,
PROGRESSBAR,
RADIO,
RADIOGROUP,
SCROLLBAR,
SPINBUTTON,
SWITCH,
TAB,
TABLIST,
TIMER,
LIST,
GRID,
PAGER,
SCROLLVIEW,
HORIZONTALSCROLLVIEW,
VIEWGROUP,
WEBVIEW,
DRAWERLAYOUT,
SLIDINGDRAWER,
ICONMENU,
TOOLBAR;
public companion object {
@JvmStatic
public fun getValue(role: AccessibilityRole): String {
return when (role) {
BUTTON -> "android.widget.Button"
DROPDOWNLIST -> "android.widget.Spinner"
TOGGLEBUTTON -> "android.widget.ToggleButton"
SEARCH -> "android.widget.EditText"
IMAGE -> "android.widget.ImageView"
IMAGEBUTTON -> "android.widget.ImageButton"
KEYBOARDKEY -> "android.inputmethodservice.Keyboard\$Key"
TEXT -> "android.widget.TextView"
ADJUSTABLE -> "android.widget.SeekBar"
CHECKBOX -> "android.widget.CheckBox"
RADIO -> "android.widget.RadioButton"
SPINBUTTON -> "android.widget.SpinButton"
SWITCH -> "android.widget.Switch"
LIST -> "android.widget.AbsListView"
GRID -> "android.widget.GridView"
SCROLLVIEW -> "android.widget.ScrollView"
HORIZONTALSCROLLVIEW -> "android.widget.HorizontalScrollView"
PAGER -> "androidx.viewpager.widget.ViewPager"
DRAWERLAYOUT -> "androidx.drawerlayout.widget.DrawerLayout"
SLIDINGDRAWER -> "android.widget.SlidingDrawer"
ICONMENU -> "com.android.internal.view.menu.IconMenuView"
VIEWGROUP -> "android.view.ViewGroup"
WEBVIEW -> "android.webkit.WebView"
NONE,
LINK,
SUMMARY,
HEADER,
ALERT,
COMBOBOX,
MENU,
MENUBAR,
MENUITEM,
PROGRESSBAR,
RADIOGROUP,
SCROLLBAR,
TAB,
TABLIST,
TIMER,
TOOLBAR -> "android.view.View"
}
}
@JvmStatic
public fun fromValue(value: String?): AccessibilityRole {
if (value == null) {
return NONE
}
for (role in entries) {
if (role.name.equals(value, ignoreCase = true)) {
return role
}
}
throw IllegalArgumentException("Invalid accessibility role value: $value")
}
@JvmStatic
public fun fromRole(role: Role): AccessibilityRole? {
return when (role) {
Role.ALERT -> ALERT
Role.BUTTON -> BUTTON
Role.CHECKBOX -> CHECKBOX
Role.COMBOBOX -> COMBOBOX
Role.GRID -> GRID
Role.HEADING -> HEADER
Role.IMG -> IMAGE
Role.LINK -> LINK
Role.LIST -> LIST
Role.MENU -> MENU
Role.MENUBAR -> MENUBAR
Role.MENUITEM -> MENUITEM
Role.NONE -> NONE
Role.PROGRESSBAR -> PROGRESSBAR
Role.RADIO -> RADIO
Role.RADIOGROUP -> RADIOGROUP
Role.SCROLLBAR -> SCROLLBAR
Role.SEARCHBOX -> SEARCH
Role.SLIDER -> ADJUSTABLE
Role.SPINBUTTON -> SPINBUTTON
Role.SUMMARY -> SUMMARY
Role.SWITCH -> SWITCH
Role.TAB -> TAB
Role.TABLIST -> TABLIST
Role.TIMER -> TIMER
Role.TOOLBAR -> TOOLBAR
else -> // No mapping from ARIA role to AccessibilityRole
null
}
}
@JvmStatic
public fun fromViewTag(view: View): AccessibilityRole? {
val role = view.getTag(R.id.role) as Role?
return if (role != null) {
fromRole(role)
} else {
view.getTag(R.id.accessibility_role) as AccessibilityRole?
}
}
}
}
public companion object {
public const val TOP_ACCESSIBILITY_ACTION_EVENT: String = "topAccessibilityAction"
private val actionIdMap =
mapOf<String, Int>(
"activate" to AccessibilityActionCompat.ACTION_CLICK.id,
"longpress" to AccessibilityActionCompat.ACTION_LONG_CLICK.id,
"increment" to AccessibilityActionCompat.ACTION_SCROLL_FORWARD.id,
"decrement" to AccessibilityActionCompat.ACTION_SCROLL_BACKWARD.id,
"expand" to AccessibilityActionCompat.ACTION_EXPAND.id,
"collapse" to AccessibilityActionCompat.ACTION_COLLAPSE.id,
)
private const val TAG = "ReactAccessibilityDelegate"
private var customActionCounter = 0x3f000000
private val customActionIdMap: MutableMap<String?, Int> = HashMap()
private const val TIMEOUT_SEND_ACCESSIBILITY_EVENT = 200
private const val SEND_EVENT = 1
private const val delimiter = ", "
private const val delimiterLength = delimiter.length
// State constants for states which have analogs in AccessibilityNodeInfo
private const val STATE_DISABLED = "disabled"
private const val STATE_SELECTED = "selected"
private const val STATE_CHECKED = "checked"
@JvmStatic
public fun setDelegate(
view: View,
originalFocus: Boolean,
originalImportantForAccessibility: Int
) {
// if a view already has an accessibility delegate, replacing it could cause
// problems, so leave it alone.
if (!ViewCompat.hasAccessibilityDelegate(view) &&
(view.getTag(R.id.accessibility_role) != null ||
view.getTag(R.id.accessibility_state) != null ||
view.getTag(R.id.accessibility_actions) != null ||
view.getTag(R.id.react_test_id) != null ||
view.getTag(R.id.accessibility_collection_item) != null ||
view.getTag(R.id.accessibility_links) != null ||
view.getTag(R.id.role) != null)) {
ViewCompat.setAccessibilityDelegate(
view,
ReactAccessibilityDelegate(view, originalFocus, originalImportantForAccessibility))
}
}
// Explicitly re-set the delegate, even if one has already been set.
@JvmStatic
public fun resetDelegate(
view: View,
originalFocus: Boolean,
originalImportantForAccessibility: Int
) {
ViewCompat.setAccessibilityDelegate(
view, ReactAccessibilityDelegate(view, originalFocus, originalImportantForAccessibility))
}
private fun setState(
info: AccessibilityNodeInfoCompat,
accessibilityState: ReadableMap,
) {
val i = accessibilityState.keySetIterator()
while (i.hasNextKey()) {
val state = i.nextKey()
val value = accessibilityState.getDynamic(state)
if (state == STATE_SELECTED && value.type == ReadableType.Boolean) {
info.isSelected = value.asBoolean()
} else if (state == STATE_DISABLED && value.type == ReadableType.Boolean) {
info.isEnabled = !value.asBoolean()
} else if (state == STATE_CHECKED && value.type == ReadableType.Boolean) {
val boolValue = value.asBoolean()
info.isCheckable = true
info.isChecked = boolValue
}
}
}
// TODO: Eventually support for other languages on talkback
@JvmStatic
public fun setRole(
nodeInfo: AccessibilityNodeInfoCompat,
role: AccessibilityRole?,
context: Context
) {
val resolvedRole = role ?: AccessibilityRole.NONE
nodeInfo.className = AccessibilityRole.getValue(resolvedRole)
when (resolvedRole) {
AccessibilityRole.LINK -> {
nodeInfo.roleDescription = context.getString(R.string.link_description)
}
AccessibilityRole.IMAGE -> {
nodeInfo.roleDescription = context.getString(R.string.image_description)
}
AccessibilityRole.IMAGEBUTTON -> {
nodeInfo.roleDescription = context.getString(R.string.imagebutton_description)
nodeInfo.isClickable = true
}
AccessibilityRole.BUTTON -> {
nodeInfo.isClickable = true
}
AccessibilityRole.TOGGLEBUTTON -> {
nodeInfo.isClickable = true
nodeInfo.isCheckable = true
}
AccessibilityRole.SUMMARY -> {
nodeInfo.roleDescription = context.getString(R.string.summary_description)
}
AccessibilityRole.HEADER -> {
nodeInfo.isHeading = true
}
AccessibilityRole.ALERT -> {
nodeInfo.roleDescription = context.getString(R.string.alert_description)
}
AccessibilityRole.COMBOBOX -> {
nodeInfo.roleDescription = context.getString(R.string.combobox_description)
}
AccessibilityRole.MENU -> {
nodeInfo.roleDescription = context.getString(R.string.menu_description)
}
AccessibilityRole.MENUBAR -> {
nodeInfo.roleDescription = context.getString(R.string.menubar_description)
}
AccessibilityRole.MENUITEM -> {
nodeInfo.roleDescription = context.getString(R.string.menuitem_description)
}
AccessibilityRole.PROGRESSBAR -> {
nodeInfo.roleDescription = context.getString(R.string.progressbar_description)
}
AccessibilityRole.RADIOGROUP -> {
nodeInfo.roleDescription = context.getString(R.string.radiogroup_description)
}
AccessibilityRole.SCROLLBAR -> {
nodeInfo.roleDescription = context.getString(R.string.scrollbar_description)
}
AccessibilityRole.SPINBUTTON -> {
nodeInfo.roleDescription = context.getString(R.string.spinbutton_description)
}
AccessibilityRole.TAB -> {
nodeInfo.roleDescription = context.getString(R.string.rn_tab_description)
}
AccessibilityRole.TABLIST -> {
nodeInfo.roleDescription = context.getString(R.string.tablist_description)
}
AccessibilityRole.TIMER -> {
nodeInfo.roleDescription = context.getString(R.string.timer_description)
}
AccessibilityRole.TOOLBAR -> {
nodeInfo.roleDescription = context.getString(R.string.toolbar_description)
}
else -> {
// TODO: Add support for other roles
}
}
}
/**
* Determines if the supplied [View] and [AccessibilityNodeInfoCompat] has any children which
* are not independently accessibility focusable and also have a spoken description.
*
* NOTE: Accessibility services will include these children's descriptions in the closest
* focusable ancestor.
*
* @param view The [View] to evaluate
* @param node The [AccessibilityNodeInfoCompat] to evaluate
* @return `true` if it has any non-actionable speaking descendants within its subtree
*/
@JvmStatic
public fun hasNonActionableSpeakingDescendants(
node: AccessibilityNodeInfoCompat?,
view: View?
): Boolean {
if (node == null || view == null || (view !is ViewGroup)) {
return false
}
val viewGroup = view
var i = 0
val count = viewGroup.childCount
while (i < count) {
val childView = viewGroup.getChildAt(i)
if (childView == null) {
i++
continue
}
val childNode = AccessibilityNodeInfoCompat.obtain()
@Suppress("DEPRECATION") // TODO: Replace with direct invocation on view
ViewCompat.onInitializeAccessibilityNodeInfo(childView, childNode)
if (!childNode.isVisibleToUser) {
i++
continue
}
if (isAccessibilityFocusable(childNode, childView)) {
i++
continue
}
if (isSpeakingNode(childNode, childView)) {
return true
}
i++
}
return false
}
/**
* Returns whether the node has valid RangeInfo.
*
* @param node The node to check.
* @return Whether the node has valid RangeInfo.
*/
@JvmStatic
public fun hasValidRangeInfo(node: AccessibilityNodeInfoCompat?): Boolean {
if (node == null) {
return false
}
val rangeInfo = node.rangeInfo ?: return false
val maxProgress = rangeInfo.max
val minProgress = rangeInfo.min
val currentProgress = rangeInfo.current
val diffProgress = maxProgress - minProgress
return (diffProgress > 0.0f) &&
(currentProgress >= minProgress) &&
(currentProgress <= maxProgress)
}
/**
* Returns whether the specified node has state description.
*
* @param node The node to check.
* @return `true` if the node has state description.
*/
private fun hasStateDescription(node: AccessibilityNodeInfoCompat?): Boolean {
return node != null &&
(!node.stateDescription.isNullOrEmpty() || node.isCheckable || hasValidRangeInfo(node))
}
/**
* Returns whether the supplied [View] and [AccessibilityNodeInfoCompat] would produce spoken
* feedback if it were accessibility focused. NOTE: not all speaking nodes are focusable.
*
* @param view The [View] to evaluate
* @param node The [AccessibilityNodeInfoCompat] to evaluate
* @return `true` if it meets the criterion for producing spoken feedback
*/
@Suppress("DEPRECATION") // TODO: Replace ViewCompat with direct invocation on view
@JvmStatic
public fun isSpeakingNode(node: AccessibilityNodeInfoCompat?, view: View?): Boolean {
if (node == null || view == null) {
return false
}
val important = ViewCompat.getImportantForAccessibility(view)
if (important == ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS ||
(important == ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO && node.childCount <= 0)) {
return false
}
return hasText(node) ||
hasStateDescription(node) ||
node.isCheckable ||
hasNonActionableSpeakingDescendants(node, view)
}
@JvmStatic
public fun hasText(node: AccessibilityNodeInfoCompat?): Boolean {
return node != null &&
node.collectionInfo == null &&
(!node.text.isNullOrEmpty() ||
!node.contentDescription.isNullOrEmpty() ||
!node.hintText.isNullOrEmpty())
}
/**
* Determines if the provided [View] and [AccessibilityNodeInfoCompat] meet the criteria for
* gaining accessibility focus.
*
* Note: this is evaluating general focusability by accessibility services, and does not mean
* this view will be guaranteed to be focused by specific services such as Talkback. For
* Talkback focusability, see [isTalkbackFocusable(View)]
*
* @param view The [View] to evaluate
* @param node The [AccessibilityNodeInfoCompat] to evaluate
* @return `true` if it is possible to gain accessibility focus
*/
@JvmStatic
public fun isAccessibilityFocusable(node: AccessibilityNodeInfoCompat?, view: View?): Boolean {
if (node == null || view == null) {
return false
}
// Never focus invisible nodes.
if (!node.isVisibleToUser) {
return false
}
// Always focus "actionable" nodes.
return node.isScreenReaderFocusable || isActionableForAccessibility(node)
}
/**
* Returns whether a node is actionable. That is, the node supports one of
* [AccessibilityNodeInfoCompat#isClickable()], [AccessibilityNodeInfoCompat#isFocusable()], or
* [AccessibilityNodeInfoCompat#isLongClickable()].
*
* @param node The [AccessibilityNodeInfoCompat] to evaluate
* @return `true` if node is actionable.
*/
@JvmStatic
public fun isActionableForAccessibility(node: AccessibilityNodeInfoCompat?): Boolean {
if (node == null) {
return false
}
if (node.isClickable || node.isLongClickable || node.isFocusable) {
return true
}
return node.actionList.any { action ->
action == AccessibilityActionCompat.ACTION_CLICK ||
action == AccessibilityActionCompat.ACTION_LONG_CLICK ||
action == AccessibilityActionCompat.ACTION_FOCUS
}
}
/**
* Returns a cached instance if such is available otherwise a new one.
*
* @param view The [View] to derive the AccessibilityNodeInfo properties from.
* @return [FlipperObject] containing the properties.
*/
@JvmStatic
public fun createNodeInfoFromView(view: View?): AccessibilityNodeInfoCompat? {
if (view == null) {
return null
}
val nodeInfo = AccessibilityNodeInfoCompat.obtain()
try {
@Suppress("DEPRECATION") // TODO: Replace with direct invocation on view
ViewCompat.onInitializeAccessibilityNodeInfo(view, nodeInfo)
} catch (e: NullPointerException) {
// For some unknown reason, Android seems to occasionally throw a NPE from
// onInitializeAccessibilityNodeInfo.
return null
}
return nodeInfo
}
/**
* Creates the text that Google's TalkBack screen reader will read aloud for a given [View].
* This may be any combination of the [View]'s `text`, `contentDescription`, and the `text` and
* `contentDescription` of any ancestor [View].
*
* This description is generally ported over from Google's TalkBack screen reader, and this
* should be kept up to date with their implementation (as much as necessary). Details can be
* seen in their source code here:
*
* https://github.com/google/talkback/compositor/src/main/res/raw/compositor.json - search for
* "get_description_for_tree", "append_description_for_tree", "description_for_tree_nodes"
*
* @param view The [View] to evaluate.
* @param info The default [AccessibilityNodeInfoCompat].
* @return `String` representing what talkback will say when a [View] is focused.
*/
@JvmStatic
public fun getTalkbackDescription(
view: View,
info: AccessibilityNodeInfoCompat?
): CharSequence? {
val node =
if (info == null) createNodeInfoFromView(view)
else AccessibilityNodeInfoCompat.obtain(info)
if (node == null) {
return null
}
val contentDescription = node.contentDescription
val nodeText = node.text
val hasNodeText = !nodeText.isNullOrEmpty()
val isEditText = view is EditText
val talkbackSegments = StringBuilder()
// EditText's prioritize their own text content over a contentDescription so skip this
if (!contentDescription.isNullOrEmpty() && (!isEditText || !hasNodeText)) {
// next add content description
talkbackSegments.append(contentDescription)
return talkbackSegments
}
// TextView
if (hasNodeText) {
talkbackSegments.append(nodeText)
return talkbackSegments
}
// If there are child views and no contentDescription the text of all non-focusable
// children,
// comma separated, becomes the description.
if (view is ViewGroup) {
val concatChildDescription = StringBuilder()
val viewGroup = view
var i = 0
val count = viewGroup.childCount
while (i < count) {
val child = viewGroup.getChildAt(i)
val childNodeInfo = AccessibilityNodeInfoCompat.obtain()
@Suppress("DEPRECATION") // TODO: Replace with direct invocation on view
ViewCompat.onInitializeAccessibilityNodeInfo(child, childNodeInfo)
if (isSpeakingNode(childNodeInfo, child) &&
!isAccessibilityFocusable(childNodeInfo, child)) {
val childNodeDescription = getTalkbackDescription(child, null)
if (!childNodeDescription.isNullOrEmpty()) {
concatChildDescription.append(childNodeDescription.toString() + delimiter)
}
}
i++
}
return removeFinalDelimiter(concatChildDescription)
}
return null
}
private fun removeFinalDelimiter(builder: StringBuilder): String {
val end = builder.length
if (end > 0) {
builder.delete(end - delimiterLength, end)
}
return builder.toString()
}
}
}
@@ -46,6 +46,8 @@ import com.facebook.yoga.YogaWrap;
* NativeViewHierarchyOptimizer} for more information.
*/
@LegacyArchitecture
@Deprecated(
since = "This class is part of Legacy Architecture and will be removed in a future release")
public interface ReactShadowNode<T extends ReactShadowNode> {
/**

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