Compare commits

...
Author SHA1 Message Date
CodemodService BotandFacebook GitHub Bot fcc1e19198 Fix CQS signal modernize-concat-nested-namespaces in xplat/js/react-native-github/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon
Reviewed By: dtolnay

Differential Revision: D78146649
2025-07-11 09:19:23 -07:00
Riccardo CipolleschiandFacebook GitHub Bot e79808fa4b Update caching keys for prebuild-core (#52565)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/52565

When we implemented caching in prebuilds for RN core for iOS, we were naïve in choosing the cache key. The current cache key does not consider the source code that is built and this can be problematic.
Imagine a contributor that changes a file in a React folder in their PR, but CI reuses a binary created from `main` and so everything will work well in CI even if the change contains an error.

This change globs over the header and implementation files in the React, ReactCommon and Libraries folder to ensure that we rebuild the code when iOS code changes.

## Changelog:
[Internal] -

Reviewed By: cortinico

Differential Revision: D78161427

fbshipit-source-id: e612b76232308835eb88c3776122bebd1316f751
2025-07-11 09:14:43 -07:00
Rubén NorteandFacebook GitHub Bot 9747c955ac Migrate network profiling to console.timeStamp (#52560)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/52560

Changelog: [internal]

This migrates the profiling logic for `XMLHttpRequest` from `performance.measure` to `console.timeStamp` with built-in support for tracks.

Reviewed By: hoxyq

Differential Revision: D78157407

fbshipit-source-id: 0ef060557a00e7973ef7f0478b26b81471d38226
2025-07-11 08:41:01 -07:00
Rubén NorteandFacebook GitHub Bot 6f6945e64f Propagate console.timeStamp entries to Perfetto (#52542)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/52542

Changelog: [internal]

This adds support to propagate performance entries logged to `console.timeStamp` to Perfetto, if enabled. It also modifies the Perfetto integration to support track groups, in addition to track names.

Reviewed By: hoxyq

Differential Revision: D78092596

fbshipit-source-id: 76b0fe2738d856fd75ee941de223d6a6a73d8e1c
2025-07-11 08:41:01 -07:00
Nicola CortiandFacebook GitHub Bot 0021dafc51 Remove deprecated constructors for TextInput *Event classes (#52535)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/52535

Those constructors are no longer necessary. They're deprecated + the class is internal so they're not breaking changes.
I'm just cleaning them up as they're not needed anymore.

Changelog:
[Internal] [Changed] - Remove deprecated constructors for TextInput *Event classes

Reviewed By: javache

Differential Revision: D78095748

fbshipit-source-id: 2dc6c750f8470a88918d8a69b68364f38251d79e
2025-07-11 08:15:42 -07:00
Riccardo CipolleschiandFacebook GitHub Bot e69777d258 Connect prebuilds with CI (#52562)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/52562

This change use the prebuilds we build in CI i other iOS jobs to speed-up the iOS CI

## Changelog:
[Internal] -

Reviewed By: cortinico

Differential Revision: D78159367

fbshipit-source-id: 64486c99fdbc54487dbcff786209cacac304b9b7
2025-07-11 07:15:35 -07:00
Riccardo CipolleschiandFacebook GitHub Bot dc5110a8f2 Unify test_ios_rntester_dynamic_frameworks with test_ios_rntester (#52563)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/52563

The test_ios_rntester_dynamic_frameworks is identical to the test_ios_rntester but for the framework parameter.

This change unifies the two, using a matrix to test all the configurations:
- Debug / Static Libraries
- Release / Static Libraries
- Debug / Dynamic Frameworks
- Release / Dynamic Frameworks

## Changelog:
[Internal] -

Reviewed By: cortinico

Differential Revision: D78159366

fbshipit-source-id: b321f295477fe3ae6e43c7518d47afb0714bddb8
2025-07-11 07:15:35 -07:00
Riccardo CipolleschiandFacebook GitHub Bot 3de1dc0fd1 Fix RCTPushNotification podspec to work with prebuilds (#52531)
Summary:
This change tries to use the prebuilds we build in CI i other iOS jobs to speed-up the iOS CI

bypass-github-export-checks

## Changelog:
[Internal] -

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

Test Plan:
Build rntester using prebuilds:

```
# after downloading the prebuilds from CI and unzipping them
export HERMES_ENGINE_TARBALL_PATH=~/Downloads/hermes-ios-Debug.tar.gz
export RCT_USE_LOCAL_RN_DEP=~/Downloads/reactnative-dependencies-debug.tar.gz
export RCT_TESTONLY_RNCORE_TARBALL_PATH=~/Downloads/React.xcframework.tar.gz

USE_FRAMEWORKS=dynamic bundle exec pod install
open RNTesterPods.xcworkspace
```
And then build from Xcode.

Reviewed By: rshest

Differential Revision: D78158734

Pulled By: cipolleschi

fbshipit-source-id: 43cbb66bd44fa621292b69de0dadde5ed20c4574
2025-07-11 07:15:35 -07:00
Christoph PurrerandFacebook GitHub Bot 88cb7832ea Remove unused Color/Transform #includes and use enum class for TransformOperationType (#52549)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/52549

Changelog: [Internal]

- The #includes are not used
- `enum class` is C++, (enum is C)

Reviewed By: rshest

Differential Revision: D78135339

fbshipit-source-id: 1a35301ea063ce17c195be7dc373132d342f111a
2025-07-11 06:51:49 -07:00
Zeya PengandFacebook GitHub Bot aa2a5a682f Animated.sequence (#52547)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/52547

## Changelog:

[Internal] [Added] - add fantom test for Animated.sequence

Reviewed By: christophpurrer

Differential Revision: D78107756

fbshipit-source-id: c3a7bc2d487cc0ae7316a26dc10b01dcf54dbd37
2025-07-11 06:40:03 -07:00
Zeya PengandFacebook GitHub Bot a0543b773c AnimatedValue.interpolate (#52546)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/52546

## Changelog:

[Internal] [Added] - add fantom test for AnimatedValue.interpolate

Reviewed By: christophpurrer

Differential Revision: D78032554

fbshipit-source-id: 0100a510cb0ad5c8e1886c309fab91ee9e017769
2025-07-11 06:40:03 -07:00
Rubén NorteandFacebook GitHub Bot f5abce0932 Micro-optimize performance methods (#52555)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/52555

Changelog: [internal]

Applied several micro-optimizations to methods in the `performance` object:
- Cached property access
- Avoided unnecessary function calls
- Avoided unnecessary object allocations
- Use strict comparisons with `undefined` instead of loose comparisons with `null` whenever possible.

This yields wins from 5 to 15% depending on the method and args.

## Before

| (index) | Task name                                                 | Latency average (ns) | Latency median (ns) | Throughput average (ops/s) | Throughput median (ops/s) | Samples |
| ------- | --------------------------------------------------------- | -------------------- | ------------------- | -------------------------- | ------------------------- | ------- |
| 0       | 'mark (default)'                                          | '1728.19 ± 0.81%'    | '1682.00'           | '592249 ± 0.01%'           | '594530'                  | 578640  |
| 1       | 'mark (with custom startTime)'                            | '2008.33 ± 1.32%'    | '1933.00'           | '514326 ± 0.01%'           | '517331'                  | 497927  |
| 2       | 'measure (default)'                                       | '2568.90 ± 1.48%'    | '2484.00'           | '400362 ± 0.02%'           | '402576'                  | 389272  |
| 3       | 'measure (with start and end timestamps)'                 | '2806.21 ± 0.69%'    | '2744.00'           | '362439 ± 0.02%'           | '364431'                  | 356353  |
| 4       | 'measure (with mark names)'                               | '2860.82 ± 0.23%'    | '2824.00'           | '352145 ± 0.02%'           | '354108'                  | 349551  |
| 5       | 'clearMarks'                                              | '763.05 ± 0.03%'     | '751.00'            | '1320377 ± 0.01%'          | '1331558'                 | 1310524 |
| 6       | 'clearMeasures'                                           | '788.10 ± 0.05%'     | '781.00'            | '1281839 ± 0.01%'          | '1280410'                 | 1268875 |
| 7       | 'mark + clearMarks'                                       | '2129.03 ± 1.04%'    | '2053.00'           | '484778 ± 0.01%'           | '487092'                  | 469698  |
| 8       | 'measure + clearMeasures (with start and end timestamps)' | '3176.38 ± 0.67%'    | '3105.00'           | '320111 ± 0.02%'           | '322061'                  | 314825  |
| 9       | 'measure + clearMeasures (with mark names)'               | '3229.33 ± 0.60%'    | '3145.00'           | '316463 ± 0.02%'           | '317965'                  | 309662  |

## After

| (index) | Task name                                                 | Latency average (ns) | Latency median (ns) | Throughput average (ops/s) | Throughput median (ops/s) | Samples |
| ------- | --------------------------------------------------------- | -------------------- | ------------------- | -------------------------- | ------------------------- | ------- |
| 0       | 'mark (default)'                                          | '1598.54 ± 0.93%'    | '1553.00'           | '639076 ± 0.01%'           | '643915'                  | 625572  |
| 1       | 'mark (with custom startTime)'                            | '1772.07 ± 1.24%'    | '1713.00'           | '579523 ± 0.01%'           | '583771'                  | 564314  |
| 2       | 'measure (default)'                                       | '2349.32 ± 0.81%'    | '2284.00'           | '434149 ± 0.01%'           | '437828'                  | 425656  |
| 3       | 'measure (with start and end timestamps)'                 | '2609.11 ± 1.06%'    | '2534.00'           | '391950 ± 0.02%'           | '394633'                  | 383273  |
| 4       | 'measure (with mark names)'                               | '2656.46 ± 0.42%'    | '2614.00'           | '380128 ± 0.01%'           | '382555'                  | 376442  |
| 5       | 'clearMarks'                                              | '666.38 ± 0.03%'     | '661.00'            | '1511649 ± 0.01%'          | '1512859'                 | 1500641 |
| 6       | 'clearMeasures'                                           | '718.62 ± 0.03%'     | '711.00'            | '1401526 ± 0.01%'          | '1406470'                 | 1391563 |
| 7       | 'mark + clearMarks'                                       | '2027.47 ± 1.29%'    | '1953.00'           | '509105 ± 0.01%'           | '512033'                  | 493227  |
| 8       | 'measure + clearMeasures (with start and end timestamps)' | '3030.83 ± 0.98%'    | '2915.00'           | '340624 ± 0.02%'           | '343053'                  | 329943  |
| 9       | 'measure + clearMeasures (with mark names)'               | '2915.76 ± 0.59%'    | '2844.00'           | '349120 ± 0.02%'           | '351617'                  | 342964  |

Reviewed By: hoxyq

Differential Revision: D78013565

fbshipit-source-id: ddd02d887b228debd58805406c1395b9179dd804
2025-07-11 05:37:31 -07:00
Rubén NorteandFacebook GitHub Bot 38cf247c63 Add more benchmarks for performance.measure (#52556)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/52556

Changelog: [internal]

This adds a new benchmark for `performance.measure` to measure the performance of calling it without arguments.

Reviewed By: hoxyq

Differential Revision: D78013563

fbshipit-source-id: 84e2151d9d91cfc2e85d310f42010483e7304648
2025-07-11 05:37:31 -07:00
Rubén NorteandFacebook GitHub Bot 1fc168f005 Handle nullability of detail correctly in performance.mark and performance.measure (#52557)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/52557

Changelog: [internal]

`PerformanceEntry.detail` should be `null` if not defined, not undefined as it is currently. This fixes that.

Reviewed By: hoxyq

Differential Revision: D78013568

fbshipit-source-id: b22dfdd8d582594fc1e5199264e8af92c26bb0ea
2025-07-11 05:37:31 -07:00
Rubén NorteandFacebook GitHub Bot 5e0eb0a17c Small refactor of performance API (#52558)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/52558

Changelog: [internal]

Small refactors for `$ReadOnly`, move `getCurrentTimeStamp` to utils so it can be reused, etc.

Reviewed By: hoxyq

Differential Revision: D78013570

fbshipit-source-id: f73d119f22dd4dc9aaa5efef76a1156821ecd8de
2025-07-11 05:37:31 -07:00
Rubén NorteandFacebook GitHub Bot acd07c7e1c Handle casting to string in performance.mark and performance.measure correctly (#52559)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/52559

Changelog: [internal]

Making `performance.mark` and `performance.measure` slightly more spec-compliant.

Reviewed By: hoxyq

Differential Revision: D78013571

fbshipit-source-id: 4881b674f7cded5045b9f464ca7442a186c39048
2025-07-11 05:37:31 -07:00
Harini MalothuandFacebook GitHub Bot ff38d59cff # Fixed Type Conversion Error in DynamicEventPayload (#52525)
Summary:
Resolves https://github.com/microsoft/react-native-windows/issues/14797
We were facing a type conversion error in the DynamicEventPayload::extractValue() method. The function signature declares a return type of std::optional<double>, but when handling INT64 values, but when handling `INT64` values, the code was directly returning `dynamic.asInt()` without proper type conversion
We faced the issue while integrating https://github.com/microsoft/react-native-windows/pull/14791
## Changelog:
[General][Fixed]

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

Test Plan:
The fix involved wrapping the dynamic.asInt() call with static_cast<double>(), creating the corrected line: return static_cast<double>(dynamic.asInt())

Tested E2E in RNW

Reviewed By: andrewdacenko

Differential Revision: D78083842

Pulled By: rshest

fbshipit-source-id: 8dbedd67fa7c21e89b863d8b1bc7b9e0d7978b9f
2025-07-11 03:13:30 -07:00
Riccardo CipolleschiandFacebook GitHub Bot 7bbb13c9be Fix ENTERPRISE_REPOSITORY usage (#52553)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/52553

This change fixes the usage of `ENTERPRISE_REPOSITORY` in Ruby

## Changelog
[Internal] -

Reviewed By: cortinico

Differential Revision: D78152641

fbshipit-source-id: e4ace014f1b7cbeb1ec5a0dea955d1fc2bae5b67
2025-07-11 03:01:30 -07:00
Jakub PiaseckiandFacebook GitHub Bot d4b36b0300 Fix display: contents nodes not being cloned with the wrong owner (#52530)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/52530

This PR fixes two issues with `display: contents` implementation:
1. When a node with `display: contents` set is a leaf, it won't be cloned after the initial tree is built. The added test case covers this scenario.
2. It was possible for the subtree of `display: contents` nodes not to be cloned during layout. I don't have a minimal reproduction for this one, unfortunately. It was discovered in the Expensify app: https://github.com/Expensify/App/issues/65268, along with a consistent reproduction. In that specific case, it seems to be heavily tied to `react-native-onyx`, which is a state management library.

Changelog: [GENERAL][FIXED] - Fixed nodes with `display: contents` set being cloned with the wrong owner

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

Reviewed By: adityasharat, NickGerleman

Differential Revision: D78084270

Pulled By: j-piasecki

fbshipit-source-id: eb81f6d7dcd1665974d07261ba693e2abea239bb
2025-07-11 02:16:35 -07:00
Vitali ZaidmanandFacebook GitHub Bot 84a2765c2a renamed release testing scripts (#52541)
Summary:
Use a more suitable name for the [scripts used in the release process](https://github.com/reactwg/react-native-releases/blob/main/docs/guide-release-testing.md) to generate a testing project to test a new React Native release against.
```diff
- test-e2e-local
+ test-release-local
```
## Changelog:
[INTERNAL]

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

Test Plan:
`yarn test-release-local-clean` works the same way:
<img width="1177" height="161" alt="Screenshot 2025-07-10 at 17 54 50" src="https://github.com/user-attachments/assets/5efe30c6-a738-476e-a670-696959e9a0fc" />

`yarn test-release-local` works the same way:
<img width="1077" height="395" alt="Screenshot 2025-07-10 at 17 59 29" src="https://github.com/user-attachments/assets/fe6c6443-9316-4ed0-b6dc-51de5ffb109c" />

Reviewed By: cipolleschi

Differential Revision: D78150648

Pulled By: vzaidman

fbshipit-source-id: 471715da271d03bc2a35afbda02074bf71f62734
2025-07-11 01:57:14 -07:00
Nick LefeverandFacebook GitHub Bot 6b8bc5a1d0 Move toDynamic conversion for FilterFunction (#52537)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/52537

See title

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D78088447

fbshipit-source-id: 3f3a1e82e527cfe83de7a798b8b9ea2996dc8de1
2025-07-10 12:35:18 -07:00
Nick LefeverandFacebook GitHub Bot 0144798e25 Move toDynamic conversion for BoxShadow (#52536)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/52536

See title

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D78005880

fbshipit-source-id: 5a4b7ff3c4d9c6ece17759926ee80aec80d3cde0
2025-07-10 12:35:18 -07:00
generatedunixname89002005287564andFacebook GitHub Bot 263ccad3c5 Fix CQS signal modernize-use-using in xplat/js/react-native-github/packages/react-native/React/CoreModules [B] (#52539)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/52539

Reviewed By: dtolnay

Differential Revision: D78062538

fbshipit-source-id: 610505b5bfd78798b09970194f3b95aaefb08920
2025-07-10 12:16:40 -07:00
Devan BuggayandFacebook GitHub Bot c2a3e4420e HWInput: Add Channel Up/Down Support (#52540)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/52540

Adds Channel Up/Down events to HWInput.

Changelog:
[Android][Added] - Channel up/down hardware events.

Reviewed By: Abbondanzo

Differential Revision: D78099245

fbshipit-source-id: 133d5c835f3862feba641354cb1164eefeafed9f
2025-07-10 12:04:00 -07:00
Rob HoganandFacebook GitHub Bot 5d4c22b4a7 Update @typescript-eslint (#52532)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/52532

Since we updated TypeScript in https://github.com/facebook/react-native/pull/51831, ESLint has printed a warning that `typescript/eslint` doesn't support our TS version.

This updates it to fix the warning.

Changelog: [Internal]

Reviewed By: vzaidman

Differential Revision: D77833826

fbshipit-source-id: 29a5179c4f223a8cc0ab2c8071f0a5efa09e5edc
2025-07-10 10:10:09 -07:00
Nicola CortiandFacebook GitHub Bot b0606ba041 Correctly mark as deprecated the ReactActivityDelegate.getReactInstanceManager (#52533)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/52533

This method is deprecated in the JavaDoc but not correctly annotated as Deprecated, let's fix it.

Changelog:
[Internal] [Changed] -

Reviewed By: cipolleschi

Differential Revision: D78092468

fbshipit-source-id: 31e4cb958a51b20f5105a4bec3366d67402e5419
2025-07-10 10:00:32 -07:00
46 changed files with 708 additions and 353 deletions
@@ -48,6 +48,14 @@ runs:
- name: Print third-party folder
shell: bash
run: ls -lR /tmp/third-party
- name: Download React Native Prebuilds
uses: actions/download-artifact@v4
with:
name: ReactCore${{ inputs.flavor }}.xcframework.tar.gz
path: /tmp/ReactCore
- name: Print ReactCore folder
shell: bash
run: ls -lR /tmp/ReactCore
- name: Install iOS dependencies - Configuration ${{ inputs.flavor }};
shell: bash
run: |
@@ -73,6 +81,7 @@ runs:
TARBALL_FILENAME=$(node ../../packages/react-native/scripts/hermes/get-tarball-name.js --buildType "$BUILD_TYPE")
export HERMES_ENGINE_TARBALL_PATH="$HERMES_WS_DIR/hermes-runtime-darwin/$TARBALL_FILENAME"
export RCT_USE_LOCAL_RN_DEP="/tmp/third-party/ReactNativeDependencies${{ inputs.flavor }}.xcframework.tar.gz"
export RCT_TESTONLY_RNCORE_TARBALL_PATH="/tmp/ReactCore/ReactCore${{ inputs.flavor }}.xcframework.tar.gz"
yarn bootstrap ios "${args[@]}" | cat
+10 -1
View File
@@ -94,6 +94,14 @@ runs:
- name: Print third-party folder
shell: bash
run: ls -lR /tmp/third-party
- name: Download React Native Prebuilds
uses: actions/download-artifact@v4
with:
name: ReactCore${{ inputs.flavor }}.xcframework.tar.gz
path: /tmp/ReactCore
- name: Print ReactCore folder
shell: bash
run: ls -lR /tmp/ReactCore
- name: Setup xcode build cache
uses: ./.github/actions/setup-xcode-build-cache
with:
@@ -105,12 +113,13 @@ runs:
shell: bash
run: |
export HERMES_ENGINE_TARBALL_PATH=$HERMES_ENGINE_TARBALL_PATH
export RCT_USE_LOCAL_RN_DEP="/tmp/third-party/ReactNativeDependencies${{ inputs.flavor }}.xcframework.tar.gz"
export RCT_TESTONLY_RNCORE_TARBALL_PATH="/tmp/ReactCore/ReactCore${{ inputs.flavor }}.xcframework.tar.gz"
if [[ ${{ inputs.use-frameworks }} == "DynamicFrameworks" ]]; then
export USE_FRAMEWORKS=dynamic
fi
export RCT_USE_LOCAL_RN_DEP="/tmp/third-party/ReactNativeDependencies${{ inputs.flavor }}.xcframework.tar.gz"
cd packages/rn-tester
bundle install
+4 -4
View File
@@ -23,7 +23,7 @@ jobs:
id: restore-ios-slice
uses: actions/cache/restore@v4
with:
key: v3-ios-core-${{ matrix.slice }}-${{ matrix.flavor }}-${{ hashFiles('packages/react-native/Package.swift') }}-${{ hashFiles('packages/react-native/scripts/ios-prebuild/setup.js') }}
key: v3-ios-core-${{ matrix.slice }}-${{ matrix.flavor }}-${{ hashFiles('packages/react-native/Package.swift', 'packages/react-native/scripts/ios-prebuild/setup.js', 'packages/react-native/React/**/*', 'packages/react-native/ReactCommon/**/*', 'packages/react-native/Libraries/**/*') }}
path: packages/react-native/
- name: Setup node.js
if: steps.restore-ios-slice.outputs.cache-hit != 'true'
@@ -117,7 +117,7 @@ jobs:
uses: actions/cache/save@v4
if: ${{ github.ref == 'refs/heads/main' }} # To avoid that the cache explode
with:
key: v3-ios-core-${{ matrix.slice }}-${{ matrix.flavor }}-${{ hashFiles('packages/react-native/Package.swift') }}-${{ hashFiles('packages/react-native/scripts/ios-prebuild/setup.js') }}
key: v3-ios-core-${{ matrix.slice }}-${{ matrix.flavor }}-${{ hashFiles('packages/react-native/Package.swift', 'packages/react-native/scripts/ios-prebuild/setup.js', 'packages/react-native/React/**/*', 'packages/react-native/ReactCommon/**/*', 'packages/react-native/Libraries/**/*') }}
path: |
packages/react-native/.build/output/spm/${{ matrix.flavor }}/Build/Products
packages/react-native/.build/headers
@@ -140,7 +140,7 @@ jobs:
uses: actions/cache/restore@v4
with:
path: packages/react-native/.build/output/xcframeworks
key: v2-ios-core-xcframework-${{ matrix.flavor }}-${{ hashFiles('packages/react-native/Package.swift') }}-${{ hashFiles('packages/react-native/scripts/ios-prebuild/setup.js') }}
key: v2-ios-core-xcframework-${{ matrix.flavor }}-${{ hashFiles('packages/react-native/Package.swift', 'packages/react-native/scripts/ios-prebuild/setup.js', 'packages/react-native/React/**/*', 'packages/react-native/ReactCommon/**/*', 'packages/react-native/Libraries/**/*') }}
- name: Setup node.js
if: steps.restore-ios-xcframework.outputs.cache-hit != 'true'
uses: ./.github/actions/setup-node
@@ -209,4 +209,4 @@ jobs:
path: |
packages/react-native/.build/output/xcframeworks/ReactCore${{matrix.flavor}}.xcframework.tar.gz
packages/react-native/.build/output/xcframeworks/ReactCore${{matrix.flavor}}.framework.dSYM.tar.gz
key: v2-ios-core-xcframework-${{ matrix.flavor }}-${{ hashFiles('packages/react-native/Package.swift') }}-${{ hashFiles('packages/react-native/scripts/ios-prebuild/setup.js') }}
key: v2-ios-core-xcframework-${{ matrix.flavor }}-${{ hashFiles('packages/react-native/Package.swift', 'packages/react-native/scripts/ios-prebuild/setup.js', 'packages/react-native/React/**/*', 'packages/react-native/ReactCommon/**/*', 'packages/react-native/Libraries/**/*') }}
+16 -26
View File
@@ -128,7 +128,7 @@ jobs:
test_ios_rntester_ruby_3_2_0:
runs-on: macos-14
needs:
[build_apple_slices_hermes, prepare_hermes_workspace, build_hermes_macos, prebuild_apple_dependencies]
[build_apple_slices_hermes, prepare_hermes_workspace, build_hermes_macos, prebuild_apple_dependencies, prebuild_react_native_core]
env:
HERMES_WS_DIR: /tmp/hermes
HERMES_TARBALL_ARTIFACTS_DIR: /tmp/hermes/hermes-runtime-darwin
@@ -141,31 +141,12 @@ jobs:
ruby-version: "3.2.0"
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
test_ios_rntester_dynamic_frameworks:
runs-on: macos-14
needs:
[build_apple_slices_hermes, prepare_hermes_workspace, build_hermes_macos, prebuild_apple_dependencies]
env:
HERMES_WS_DIR: /tmp/hermes
HERMES_TARBALL_ARTIFACTS_DIR: /tmp/hermes/hermes-runtime-darwin
continue-on-error: true
strategy:
fail-fast: false
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Run it
uses: ./.github/actions/test-ios-rntester
with:
use-frameworks: DynamicFrameworks
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
flavor: Debug
test_ios_rntester:
runs-on: macos-14-large
needs:
[build_apple_slices_hermes, prepare_hermes_workspace, build_hermes_macos, prebuild_apple_dependencies]
[build_apple_slices_hermes, prepare_hermes_workspace, build_hermes_macos, prebuild_apple_dependencies, prebuild_react_native_core]
env:
HERMES_WS_DIR: /tmp/hermes
HERMES_TARBALL_ARTIFACTS_DIR: /tmp/hermes/hermes-runtime-darwin
@@ -174,14 +155,14 @@ jobs:
fail-fast: false
matrix:
flavor: [Debug, Release]
frameworks: [StaticLibraries, DynamicFrameworks]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Run it
uses: ./.github/actions/test-ios-rntester
with:
run-unit-tests: "false"
use-frameworks: StaticLibraries
use-frameworks: ${{ matrix.frameworks }}
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
flavor: ${{ matrix.flavor }}
@@ -264,6 +245,14 @@ jobs:
- name: Print third-party folder
shell: bash
run: ls -lR /tmp/third-party
- name: Download React Native Prebuilds
uses: actions/download-artifact@v4
with:
name: ReactCore${{ matrix.flavor }}.xcframework.tar.gz
path: /tmp/ReactCore
- name: Print ReactCore folder
shell: bash
run: ls -lR /tmp/ReactCore
- name: Prepare artifacts
run: |
REACT_NATIVE_PKG=$(find /tmp/react-native-tmp -type f -name "*.tgz")
@@ -286,6 +275,7 @@ jobs:
NEW_ARCH_ENABLED=1
export RCT_USE_LOCAL_RN_DEP=/tmp/third-party/ReactNativeDependencies${{ matrix.flavor }}.xcframework.tar.gz
export RCT_TESTONLY_RNCORE_TARBALL_PATH="/tmp/ReactCore/ReactCore${{ matrix.flavor }}.xcframework.tar.gz"
HERMES_ENGINE_TARBALL_PATH=$HERMES_PATH RCT_NEW_ARCH_ENABLED=$NEW_ARCH_ENABLED bundle exec pod install
xcodebuild \
@@ -548,7 +538,7 @@ jobs:
test_ios_helloworld_with_ruby_3_2_0:
runs-on: macos-14
needs: [prepare_hermes_workspace, build_hermes_macos, prebuild_apple_dependencies] # prepare_hermes_workspace must be there because we need its reference to retrieve a couple of outputs
needs: [prepare_hermes_workspace, build_hermes_macos, prebuild_apple_dependencies, prebuild_react_native_core] # prepare_hermes_workspace must be there because we need its reference to retrieve a couple of outputs
env:
PROJECT_NAME: iOSTemplateProject
HERMES_WS_DIR: /tmp/hermes
@@ -565,7 +555,7 @@ jobs:
test_ios_helloworld:
runs-on: macos-14
needs: [prepare_hermes_workspace, build_hermes_macos, prebuild_apple_dependencies] # prepare_hermes_workspace must be there because we need its reference to retrieve a couple of outputs
needs: [prepare_hermes_workspace, build_hermes_macos, prebuild_apple_dependencies, prebuild_react_native_core] # prepare_hermes_workspace must be there because we need its reference to retrieve a couple of outputs
strategy:
matrix:
flavor: [Debug, Release]
+3 -3
View File
@@ -28,8 +28,8 @@
"set-version": "node ./scripts/releases/set-version.js",
"test-android": "./gradlew :packages:react-native:ReactAndroid:test",
"test-ci": "jest --maxWorkers=2 --ci --reporters=\"default\" --reporters=\"jest-junit\"",
"test-e2e-local-clean": "node ./scripts/release-testing/test-e2e-local-clean.js",
"test-e2e-local": "node ./scripts/release-testing/test-e2e-local.js",
"test-release-local-clean": "node ./scripts/release-testing/test-release-local-clean.js",
"test-release-local": "node ./scripts/release-testing/test-release-local.js",
"test-ios": "./scripts/objc-test.sh test",
"test-typescript": "tsc -p packages/react-native/types/tsconfig.json",
"test-generated-typescript": "tsc -p packages/react-native/types_generated/tsconfig.test.json",
@@ -58,7 +58,7 @@
"@react-native/metro-config": "0.81.0-main",
"@tsconfig/node22": "22.0.2",
"@types/react": "^19.1.0",
"@typescript-eslint/parser": "^7.1.1",
"@typescript-eslint/parser": "^8.36.0",
"ansi-styles": "^4.2.1",
"babel-plugin-minify-dead-code-elimination": "^0.5.2",
"babel-plugin-syntax-hermes-parser": "0.29.1",
@@ -23,8 +23,8 @@
"@babel/core": "^7.25.2",
"@babel/eslint-parser": "^7.25.1",
"@react-native/eslint-plugin": "0.81.0-main",
"@typescript-eslint/eslint-plugin": "^7.1.1",
"@typescript-eslint/parser": "^7.1.1",
"@typescript-eslint/eslint-plugin": "^8.36.0",
"@typescript-eslint/parser": "^8.36.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-ft-flow": "^2.0.1",
@@ -537,3 +537,160 @@ test('animate layout props', () => {
<rn-view height="100.000000" />,
);
});
test('AnimatedValue.interpolate', () => {
let _valueX;
let _interpolatedValueX;
const viewRef = createRef<HostInstance>();
function MyApp({outputRangeX}: $ReadOnly<{outputRangeX: number}>) {
const valueX = useAnimatedValue(0.5, {useNativeDriver: true});
_valueX = valueX;
const offset = outputRangeX - 1;
const interpolatedValueX = valueX.interpolate({
inputRange: [0, 1],
outputRange: [offset, 100],
});
_interpolatedValueX = interpolatedValueX;
return (
<Animated.View
ref={viewRef}
style={[
{
width: 100,
height: 100,
},
{transform: [{translateX: valueX}, {translateY: interpolatedValueX}]},
]}
/>
);
}
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<MyApp outputRangeX={1} />);
});
const viewElement = ensureInstance(viewRef.current, ReactNativeElement);
expect(_valueX?.__getValue()).toBe(0.5);
expect(_interpolatedValueX?.__getValue()).toBe(50);
expect(
JSON.stringify(
Fantom.unstable_getDirectManipulationProps(viewElement).transform,
),
).toBe('[{"translateX":0.5},{"translateY":50}]');
expect(viewElement.getBoundingClientRect().x).toBe(0.5);
expect(viewElement.getBoundingClientRect().y).toBe(50);
Fantom.runTask(() => {
root.render(<MyApp outputRangeX={51} />);
});
expect(_valueX?.__getValue()).toBe(0.5);
expect(_interpolatedValueX?.__getValue()).toBe(75);
expect(
JSON.stringify(
Fantom.unstable_getDirectManipulationProps(viewElement).transform,
),
).toBe('[{"translateX":0.5},{"translateY":75}]');
expect(viewElement.getBoundingClientRect().x).toBe(0.5);
expect(viewElement.getBoundingClientRect().y).toBe(75);
});
test('Animated.sequence', () => {
let _translateY;
let _isSequenceFinished = false;
const elementRef = createRef<HostInstance>();
function MyApp() {
const translateY = useAnimatedValue(0, {useNativeDriver: true});
_translateY = translateY;
return (
<View>
<Animated.View
ref={elementRef}
style={[
{
position: 'absolute',
width: 100,
height: 100,
},
{
transform: [
{
translateY: translateY.interpolate({
inputRange: [0, 1],
outputRange: [0, -16],
}),
},
],
},
]}
/>
</View>
);
}
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<MyApp />);
});
const element = ensureInstance(elementRef.current, ReactNativeElement);
expect(element.getBoundingClientRect().y).toBe(0);
Fantom.runTask(() => {
Animated.sequence([
Animated.timing(_translateY, {
toValue: 1,
duration: 500,
useNativeDriver: true,
}),
Animated.timing(_translateY, {
toValue: 0,
duration: 0,
useNativeDriver: true,
}),
]).start(({finished}) => {
if (finished) {
_isSequenceFinished = true;
}
});
});
Fantom.unstable_produceFramesForDuration(500);
expect(
// $FlowFixMe[incompatible-use]
Fantom.unstable_getDirectManipulationProps(element).transform[0].translateY,
).toBeCloseTo(-16, 0.001);
if (!ReactNativeFeatureFlags.cxxNativeAnimatedRemoveJsSync()) {
Fantom.runWorkLoop(); // React update to sync end state of 1st timing animation in sequence
}
expect(_isSequenceFinished).toBe(false);
expect(element.getBoundingClientRect().y).toBe(-16);
Fantom.runWorkLoop(); // React render
expect(
// $FlowFixMe[incompatible-use]
Fantom.unstable_getDirectManipulationProps(element).transform[0].translateY,
).toBeCloseTo(0, 0.001);
if (!ReactNativeFeatureFlags.cxxNativeAnimatedRemoveJsSync()) {
Fantom.runWorkLoop(); // React update to sync end state of 2nd timing animation in sequence
}
expect(element.getBoundingClientRect().y).toBe(0);
if (ReactNativeFeatureFlags.cxxNativeAnimatedRemoveJsSync()) {
expect(_isSequenceFinished).toBe(false);
Fantom.runWorkLoop();
}
expect(_isSequenceFinished).toBe(true);
});
+20 -5
View File
@@ -34,6 +34,9 @@ const RCTNetworking = require('./RCTNetworking').default;
const base64 = require('base64-js');
const invariant = require('invariant');
const PERFORMANCE_TRACK_NAME = 'Network (JS-initiated only)';
const PERFORMANCE_TRACK_GROUP = 'Chrome DevTools Temp Compat';
declare var performance: Performance;
const DEBUG_NETWORK_SEND_DELAY: false = false; // Set to a number of milliseconds when debugging
@@ -385,6 +388,9 @@ class XMLHttpRequest extends EventTarget {
if (requestId !== this._requestId) {
return;
}
const start = XMLHttpRequest._profiling ? performance.now() : undefined;
if (!this._response) {
this._response = responseText;
} else {
@@ -392,8 +398,13 @@ class XMLHttpRequest extends EventTarget {
}
if (XMLHttpRequest._profiling) {
performance.mark(
'Track:XMLHttpRequest:Incremental Data: ' + this._getMeasureURL(),
console.timeStamp(
'Incremental Data: ' + this._getMeasureURL(),
// $FlowFixMe[extra-arg] Add correct typing for `console.timeStamp`
start,
undefined,
PERFORMANCE_TRACK_NAME,
PERFORMANCE_TRACK_GROUP,
);
}
XMLHttpRequest._interceptor &&
@@ -442,10 +453,14 @@ class XMLHttpRequest extends EventTarget {
this.setReadyState(this.DONE);
if (XMLHttpRequest._profiling && this._startTime != null) {
const start = this._startTime;
performance.measure('Track:XMLHttpRequest:' + this._getMeasureURL(), {
console.timeStamp(
this._getMeasureURL(),
// $FlowFixMe[extra-arg] Add correct typing for `console.timeStamp`
start,
end: performance.now(),
});
undefined,
PERFORMANCE_TRACK_NAME,
PERFORMANCE_TRACK_GROUP,
);
}
if (error) {
XMLHttpRequest._interceptor &&
@@ -18,6 +18,7 @@ end
header_search_paths = [
"\"${PODS_ROOT}/Headers/Public/ReactCodegen/react/renderer/components\"",
"\"${PODS_ROOT}/Headers/Public/React-RCTFBReactNativeSpec/FBReactNativeSpec\"",
]
Pod::Spec.new do |s|
@@ -45,7 +46,9 @@ Pod::Spec.new do |s|
s.dependency "React-Core/RCTPushNotificationHeaders"
s.dependency "React-jsi"
add_dependency(s, "React-RCTFBReactNativeSpec")
add_dependency(s, "React-RCTFBReactNativeSpec", :additional_framework_paths => ['FBReactNativeSpec'])
add_dependency(s, "ReactCommon", :subspec => "turbomodule/core", :additional_framework_paths => ["react/nativemodule/core"])
add_dependency(s, "React-NativeModulesApple")
add_rncore_dependency(s)
end
+1 -1
View File
@@ -166,7 +166,7 @@ let reactJsInspector = RNTarget(
name: .reactJsInspector,
path: "ReactCommon/jsinspector-modern",
excludedPaths: ["tracing", "network", "tests"],
dependencies: [.reactNativeDependencies, .reactFeatureFlags, .jsi, .reactJsInspectorTracing, .reactJsInspectorNetwork, .reactRuntimeExecutor],
dependencies: [.reactNativeDependencies, .reactFeatureFlags, .jsi, .reactJsInspectorTracing, .reactJsInspectorNetwork, .reactRuntimeExecutor, .reactPerfLogger],
defines: [
CXXSetting.define("REACT_NATIVE_DEBUGGER_ENABLED", to: "1", .when(configuration: BuildConfiguration.debug)),
CXXSetting.define("REACT_NATIVE_DEBUGGER_ENABLED_DEVONLY", to: "1", .when(configuration: BuildConfiguration.debug)),
@@ -39,7 +39,7 @@ static NSString *const RCTPerfMonitorCellIdentifier = @"RCTPerfMonitorCellIdenti
static const CGFloat RCTPerfMonitorBarHeight = 50;
static const CGFloat RCTPerfMonitorExpandHeight = 250;
typedef BOOL (*RCTJSCSetOptionType)(const char *);
using RCTJSCSetOptionType = BOOL (*)(const char *);
NSArray<NSString *> *LabelsForRCTPerformanceLoggerTags();
@@ -117,6 +117,7 @@ public class ReactActivityDelegate {
* going away in the New Architecture. You should access {@link ReactHost} instead."
* @noinspection deprecation
*/
@Deprecated
public ReactInstanceManager getReactInstanceManager() {
return Objects.requireNonNull(mReactDelegate).getReactInstanceManager();
}
@@ -83,6 +83,9 @@ internal class ReactAndroidHWInputDeviceHelper(private val reactRootView: ReactR
KeyEvent.KEYCODE_DPAD_DOWN to "down",
KeyEvent.KEYCODE_DPAD_LEFT to "left",
KeyEvent.KEYCODE_INFO to "info",
KeyEvent.KEYCODE_MENU to "menu")
KeyEvent.KEYCODE_MENU to "menu",
KeyEvent.KEYCODE_CHANNEL_UP to "channelUp",
KeyEvent.KEYCODE_CHANNEL_DOWN to "channelDown",
)
}
}
@@ -10,26 +10,16 @@ package com.facebook.react.views.textinput
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.WritableMap
import com.facebook.react.bridge.buildReadableMap
import com.facebook.react.uimanager.common.ViewUtil
import com.facebook.react.uimanager.events.Event
/** Event emitted by EditText native view when content size changes. */
internal class ReactContentSizeChangedEvent(
internal class ReactContentSizeChangedEvent
constructor(
surfaceId: Int,
viewId: Int,
private val contentWidth: Float,
private val contentHeight: Float
) : Event<ReactTextChangedEvent>(surfaceId, viewId) {
@Deprecated(
"Use the constructor with surfaceId instead",
ReplaceWith(
"ReactContentSizeChangedEvent(surfaceId, viewId, contentSizeWidth, contentSizeHeight)"))
constructor(
viewId: Int,
contentSizeWidth: Float,
contentSizeHeight: Float
) : this(ViewUtil.NO_SURFACE_ID, viewId, contentSizeWidth, contentSizeHeight)
override fun getEventName(): String = EVENT_NAME
override fun getEventData(): WritableMap {
@@ -9,7 +9,6 @@ package com.facebook.react.views.textinput
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.WritableMap
import com.facebook.react.uimanager.common.ViewUtil
import com.facebook.react.uimanager.events.Event
/** Event emitted by EditText native view when text changes. */
@@ -19,15 +18,6 @@ internal class ReactTextChangedEvent(
private val text: String,
private val eventCount: Int
) : Event<ReactTextChangedEvent>(surfaceId, viewId) {
@Deprecated(
"Use the constructor with surfaceId instead",
ReplaceWith("ReactTextChangedEvent(surfaceId, viewId, text, eventCount)"))
constructor(
viewId: Int,
text: String,
eventCount: Int
) : this(ViewUtil.NO_SURFACE_ID, viewId, text, eventCount)
override fun getEventName(): String = EVENT_NAME
override fun getEventData(): WritableMap {
@@ -9,7 +9,6 @@ package com.facebook.react.views.textinput
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.WritableMap
import com.facebook.react.uimanager.common.ViewUtil
import com.facebook.react.uimanager.events.Event
/**
@@ -21,11 +20,6 @@ internal class ReactTextInputEndEditingEvent(
viewId: Int,
private val text: String
) : Event<ReactTextInputEndEditingEvent>(surfaceId, viewId) {
@Deprecated(
"Use the constructor with surfaceId instead",
ReplaceWith("ReactTextInputEndEditingEvent(surfaceId, viewId, text)"))
constructor(viewId: Int, text: String) : this(ViewUtil.NO_SURFACE_ID, viewId, text)
override fun getEventName(): String = EVENT_NAME
override fun canCoalesce(): Boolean = false
@@ -9,17 +9,11 @@ package com.facebook.react.views.textinput
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.WritableMap
import com.facebook.react.uimanager.common.ViewUtil
import com.facebook.react.uimanager.events.Event
/** Event emitted by EditText native view when key pressed. */
internal class ReactTextInputKeyPressEvent(surfaceId: Int, viewId: Int, private val key: String) :
Event<ReactTextInputKeyPressEvent>(surfaceId, viewId) {
@Deprecated(
"Use the constructor with surfaceId instead",
ReplaceWith("ReactTextInputKeyPressEvent(surfaceId, viewId, key)"))
constructor(viewId: Int, key: String) : this(ViewUtil.NO_SURFACE_ID, viewId, key)
override fun getEventName(): String = EVENT_NAME
override fun getEventData(): WritableMap {
@@ -10,7 +10,6 @@ package com.facebook.react.views.textinput
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.WritableMap
import com.facebook.react.bridge.buildReadableMap
import com.facebook.react.uimanager.common.ViewUtil
import com.facebook.react.uimanager.events.Event
/** Event emitted by EditText native view when the text selection changes. */
@@ -20,15 +19,6 @@ internal class ReactTextInputSelectionEvent(
private val selectionStart: Int,
private val selectionEnd: Int
) : Event<ReactTextInputSelectionEvent>(surfaceId, viewId) {
@Deprecated(
"Use the constructor with surfaceId instead",
ReplaceWith("ReactTextInputSelectionEvent(surfaceId, viewId, selectionStart, selectionEnd)"))
constructor(
viewId: Int,
selectionStart: Int,
selectionEnd: Int
) : this(ViewUtil.NO_SURFACE_ID, viewId, selectionStart, selectionEnd)
override fun getEventName(): String = EVENT_NAME
override fun getEventData(): WritableMap {
@@ -9,7 +9,6 @@ package com.facebook.react.views.textinput
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.WritableMap
import com.facebook.react.uimanager.common.ViewUtil
import com.facebook.react.uimanager.events.Event
/** Event emitted by EditText native view when the user submits the text. */
@@ -18,11 +17,6 @@ internal class ReactTextInputSubmitEditingEvent(
viewId: Int,
private val text: String
) : Event<ReactTextInputSubmitEditingEvent>(surfaceId, viewId) {
@Deprecated(
"Use the constructor with surfaceId instead",
ReplaceWith("ReactTextInputSubmitEditingEvent(surfaceId, viewId, text)"))
constructor(viewId: Int, text: String) : this(ViewUtil.NO_SURFACE_ID, viewId, text)
override fun getEventName(): String = EVENT_NAME
override fun getEventData(): WritableMap {
@@ -25,6 +25,7 @@ target_link_libraries(jsinspector
jsinspector_tracing
react_featureflags
runtimeexecutor
reactperflogger
)
target_compile_reactnative_options(jsinspector PRIVATE)
target_compile_options(jsinspector PRIVATE
@@ -8,6 +8,7 @@
#include <jsinspector-modern/RuntimeTarget.h>
#include <jsinspector-modern/tracing/PerformanceTracer.h>
#include <reactperflogger/ReactPerfettoLogger.h>
#include <concepts>
#include <deque>
#include <string>
@@ -19,6 +20,20 @@ namespace facebook::react::jsinspector_modern {
namespace {
inline std::optional<HighResTimeStamp> getTimeStampForPerfetto(
const std::optional<tracing::ConsoleTimeStampEntry>& consoleTimeStampEntry,
const HighResTimeStamp now) {
if (consoleTimeStampEntry) {
if (std::holds_alternative<HighResTimeStamp>(*consoleTimeStampEntry)) {
return std::get<HighResTimeStamp>(*consoleTimeStampEntry);
} else {
return std::nullopt;
}
} else {
return now;
}
}
struct ConsoleState {
/**
* https://console.spec.whatwg.org/#counting
@@ -376,7 +391,8 @@ void consoleTimeStamp(
const jsi::Value* arguments,
size_t argumentsCount) {
auto& performanceTracer = tracing::PerformanceTracer::getInstance();
if (!performanceTracer.isTracing() || argumentsCount == 0) {
if ((!performanceTracer.isTracing() && !ReactPerfettoLogger::isTracing()) ||
argumentsCount == 0) {
// If not tracing, just early return to avoid the cost of parsing.
return;
}
@@ -444,8 +460,22 @@ void consoleTimeStamp(
}
}
performanceTracer.reportTimeStamp(
label, start, end, trackName, trackGroup, color);
if (performanceTracer.isTracing()) {
performanceTracer.reportTimeStamp(
label, start, end, trackName, trackGroup, color);
}
if (ReactPerfettoLogger::isTracing()) {
std::optional<HighResTimeStamp> perfettoStart =
getTimeStampForPerfetto(start, now);
std::optional<HighResTimeStamp> perfettoEnd =
getTimeStampForPerfetto(end, now);
if (perfettoStart && perfettoEnd) {
ReactPerfettoLogger::measure(
label, *perfettoStart, *perfettoEnd, trackName, trackGroup);
}
}
}
/*
@@ -491,45 +491,6 @@ inline static void updateAccessibilityStateProp(
result["accessibilityState"] = resultState;
}
static folly::dynamic toDynamic(const std::vector<BoxShadow>& boxShadow) {
folly::dynamic boxShadowResult = folly::dynamic::array();
for (const auto& boxShadowValue : boxShadow) {
folly::dynamic boxShadowValueResult = folly::dynamic::object();
boxShadowValueResult["offsetX"] = boxShadowValue.offsetX;
boxShadowValueResult["offsetY"] = boxShadowValue.offsetY;
boxShadowValueResult["blurRadius"] = boxShadowValue.blurRadius;
boxShadowValueResult["spreadDistance"] = boxShadowValue.spreadDistance;
boxShadowValueResult["color"] = *boxShadowValue.color;
boxShadowValueResult["inset"] = boxShadowValue.inset;
boxShadowResult.push_back(boxShadowValueResult);
}
return boxShadowResult;
}
static folly::dynamic toDynamic(const std::vector<FilterFunction>& filter) {
folly::dynamic filterResult = folly::dynamic::array();
for (const auto& filterFunction : filter) {
folly::dynamic filterFunctionResult = folly::dynamic::object();
std::string typeKey = toString(filterFunction.type);
if (std::holds_alternative<Float>(filterFunction.parameters)) {
filterFunctionResult[typeKey] =
std::get<Float>(filterFunction.parameters);
} else if (std::holds_alternative<DropShadowParams>(
filterFunction.parameters)) {
const auto& parameters =
std::get<DropShadowParams>(filterFunction.parameters);
folly::dynamic parametersResult = folly::dynamic::object();
parametersResult["offsetX"] = parameters.offsetX;
parametersResult["offsetY"] = parameters.offsetY;
parametersResult["standardDeviation"] = parameters.standardDeviation;
parametersResult["color"] = *parameters.color;
filterFunctionResult[typeKey] = parametersResult;
}
filterResult.push_back(filterFunctionResult);
}
return filterResult;
}
ComponentName HostPlatformViewProps::getDiffPropsImplementationTarget() const {
return "View";
}
@@ -36,7 +36,7 @@ std::optional<double> DynamicEventPayload::extractValue(
if (dynamic.type() == folly::dynamic::Type::DOUBLE) {
return dynamic.asDouble();
} else if (dynamic.type() == folly::dynamic::Type::INT64) {
return dynamic.asInt();
return static_cast<double>(dynamic.asInt());
}
return std::nullopt;
}
@@ -21,5 +21,25 @@ struct BoxShadow {
Float spreadDistance{};
SharedColor color{};
bool inset{};
#ifdef RN_SERIALIZABLE_STATE
folly::dynamic toDynamic() const {
folly::dynamic result = folly::dynamic::object();
result["offsetX"] = offsetX;
result["offsetY"] = offsetY;
result["blurRadius"] = blurRadius;
result["spreadDistance"] = spreadDistance;
result["color"] = *color;
result["inset"] = inset;
return result;
}
#endif
};
#ifdef RN_SERIALIZABLE_STATE
inline folly::dynamic toDynamic(const BoxShadow& boxShadow) {
return boxShadow.toDynamic();
}
#endif
} // namespace facebook::react
@@ -8,7 +8,6 @@
#pragma once
#include <functional>
#include <limits>
#include <react/renderer/graphics/ColorComponents.h>
#include <react/renderer/graphics/HostPlatformColor.h>
@@ -29,22 +29,6 @@ enum class FilterType {
DropShadow
};
struct DropShadowParams {
bool operator==(const DropShadowParams& other) const = default;
Float offsetX{};
Float offsetY{};
Float standardDeviation{};
SharedColor color{};
};
struct FilterFunction {
bool operator==(const FilterFunction& other) const = default;
FilterType type{};
std::variant<Float, DropShadowParams> parameters{};
};
inline FilterType filterTypeFromString(std::string_view filterName) {
if (filterName == "blur") {
return FilterType::Blur;
@@ -96,4 +80,51 @@ inline std::string toString(const FilterType& filterType) {
}
}
struct DropShadowParams {
bool operator==(const DropShadowParams& other) const = default;
Float offsetX{};
Float offsetY{};
Float standardDeviation{};
SharedColor color{};
#ifdef RN_SERIALIZABLE_STATE
folly::dynamic toDynamic() const {
folly::dynamic result = folly::dynamic::object();
result["offsetX"] = offsetX;
result["offsetY"] = offsetY;
result["standardDeviation"] = standardDeviation;
result["color"] = *color;
return result;
}
#endif
};
struct FilterFunction {
bool operator==(const FilterFunction& other) const = default;
FilterType type{};
std::variant<Float, DropShadowParams> parameters{};
#ifdef RN_SERIALIZABLE_STATE
folly::dynamic toDynamic() const {
folly::dynamic result = folly::dynamic::object();
std::string typeKey = toString(type);
if (std::holds_alternative<Float>(parameters)) {
result[typeKey] = std::get<Float>(parameters);
} else if (std::holds_alternative<DropShadowParams>(parameters)) {
const auto& dropShadowParams = std::get<DropShadowParams>(parameters);
result[typeKey] = dropShadowParams.toDynamic();
}
return result;
}
#endif
};
#ifdef RN_SERIALIZABLE_STATE
inline folly::dynamic toDynamic(const FilterFunction& filterFunction) {
return filterFunction.toDynamic();
}
#endif
} // namespace facebook::react
@@ -8,7 +8,6 @@
#pragma once
#include <array>
#include <string>
#include <vector>
#include <react/renderer/debug/flags.h>
@@ -37,7 +36,7 @@ inline bool isZero(Float n) {
* An "Arbitrary" operation means that the transform was seeded with some
* arbitrary initial result.
*/
enum class TransformOperationType {
enum class TransformOperationType : uint8_t {
Arbitrary,
Identity,
Perspective,
@@ -9,8 +9,7 @@
#import <jsi/jsi.h>
#import <react/runtime/JSRuntimeFactory.h>
namespace facebook {
namespace react {
namespace facebook::react {
class RCTJscInstance : public JSRuntimeFactory {
public:
@@ -21,5 +20,4 @@ class RCTJscInstance : public JSRuntimeFactory {
~RCTJscInstance(){};
};
} // namespace react
} // namespace facebook
} // namespace facebook::react
@@ -8,8 +8,7 @@
#import "RCTJscInstance.h"
#include <jsc/JSCRuntime.h>
namespace facebook {
namespace react {
namespace facebook::react {
RCTJscInstance::RCTJscInstance() {}
@@ -18,5 +17,4 @@ std::unique_ptr<JSRuntime> RCTJscInstance::createJSRuntime(std::shared_ptr<Messa
return std::make_unique<JSIRuntimeHolder>(jsc::makeJSCRuntime());
}
} // namespace react
} // namespace facebook
} // namespace facebook::react
@@ -22,10 +22,26 @@ const std::string PERFETTO_DEFAULT_TRACK_NAME = "# Web Performance";
const std::string PERFETTO_TRACK_NAME_PREFIX = "# Web Performance: ";
std::string toPerfettoTrackName(
const std::optional<std::string_view>& trackName) {
return trackName.has_value()
? PERFETTO_TRACK_NAME_PREFIX + std::string(trackName.value())
: PERFETTO_DEFAULT_TRACK_NAME;
const std::optional<std::string_view>& trackName,
const std::optional<std::string_view>& trackGroup) {
std::string perfettoTrackName = PERFETTO_DEFAULT_TRACK_NAME;
if (trackName || trackGroup) {
perfettoTrackName += ": ";
if (trackGroup) {
perfettoTrackName += *trackGroup;
if (trackName) {
perfettoTrackName += " | ";
}
}
if (trackName) {
perfettoTrackName += *trackName;
}
}
return perfettoTrackName;
}
#elif defined(WITH_FBSYSTRACE)
int64_t getDeltaNanos(HighResTimeStamp jsTime) {
@@ -50,10 +66,12 @@ int64_t getDeltaNanos(HighResTimeStamp jsTime) {
const std::string_view& eventName,
HighResTimeStamp startTime,
HighResTimeStamp endTime,
const std::optional<std::string_view>& trackName) {
const std::optional<std::string_view>& trackName,
const std::optional<std::string_view>& trackGroup) {
#if defined(WITH_PERFETTO)
if (TRACE_EVENT_CATEGORY_ENABLED("react-native")) {
auto track = getPerfettoWebPerfTrackAsync(toPerfettoTrackName(trackName));
auto track = getPerfettoWebPerfTrackAsync(
toPerfettoTrackName(trackName, trackGroup));
TRACE_EVENT_BEGIN(
"react-native",
perfetto::DynamicString(eventName.data(), eventName.size()),
@@ -75,13 +93,14 @@ int64_t getDeltaNanos(HighResTimeStamp jsTime) {
/* static */ void ReactPerfettoLogger::mark(
const std::string_view& eventName,
HighResTimeStamp startTime,
const std::optional<std::string_view>& trackName) {
const std::optional<std::string_view>& trackName,
const std::optional<std::string_view>& trackGroup) {
#if defined(WITH_PERFETTO)
if (TRACE_EVENT_CATEGORY_ENABLED("react-native")) {
TRACE_EVENT_INSTANT(
"react-native",
perfetto::DynamicString(eventName.data(), eventName.size()),
getPerfettoWebPerfTrackSync(toPerfettoTrackName(trackName)),
getPerfettoWebPerfTrackSync(toPerfettoTrackName(trackName, trackGroup)),
highResTimeStampToPerfettoTraceTime(startTime));
}
#elif defined(WITH_FBSYSTRACE)
@@ -11,7 +11,7 @@
#include <reactperflogger/ReactPerfettoCategories.h>
#include <optional>
#include <string>
#include <string_view>
namespace facebook::react {
@@ -26,13 +26,15 @@ class ReactPerfettoLogger {
static void mark(
const std::string_view& eventName,
HighResTimeStamp startTime,
const std::optional<std::string_view>& trackName);
const std::optional<std::string_view>& trackName = std::nullopt,
const std::optional<std::string_view>& trackGroup = std::nullopt);
static void measure(
const std::string_view& eventName,
HighResTimeStamp startTime,
HighResTimeStamp endTime,
const std::optional<std::string_view>& trackName);
const std::optional<std::string_view>& trackName = std::nullopt,
const std::optional<std::string_view>& trackGroup = std::nullopt);
};
} // namespace facebook::react
@@ -478,16 +478,19 @@ static void zeroOutLayoutRecursively(yoga::Node* const node) {
}
static void cleanupContentsNodesRecursively(yoga::Node* const node) {
for (auto child : node->getChildren()) {
if (child->style().display() == Display::Contents) {
child->getLayout() = {};
child->setLayoutDimension(0, Dimension::Width);
child->setLayoutDimension(0, Dimension::Height);
child->setHasNewLayout(true);
child->setDirty(false);
child->cloneChildrenIfNeeded();
if (node->hasContentsChildren()) [[unlikely]] {
node->cloneContentsChildrenIfNeeded();
for (auto child : node->getChildren()) {
if (child->style().display() == Display::Contents) {
child->getLayout() = {};
child->setLayoutDimension(0, Dimension::Width);
child->setLayoutDimension(0, Dimension::Height);
child->setHasNewLayout(true);
child->setDirty(false);
child->cloneChildrenIfNeeded();
cleanupContentsNodesRecursively(child);
cleanupContentsNodesRecursively(child);
}
}
}
}
@@ -181,6 +181,17 @@ void Node::setDirty(bool isDirty) {
}
}
void Node::setChildren(const std::vector<Node*>& children) {
children_ = children;
contentsChildrenCount_ = 0;
for (const auto& child : children) {
if (child->style().display() == Display::Contents) {
contentsChildrenCount_++;
}
}
}
bool Node::removeChild(Node* child) {
auto p = std::find(children_.begin(), children_.end(), child);
if (p != children_.end()) {
@@ -380,6 +391,23 @@ void Node::cloneChildrenIfNeeded() {
if (child->getOwner() != this) {
child = resolveRef(config_->cloneNode(child, this, i));
child->setOwner(this);
if (child->hasContentsChildren()) [[unlikely]] {
child->cloneContentsChildrenIfNeeded();
}
}
i += 1;
}
}
void Node::cloneContentsChildrenIfNeeded() {
size_t i = 0;
for (Node*& child : children_) {
if (child->style().display() == Display::Contents &&
child->getOwner() != this) {
child = resolveRef(config_->cloneNode(child, this, i));
child->setOwner(this);
child->cloneChildrenIfNeeded();
}
i += 1;
}
@@ -96,6 +96,10 @@ class YG_EXPORT Node : public ::YGNode {
return config_->hasErrata(errata);
}
bool hasContentsChildren() const {
return contentsChildrenCount_ != 0;
}
YGDirtiedFunc getDirtiedFunc() const {
return dirtiedFunc_;
}
@@ -244,15 +248,12 @@ class YG_EXPORT Node : public ::YGNode {
owner_ = owner;
}
void setChildren(const std::vector<Node*>& children) {
children_ = children;
}
// TODO: rvalue override for setChildren
void setConfig(Config* config);
void setDirty(bool isDirty);
void setChildren(const std::vector<Node*>& children);
void setLayoutLastOwnerDirection(Direction direction);
void setLayoutComputedFlexBasis(FloatOptional computedFlexBasis);
void setLayoutComputedFlexBasisGeneration(
@@ -286,6 +287,7 @@ class YG_EXPORT Node : public ::YGNode {
void removeChild(size_t index);
void cloneChildrenIfNeeded();
void cloneContentsChildrenIfNeeded();
void markDirtyAndPropagate();
float resolveFlexGrow() const;
float resolveFlexShrink() const;
@@ -134,8 +134,8 @@ class ReactNativeCoreUtils
## You can use the `ENTERPRISE_REPOSITORY` ariable to customise the base url from which artifacts will be downloaded.
## The mirror's structure must be the same of the Maven repo the react-native core team publishes on Maven Central.
maven_repo_url =
ENV[ENTERPRISE_REPOSITORY] != nil && ENV[ENTERPRISE_REPOSITORY] != "" ?
ENV[ENTERPRISE_REPOSITORY] :
ENV['ENTERPRISE_REPOSITORY'] != nil && ENV['ENTERPRISE_REPOSITORY'] != "" ?
ENV['ENTERPRISE_REPOSITORY'] :
"https://repo1.maven.org/maven2"
group = "com/facebook/react"
# Sample url from Maven:
@@ -169,8 +169,8 @@ class ReactNativeDependenciesUtils
## You can use the `ENTERPRISE_REPOSITORY` ariable to customise the base url from which artifacts will be downloaded.
## The mirror's structure must be the same of the Maven repo the react-native core team publishes on Maven Central.
maven_repo_url =
ENV[ENTERPRISE_REPOSITORY] != nil && ENV[ENTERPRISE_REPOSITORY] != "" ?
ENV[ENTERPRISE_REPOSITORY] :
ENV['ENTERPRISE_REPOSITORY'] != nil && ENV['ENTERPRISE_REPOSITORY'] != "" ?
ENV['ENTERPRISE_REPOSITORY'] :
"https://repo1.maven.org/maven2"
group = "com/facebook/react"
# Sample url from Maven:
@@ -207,8 +207,8 @@ def release_tarball_url(version, build_type)
## You can use the `ENTERPRISE_REPOSITORY` ariable to customise the base url from which artifacts will be downloaded.
## The mirror's structure must be the same of the Maven repo the react-native core team publishes on Maven Central.
maven_repo_url =
ENV[ENTERPRISE_REPOSITORY] != nil && ENV[ENTERPRISE_REPOSITORY] != "" ?
ENV[ENTERPRISE_REPOSITORY] :
ENV['ENTERPRISE_REPOSITORY'] != nil && ENV['ENTERPRISE_REPOSITORY'] != "" ?
ENV['ENTERPRISE_REPOSITORY'] :
"https://repo1.maven.org/maven2"
namespace = "com/facebook/react"
# Sample url from Maven:
@@ -15,7 +15,11 @@ import type {
PerformanceEntryList,
PerformanceEntryType,
} from './PerformanceEntry';
import type {DetailType, PerformanceMarkOptions} from './UserTiming';
import type {
DetailType,
PerformanceMarkOptions,
PerformanceMeasureInit,
} from './UserTiming';
import DOMException from '../errors/DOMException';
import structuredClone from '../structuredClone/structuredClone';
@@ -25,35 +29,46 @@ import {
performanceEntryTypeToRaw,
rawToPerformanceEntry,
} from './internals/RawPerformanceEntry';
import {warnNoNativePerformance} from './internals/Utilities';
import {
getCurrentTimeStamp,
warnNoNativePerformance,
} from './internals/Utilities';
import MemoryInfo from './MemoryInfo';
import ReactNativeStartupTiming from './ReactNativeStartupTiming';
import NativePerformance from './specs/NativePerformance';
import {PerformanceMark, PerformanceMeasure} from './UserTiming';
declare var global: {
// This value is defined directly via JSI, if available.
+nativePerformanceNow?: ?() => number,
};
const getCurrentTimeStamp: () => DOMHighResTimeStamp =
NativePerformance?.now ?? global.nativePerformanceNow ?? (() => Date.now());
export type PerformanceMeasureOptions =
| {
| $ReadOnly<{
detail?: DetailType,
start?: DOMHighResTimeStamp | string,
duration?: DOMHighResTimeStamp,
}
| {
}>
| $ReadOnly<{
detail?: DetailType,
start?: DOMHighResTimeStamp | string,
end?: DOMHighResTimeStamp | string,
};
}>;
const ENTRY_TYPES_AVAILABLE_FROM_TIMELINE: $ReadOnlyArray<PerformanceEntryType> =
['mark', 'measure'];
const cachedNativeMark = NativePerformance?.markWithResult;
const cachedNativeMeasure = NativePerformance?.measure;
const cachedNativeClearMarks = NativePerformance?.clearMarks;
const cachedNativeClearMeasures = NativePerformance?.clearMeasures;
const MARK_OPTIONS_REUSABLE_OBJECT: {...PerformanceMarkOptions} = {
startTime: 0,
detail: undefined,
};
const MEASURE_OPTIONS_REUSABLE_OBJECT: {...PerformanceMeasureInit} = {
startTime: 0,
duration: 0,
detail: undefined,
};
/**
* Partial implementation of the Performance interface for RN,
* corresponding to the standard in
@@ -117,58 +132,68 @@ export default class Performance {
markName: string,
markOptions?: PerformanceMarkOptions,
): PerformanceMark {
if (markName == null) {
// IMPORTANT: this method has been micro-optimized.
// Please run the benchmarks in `Performance-benchmarks-itest` to ensure
// changes do not regress performance.
if (markName === undefined) {
throw new TypeError(
`Failed to execute 'mark' on 'Performance': 1 argument required, but only 0 present.`,
);
}
const resolvedMarkName =
typeof markName === 'string' ? markName : String(markName);
let resolvedDetail;
if (markOptions?.detail != null) {
resolvedDetail = structuredClone(markOptions.detail);
const detail = markOptions?.detail;
if (detail !== undefined) {
resolvedDetail = structuredClone(detail);
}
let computedStartTime;
if (NativePerformance?.markWithResult) {
if (cachedNativeMark) {
let resolvedStartTime;
const startTime = markOptions?.startTime;
if (startTime !== undefined) {
resolvedStartTime = Number(startTime);
resolvedStartTime =
typeof startTime === 'number' ? startTime : Number(startTime);
if (resolvedStartTime < 0) {
throw new TypeError(
`Failed to execute 'mark' on 'Performance': '${markName}' cannot have a negative start time.`,
`Failed to execute 'mark' on 'Performance': '${resolvedMarkName}' cannot have a negative start time.`,
);
} else if (!Number.isFinite(resolvedStartTime)) {
} else if (
// This is faster than calling Number.isFinite()
// eslint-disable-next-line no-self-compare
resolvedStartTime !== resolvedStartTime ||
resolvedStartTime === Infinity
) {
throw new TypeError(
`Failed to execute 'mark' on 'Performance': Failed to read the 'startTime' property from 'PerformanceMarkOptions': The provided double value is non-finite.`,
);
}
}
// $FlowExpectedError[not-a-function]
computedStartTime = NativePerformance.markWithResult(
markName,
resolvedStartTime,
);
computedStartTime = cachedNativeMark(resolvedMarkName, resolvedStartTime);
} else {
warnNoNativePerformance();
computedStartTime = performance.now();
computedStartTime = getCurrentTimeStamp();
}
return new PerformanceMark(markName, {
startTime: computedStartTime,
detail: resolvedDetail,
});
MARK_OPTIONS_REUSABLE_OBJECT.startTime = computedStartTime;
MARK_OPTIONS_REUSABLE_OBJECT.detail = resolvedDetail;
return new PerformanceMark(resolvedMarkName, MARK_OPTIONS_REUSABLE_OBJECT);
}
clearMarks(markName?: string): void {
if (!NativePerformance?.clearMarks) {
if (!cachedNativeClearMarks) {
warnNoNativePerformance();
return;
}
NativePerformance.clearMarks(markName);
cachedNativeClearMarks(markName);
}
measure(
@@ -176,6 +201,18 @@ export default class Performance {
startMarkOrOptions?: string | PerformanceMeasureOptions,
endMark?: string,
): PerformanceMeasure {
// IMPORTANT: this method has been micro-optimized.
// Please run the benchmarks in `Performance-benchmarks-itest` to ensure
// changes do not regress performance.
if (measureName === undefined) {
throw new TypeError(
`Failed to execute 'measure' on 'Performance': 1 argument required, but only 0 present.`,
);
}
let resolvedMeasureName =
typeof measureName === 'string' ? measureName : String(measureName);
let resolvedStartTime: number | void;
let resolvedStartMark: string | void;
let resolvedEndTime: number | void;
@@ -186,7 +223,7 @@ export default class Performance {
if (startMarkOrOptions != null) {
switch (typeof startMarkOrOptions) {
case 'object': {
if (endMark != null) {
if (endMark !== undefined) {
throw new TypeError(
`Failed to execute 'measure' on 'Performance': If a non-empty PerformanceMeasureOptions object was passed, |end_mark| must not be passed.`,
);
@@ -247,8 +284,8 @@ export default class Performance {
}
if (
resolvedDuration != null &&
(resolvedEndMark != null || resolvedEndTime != null)
resolvedDuration !== undefined &&
(resolvedEndMark !== undefined || resolvedEndTime !== undefined)
) {
throw new TypeError(
`Failed to execute 'measure' on 'Performance': If a non-empty PerformanceMeasureOptions object was passed, it must not have all of its 'start', 'duration', and 'end' properties defined`,
@@ -256,7 +293,7 @@ export default class Performance {
}
const detail = startMarkOrOptions.detail;
if (detail != null) {
if (detail !== undefined) {
resolvedDetail = structuredClone(detail);
}
@@ -279,10 +316,10 @@ export default class Performance {
let computedStartTime = 0;
let computedDuration = 0;
if (NativePerformance?.measure) {
if (cachedNativeMeasure) {
try {
[computedStartTime, computedDuration] = NativePerformance.measure(
measureName,
[computedStartTime, computedDuration] = cachedNativeMeasure(
resolvedMeasureName,
resolvedStartTime,
resolvedEndTime,
resolvedDuration,
@@ -299,7 +336,7 @@ export default class Performance {
try {
[computedStartTime, computedDuration] =
NativePerformance.measureWithResult(
measureName,
resolvedMeasureName,
resolvedStartTime ?? 0,
resolvedEndTime ?? 0,
resolvedDuration,
@@ -316,22 +353,23 @@ export default class Performance {
warnNoNativePerformance();
}
const measure = new PerformanceMeasure(measureName, {
startTime: computedStartTime,
duration: computedDuration ?? 0,
detail: resolvedDetail,
});
MEASURE_OPTIONS_REUSABLE_OBJECT.startTime = computedStartTime;
MEASURE_OPTIONS_REUSABLE_OBJECT.duration = computedDuration ?? 0;
MEASURE_OPTIONS_REUSABLE_OBJECT.detail = resolvedDetail;
return measure;
return new PerformanceMeasure(
resolvedMeasureName,
MEASURE_OPTIONS_REUSABLE_OBJECT,
);
}
clearMeasures(measureName?: string): void {
if (!NativePerformance?.clearMeasures) {
if (!cachedNativeClearMeasures) {
warnNoNativePerformance();
return;
}
NativePerformance?.clearMeasures(measureName);
cachedNativeClearMeasures(measureName);
}
/**
@@ -12,44 +12,43 @@
import type {DOMHighResTimeStamp} from './PerformanceEntry';
import {getCurrentTimeStamp} from './internals/Utilities';
import {PerformanceEntry} from './PerformanceEntry';
export type DetailType = mixed;
export type PerformanceMarkOptions = {
export type PerformanceMarkOptions = $ReadOnly<{
detail?: DetailType,
startTime?: DOMHighResTimeStamp,
};
}>;
export type TimeStampOrName = DOMHighResTimeStamp | string;
export type PerformanceMeasureInit = {
export type PerformanceMeasureInit = $ReadOnly<{
detail?: DetailType,
startTime: DOMHighResTimeStamp,
duration: DOMHighResTimeStamp,
};
}>;
class PerformanceMarkTemplate extends PerformanceEntry {
// We don't use private fields because they're significantly slower to
// initialize on construction and to access.
_detail: DetailType;
__detail: DetailType;
// This constructor isn't really used. See `PerformanceMark` below.
constructor(markName: string, markOptions?: PerformanceMarkOptions) {
super({
name: markName,
entryType: 'mark',
startTime: markOptions?.startTime ?? performance.now(),
startTime: markOptions?.startTime ?? getCurrentTimeStamp(),
duration: 0,
});
if (markOptions) {
this._detail = markOptions.detail;
}
this.__detail = markOptions?.detail ?? null;
}
get detail(): DetailType {
return this._detail;
return this.__detail;
}
}
@@ -67,12 +66,10 @@ export const PerformanceMark: typeof PerformanceMarkTemplate =
) {
this.__name = markName;
this.__entryType = 'mark';
this.__startTime = markOptions?.startTime ?? performance.now();
this.__startTime = markOptions?.startTime ?? getCurrentTimeStamp();
this.__duration = 0;
if (markOptions) {
this._detail = markOptions.detail;
}
this.__detail = markOptions?.detail ?? null;
};
// $FlowExpectedError[prop-missing]
@@ -81,7 +78,7 @@ PerformanceMark.prototype = PerformanceMarkTemplate.prototype;
class PerformanceMeasureTemplate extends PerformanceEntry {
// We don't use private fields because they're significantly slower to
// initialize on construction and to access.
_detail: DetailType;
__detail: DetailType;
// This constructor isn't really used. See `PerformanceMeasure` below.
constructor(measureName: string, measureOptions: PerformanceMeasureInit) {
@@ -92,13 +89,11 @@ class PerformanceMeasureTemplate extends PerformanceEntry {
duration: measureOptions.duration,
});
if (measureOptions) {
this._detail = measureOptions.detail;
}
this.__detail = measureOptions?.detail ?? null;
}
get detail(): DetailType {
return this._detail;
return this.__detail;
}
}
@@ -115,9 +110,7 @@ export const PerformanceMeasure: typeof PerformanceMeasureTemplate =
this.__startTime = measureOptions.startTime;
this.__duration = measureOptions.duration;
if (measureOptions) {
this._detail = measureOptions.detail;
}
this.__detail = measureOptions.detail ?? null;
};
// $FlowExpectedError[prop-missing]
@@ -44,6 +44,15 @@ Fantom.unstable_benchmark
afterEach: clearMarksAndMeasures,
},
)
.test(
'measure (default)',
() => {
performance.measure('measure');
},
{
afterEach: clearMarksAndMeasures,
},
)
.test(
'measure (with start and end timestamps)',
() => {
@@ -53,7 +53,7 @@ describe('Performance', () => {
expect(mark.name).toBe('mark-now');
expect(mark.startTime).toBe(25);
expect(mark.duration).toBe(0);
expect(mark.detail).toBeUndefined();
expect(mark.detail).toBe(null);
});
it('works with custom timestamp', () => {
@@ -64,7 +64,7 @@ describe('Performance', () => {
expect(mark.name).toBe('mark-custom');
expect(mark.startTime).toBe(10);
expect(mark.duration).toBe(0);
expect(mark.detail).toBeUndefined();
expect(mark.detail).toBe(null);
});
it('provides detail', () => {
@@ -78,6 +78,13 @@ describe('Performance', () => {
expect(mark.detail).not.toBe(originalDetail);
});
it('provides a null detail if it is not provided or is undefined', () => {
expect(performance.mark('mark-without-detail').detail).toBe(null);
expect(
performance.mark('mark-without-detail', {detail: undefined}).detail,
).toBe(null);
});
it('throws if no name is provided', () => {
expect(() => {
// $FlowExpectedError[incompatible-call]
@@ -87,6 +94,13 @@ describe('Performance', () => {
);
});
it('casts mark name to a string', () => {
// $FlowExpectedError[incompatible-call]
const mark = performance.mark(10);
expect(mark.name).toBe('10');
});
it('casts startTime to a number', () => {
const mark = performance.mark('some-mark', {
// $FlowExpectedError[incompatible-call]
@@ -139,7 +153,7 @@ describe('Performance', () => {
expect(measure.name).toBe('measure-with-defaults');
expect(measure.startTime).toBe(0);
expect(measure.duration).toBe(25);
expect(measure.detail).toBeUndefined();
expect(measure.detail).toBe(null);
});
it('works with a start timestamp', () => {
@@ -154,7 +168,7 @@ describe('Performance', () => {
expect(measure.name).toBe('measure-with-start-timestamp');
expect(measure.startTime).toBe(10);
expect(measure.duration).toBe(15);
expect(measure.detail).toBeUndefined();
expect(measure.detail).toBe(null);
});
it('works with start mark', () => {
@@ -173,7 +187,7 @@ describe('Performance', () => {
expect(measure.name).toBe('measure-with-start-mark');
expect(measure.startTime).toBe(10);
expect(measure.duration).toBe(15);
expect(measure.detail).toBeUndefined();
expect(measure.detail).toBe(null);
});
it('works with end mark', () => {
@@ -192,7 +206,7 @@ describe('Performance', () => {
expect(measure.name).toBe('measure-with-end-mark');
expect(measure.startTime).toBe(0);
expect(measure.duration).toBe(50);
expect(measure.detail).toBeUndefined();
expect(measure.detail).toBe(null);
});
it('works with start mark and end mark', () => {
@@ -219,7 +233,7 @@ describe('Performance', () => {
expect(measure.name).toBe('measure-with-start-mark-and-end-mark');
expect(measure.startTime).toBe(10);
expect(measure.duration).toBe(40);
expect(measure.detail).toBeUndefined();
expect(measure.detail).toBe(null);
});
it('works with a start timestamp and an end timestamp', () => {
@@ -238,7 +252,7 @@ describe('Performance', () => {
);
expect(measure.startTime).toBe(10);
expect(measure.duration).toBe(15);
expect(measure.detail).toBeUndefined();
expect(measure.detail).toBe(null);
});
it('works with a start timestamp and a duration', () => {
@@ -255,7 +269,7 @@ describe('Performance', () => {
expect(measure.name).toBe('measure-with-start-timestamp-and-duration');
expect(measure.startTime).toBe(10);
expect(measure.duration).toBe(30);
expect(measure.detail).toBeUndefined();
expect(measure.detail).toBe(null);
});
it('works with a start mark and a duration', () => {
@@ -276,7 +290,7 @@ describe('Performance', () => {
expect(measure.name).toBe('measure-with-start-mark-and-duration');
expect(measure.startTime).toBe(10);
expect(measure.duration).toBe(30);
expect(measure.detail).toBeUndefined();
expect(measure.detail).toBe(null);
});
it('throws if the specified mark does NOT exist', () => {
@@ -332,7 +346,7 @@ describe('Performance', () => {
expect(measure.name).toBe('measure-with-defaults');
expect(measure.startTime).toBe(0);
expect(measure.duration).toBe(25);
expect(measure.detail).toBeUndefined();
expect(measure.detail).toBe(null);
});
it('works with startMark', () => {
@@ -352,7 +366,7 @@ describe('Performance', () => {
expect(measure.name).toBe('measure-with-start-mark');
expect(measure.startTime).toBe(10);
expect(measure.duration).toBe(15);
expect(measure.detail).toBeUndefined();
expect(measure.detail).toBe(null);
});
it('works with startMark and endMark', () => {
@@ -376,7 +390,7 @@ describe('Performance', () => {
expect(measure.name).toBe('measure-with-start-mark-and-end-mark');
expect(measure.startTime).toBe(10);
expect(measure.duration).toBe(15);
expect(measure.detail).toBeUndefined();
expect(measure.detail).toBe(null);
});
it('throws if the specified marks do NOT exist', () => {
@@ -424,6 +438,30 @@ describe('Performance', () => {
expect(measure.detail).toEqual(originalDetail);
expect(measure.detail).not.toBe(originalDetail);
});
it('provides a null detail if it is not provided or is undefined', () => {
expect(performance.measure('measure-without-detail').detail).toBe(null);
expect(
performance.measure('measure-without-detail', {detail: undefined})
.detail,
).toBe(null);
});
it('casts measure name to a string', () => {
// $FlowExpectedError[incompatible-call]
const measure = performance.measure(10);
expect(measure.name).toBe('10');
});
it('throws if no name is provided', () => {
expect(() => {
// $FlowExpectedError[incompatible-call]
performance.measure();
}).toThrow(
`Failed to execute 'measure' on 'Performance': 1 argument required, but only 0 present.`,
);
});
});
describe('getting and clearing marks and measures', () => {
@@ -9,6 +9,7 @@
*/
import warnOnce from '../../../../../Libraries/Utilities/warnOnce';
import NativePerformance from '../specs/NativePerformance';
export function warnNoNativePerformance() {
warnOnce(
@@ -16,3 +17,11 @@ export function warnNoNativePerformance() {
'Missing native implementation of Performance',
);
}
declare var global: {
// This value is defined directly via JSI, if available.
+nativePerformanceNow?: ?() => number,
};
export const getCurrentTimeStamp: () => DOMHighResTimeStamp =
NativePerformance?.now ?? global.nativePerformanceNow ?? (() => Date.now());
+2 -2
View File
@@ -6,10 +6,10 @@ Scripts supporting local manual release testing. See also [How to Test a Release
For information on command arguments, run `node <command> --help`.
### `test-e2e-local`
### `test-release-local`
Set up, build, and install a given test app configuration.
### `test-e2e-local-clean`
### `test-release-local-clean`
Clean up all file system and cache state between tests.
@@ -11,7 +11,7 @@
'use strict';
/*
* This script, paired with test-e2e-local.js, is the full suite of
* This script, paired with test-release-local.js, is the full suite of
* tooling needed for a successful local testing experience.
* This script is an helper to clean up the environment fully
* before running the test suite.
+109 -71
View File
@@ -1359,13 +1359,20 @@
minimist "^1.2.8"
postject "^1.0.0-alpha.6"
"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0":
"@eslint-community/eslint-utils@^4.2.0":
version "4.4.0"
resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59"
integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==
dependencies:
eslint-visitor-keys "^3.3.0"
"@eslint-community/eslint-utils@^4.7.0":
version "4.7.0"
resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz#607084630c6c033992a082de6e6fbc1a8b52175a"
integrity sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==
dependencies:
eslint-visitor-keys "^3.4.3"
"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.6.1":
version "4.11.0"
resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.11.0.tgz#b0ffd0312b4a3fd2d6f77237e7248a5ad3a680ae"
@@ -2495,20 +2502,20 @@
dependencies:
"@types/node" "*"
"@typescript-eslint/eslint-plugin@^7.1.1":
version "7.18.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz#b16d3cf3ee76bf572fdf511e79c248bdec619ea3"
integrity sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==
"@typescript-eslint/eslint-plugin@^8.36.0":
version "8.36.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.36.0.tgz#880ce277f8a30ccf539ec027acac157088f131ae"
integrity sha512-lZNihHUVB6ZZiPBNgOQGSxUASI7UJWhT8nHyUGCnaQ28XFCw98IfrMCG3rUl1uwUWoAvodJQby2KTs79UTcrAg==
dependencies:
"@eslint-community/regexpp" "^4.10.0"
"@typescript-eslint/scope-manager" "7.18.0"
"@typescript-eslint/type-utils" "7.18.0"
"@typescript-eslint/utils" "7.18.0"
"@typescript-eslint/visitor-keys" "7.18.0"
"@typescript-eslint/scope-manager" "8.36.0"
"@typescript-eslint/type-utils" "8.36.0"
"@typescript-eslint/utils" "8.36.0"
"@typescript-eslint/visitor-keys" "8.36.0"
graphemer "^1.4.0"
ignore "^5.3.1"
ignore "^7.0.0"
natural-compare "^1.4.0"
ts-api-utils "^1.3.0"
ts-api-utils "^2.1.0"
"@typescript-eslint/parser@7.2.0":
version "7.2.0"
@@ -2521,15 +2528,24 @@
"@typescript-eslint/visitor-keys" "7.2.0"
debug "^4.3.4"
"@typescript-eslint/parser@^7.1.1":
version "7.18.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.18.0.tgz#83928d0f1b7f4afa974098c64b5ce6f9051f96a0"
integrity sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==
"@typescript-eslint/parser@^8.36.0":
version "8.36.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.36.0.tgz#003007fe2030013936b6634b9cf52c457d36ed42"
integrity sha512-FuYgkHwZLuPbZjQHzJXrtXreJdFMKl16BFYyRrLxDhWr6Qr7Kbcu2s1Yhu8tsiMXw1S0W1pjfFfYEt+R604s+Q==
dependencies:
"@typescript-eslint/scope-manager" "7.18.0"
"@typescript-eslint/types" "7.18.0"
"@typescript-eslint/typescript-estree" "7.18.0"
"@typescript-eslint/visitor-keys" "7.18.0"
"@typescript-eslint/scope-manager" "8.36.0"
"@typescript-eslint/types" "8.36.0"
"@typescript-eslint/typescript-estree" "8.36.0"
"@typescript-eslint/visitor-keys" "8.36.0"
debug "^4.3.4"
"@typescript-eslint/project-service@8.36.0":
version "8.36.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.36.0.tgz#0c4acdcbe56476a43cdabaac1f08819424a379fd"
integrity sha512-JAhQFIABkWccQYeLMrHadu/fhpzmSQ1F1KXkpzqiVxA/iYI6UnRt2trqXHt1sYEcw1mxLnB9rKMsOxXPxowN/g==
dependencies:
"@typescript-eslint/tsconfig-utils" "^8.36.0"
"@typescript-eslint/types" "^8.36.0"
debug "^4.3.4"
"@typescript-eslint/scope-manager@5.62.0":
@@ -2540,14 +2556,6 @@
"@typescript-eslint/types" "5.62.0"
"@typescript-eslint/visitor-keys" "5.62.0"
"@typescript-eslint/scope-manager@7.18.0":
version "7.18.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz#c928e7a9fc2c0b3ed92ab3112c614d6bd9951c83"
integrity sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==
dependencies:
"@typescript-eslint/types" "7.18.0"
"@typescript-eslint/visitor-keys" "7.18.0"
"@typescript-eslint/scope-manager@7.2.0":
version "7.2.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.2.0.tgz#cfb437b09a84f95a0930a76b066e89e35d94e3da"
@@ -2556,31 +2564,44 @@
"@typescript-eslint/types" "7.2.0"
"@typescript-eslint/visitor-keys" "7.2.0"
"@typescript-eslint/type-utils@7.18.0":
version "7.18.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.18.0.tgz#2165ffaee00b1fbbdd2d40aa85232dab6998f53b"
integrity sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==
"@typescript-eslint/scope-manager@8.36.0":
version "8.36.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.36.0.tgz#23e4196ed07d7ea3737a584fbebc9a79c3835168"
integrity sha512-wCnapIKnDkN62fYtTGv2+RY8FlnBYA3tNm0fm91kc2BjPhV2vIjwwozJ7LToaLAyb1ca8BxrS7vT+Pvvf7RvqA==
dependencies:
"@typescript-eslint/typescript-estree" "7.18.0"
"@typescript-eslint/utils" "7.18.0"
"@typescript-eslint/types" "8.36.0"
"@typescript-eslint/visitor-keys" "8.36.0"
"@typescript-eslint/tsconfig-utils@8.36.0", "@typescript-eslint/tsconfig-utils@^8.36.0":
version "8.36.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.36.0.tgz#63ef8a20ae9b5754c6ceacbe87b2fe1aab12ba13"
integrity sha512-Nhh3TIEgN18mNbdXpd5Q8mSCBnrZQeY9V7Ca3dqYvNDStNIGRmJA6dmrIPMJ0kow3C7gcQbpsG2rPzy1Ks/AnA==
"@typescript-eslint/type-utils@8.36.0":
version "8.36.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.36.0.tgz#16b092c2cbbb5549f6a4df1382a481586850502f"
integrity sha512-5aaGYG8cVDd6cxfk/ynpYzxBRZJk7w/ymto6uiyUFtdCozQIsQWh7M28/6r57Fwkbweng8qAzoMCPwSJfWlmsg==
dependencies:
"@typescript-eslint/typescript-estree" "8.36.0"
"@typescript-eslint/utils" "8.36.0"
debug "^4.3.4"
ts-api-utils "^1.3.0"
ts-api-utils "^2.1.0"
"@typescript-eslint/types@5.62.0":
version "5.62.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.62.0.tgz#258607e60effa309f067608931c3df6fed41fd2f"
integrity sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==
"@typescript-eslint/types@7.18.0":
version "7.18.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.18.0.tgz#b90a57ccdea71797ffffa0321e744f379ec838c9"
integrity sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==
"@typescript-eslint/types@7.2.0":
version "7.2.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.2.0.tgz#0feb685f16de320e8520f13cca30779c8b7c403f"
integrity sha512-XFtUHPI/abFhm4cbCDc5Ykc8npOKBSJePY3a3s+lwumt7XWJuzP5cZcfZ610MIPHjQjNsOLlYK8ASPaNG8UiyA==
"@typescript-eslint/types@8.36.0", "@typescript-eslint/types@^8.36.0":
version "8.36.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.36.0.tgz#d3d184adc2899e2912c13b17c1590486ef37c7ac"
integrity sha512-xGms6l5cTJKQPZOKM75Dl9yBfNdGeLRsIyufewnxT4vZTrjC0ImQT4fj8QmtJK84F58uSh5HVBSANwcfiXxABQ==
"@typescript-eslint/typescript-estree@5.62.0":
version "5.62.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz#7d17794b77fabcac615d6a48fb143330d962eb9b"
@@ -2594,20 +2615,6 @@
semver "^7.3.7"
tsutils "^3.21.0"
"@typescript-eslint/typescript-estree@7.18.0":
version "7.18.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz#b5868d486c51ce8f312309ba79bdb9f331b37931"
integrity sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==
dependencies:
"@typescript-eslint/types" "7.18.0"
"@typescript-eslint/visitor-keys" "7.18.0"
debug "^4.3.4"
globby "^11.1.0"
is-glob "^4.0.3"
minimatch "^9.0.4"
semver "^7.6.0"
ts-api-utils "^1.3.0"
"@typescript-eslint/typescript-estree@7.2.0":
version "7.2.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.2.0.tgz#5beda2876c4137f8440c5a84b4f0370828682556"
@@ -2622,15 +2629,31 @@
semver "^7.5.4"
ts-api-utils "^1.0.1"
"@typescript-eslint/utils@7.18.0":
version "7.18.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.18.0.tgz#bca01cde77f95fc6a8d5b0dbcbfb3d6ca4be451f"
integrity sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==
"@typescript-eslint/typescript-estree@8.36.0":
version "8.36.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.36.0.tgz#344857fa79f71715369554a3cbb6b4ff8695a7bc"
integrity sha512-JaS8bDVrfVJX4av0jLpe4ye0BpAaUW7+tnS4Y4ETa3q7NoZgzYbN9zDQTJ8kPb5fQ4n0hliAt9tA4Pfs2zA2Hg==
dependencies:
"@eslint-community/eslint-utils" "^4.4.0"
"@typescript-eslint/scope-manager" "7.18.0"
"@typescript-eslint/types" "7.18.0"
"@typescript-eslint/typescript-estree" "7.18.0"
"@typescript-eslint/project-service" "8.36.0"
"@typescript-eslint/tsconfig-utils" "8.36.0"
"@typescript-eslint/types" "8.36.0"
"@typescript-eslint/visitor-keys" "8.36.0"
debug "^4.3.4"
fast-glob "^3.3.2"
is-glob "^4.0.3"
minimatch "^9.0.4"
semver "^7.6.0"
ts-api-utils "^2.1.0"
"@typescript-eslint/utils@8.36.0":
version "8.36.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.36.0.tgz#2c9af5292f14e0aa4b0e9c7ac0406afafb299acf"
integrity sha512-VOqmHu42aEMT+P2qYjylw6zP/3E/HvptRwdn/PZxyV27KhZg2IOszXod4NcXisWzPAGSS4trE/g4moNj6XmH2g==
dependencies:
"@eslint-community/eslint-utils" "^4.7.0"
"@typescript-eslint/scope-manager" "8.36.0"
"@typescript-eslint/types" "8.36.0"
"@typescript-eslint/typescript-estree" "8.36.0"
"@typescript-eslint/utils@^5.10.0", "@typescript-eslint/utils@^5.47.1":
version "5.62.0"
@@ -2654,14 +2677,6 @@
"@typescript-eslint/types" "5.62.0"
eslint-visitor-keys "^3.3.0"
"@typescript-eslint/visitor-keys@7.18.0":
version "7.18.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz#0564629b6124d67607378d0f0332a0495b25e7d7"
integrity sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==
dependencies:
"@typescript-eslint/types" "7.18.0"
eslint-visitor-keys "^3.4.3"
"@typescript-eslint/visitor-keys@7.2.0":
version "7.2.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.2.0.tgz#5035f177752538a5750cca1af6044b633610bf9e"
@@ -2670,6 +2685,14 @@
"@typescript-eslint/types" "7.2.0"
eslint-visitor-keys "^3.4.1"
"@typescript-eslint/visitor-keys@8.36.0":
version "8.36.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.36.0.tgz#7dc6ba4dd037979eb3a3bdd2093aa3604bb73674"
integrity sha512-vZrhV2lRPWDuGoxcmrzRZyxAggPL+qp3WzUrlZD+slFueDiYHxeBa34dUXPuC0RmGKzl4lS5kFJYvKCq9cnNDA==
dependencies:
"@typescript-eslint/types" "8.36.0"
eslint-visitor-keys "^4.2.1"
"@ungap/structured-clone@^1.2.0":
version "1.2.0"
resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406"
@@ -4501,6 +4524,11 @@ eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800"
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
eslint-visitor-keys@^4.2.1:
version "4.2.1"
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz#4cfea60fe7dd0ad8e816e1ed026c1d5251b512c1"
integrity sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==
eslint@^8.19.0, eslint@^8.57.0:
version "8.57.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.0.tgz#c786a6fd0e0b68941aaf624596fb987089195668"
@@ -5359,11 +5387,16 @@ ieee754@^1.1.13:
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
ignore@^5.0.5, ignore@^5.2.0, ignore@^5.2.4, ignore@^5.3.1:
ignore@^5.0.5, ignore@^5.2.0, ignore@^5.2.4:
version "5.3.2"
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5"
integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==
ignore@^7.0.0:
version "7.0.5"
resolved "https://registry.yarnpkg.com/ignore/-/ignore-7.0.5.tgz#4cb5f6cd7d4c7ab0365738c7aea888baa6d7efd9"
integrity sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==
image-size@^1.0.2:
version "1.1.1"
resolved "https://registry.yarnpkg.com/image-size/-/image-size-1.1.1.tgz#ddd67d4dc340e52ac29ce5f546a09f4e29e840ac"
@@ -9143,11 +9176,16 @@ trim-repeated@^1.0.0:
dependencies:
escape-string-regexp "^1.0.2"
ts-api-utils@^1.0.1, ts-api-utils@^1.3.0:
ts-api-utils@^1.0.1:
version "1.3.0"
resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1"
integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==
ts-api-utils@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-2.1.0.tgz#595f7094e46eed364c13fd23e75f9513d29baf91"
integrity sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==
tslib@^1.8.1, tslib@^1.9.0:
version "1.14.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"