Compare commits

...
Author SHA1 Message Date
React Native Bot 81737c2b99 Release 0.76.2
#publish-packages-to-npm&latest
2024-11-14 16:50:52 +00:00
Alex Hunt ff1261e7dc [0.76] Skip hermes-parser under Babel for non-Flow JS code (#47569) 2024-11-13 12:12:23 +00:00
Riccardo Cipolleschi 1e659dc44e Fix Typo and skip generation of app-specific component registration (#47547)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47547

In [#47176](https://github.com/facebook/react-native/pull/47176) we disabled the generation of the component registration for app specific components as it was creating a circular dependency between the app and React Native.

However, we made a couple of typos that make it not work as expected and users picked up those typos soon.

This change fixes them for good.

## Changelog
[iOS][Fixed] - Properly stop generating component registration for components defined in app.

Reviewed By: blakef

Differential Revision: D65750433

fbshipit-source-id: 1a879c5be014905558b9fd05e6f16ac36b784ed6
2024-11-12 19:14:32 +00:00
Jakub Piasecki 9f65442f2d Fix timers in headless tasks on bridgeless mode (#47496)
Summary:
Fixes https://github.com/facebook/react-native/issues/47495

`JavaTimerManager` is being registered to receive headless tasks events in the [`TimingModule`](https://github.com/facebook/react-native/blob/0ee963ea65bcc88122044d51027511e611bde584/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/core/TimingModule.kt#L28-L29). This module is not used on bridgeless: [1](https://github.com/facebook/react-native/blob/0ee963ea65bcc88122044d51027511e611bde584/packages/react-native/Libraries/Core/setUpTimers.js#L44-L61), [2](https://github.com/facebook/react-native/blob/0ee963ea65bcc88122044d51027511e611bde584/packages/react-native/Libraries/Core/setUpTimers.js#L123-L132) and since it's loaded lazily, the event listener is never registered.

This PR moves registration to the constructor of `JavaTimerManager` and deregistration to the `onInstanceDestroy` method. This way the event listener is always registered when an instance of the timer manager exists.

## Changelog:

[ANDROID] [FIXED] - Fix timers in headless tasks on bridgeless mode

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

Test Plan: See the reproducer from the issue

Reviewed By: javache

Differential Revision: D65615601

Pulled By: alanleedev

fbshipit-source-id: 6e1d36f8783e813065f79730a928b99c3e385718
2024-11-12 19:14:18 +00:00
Nicola Corti c4fd80f414 Use absolute path when compiling appmodules.so sources (#47379)
Summary:
Fixes https://github.com/facebook/react-native/issues/47352

This fixes a bug when the user is providing its own CMakeLists.txt file say because they want to compile more C++ code than we actually provide.

Previously the `*.cpp` will evalute file in the current directory, meaning that the app's default `OnLoad.cpp` file would be ignored.

## Changelog:

[ANDROID] [FIXED] - Use absolute path when compiling appmodules.so sources

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

Test Plan:
Tested against the reproducer provided in:
- Use absolute path when compiling appmodules.so sources

Reviewed By: cipolleschi

Differential Revision: D65428676

Pulled By: cortinico

fbshipit-source-id: 7f3e4d470da0fffc5191c1a2c7e8fec517fee496
2024-11-12 19:13:59 +00:00
Nicola Corti e9fc092156 Properly handle paths with spaces in autolinking (#47388)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47388

Fixes https://github.com/facebook/react-native/issues/47364
Fixes https://github.com/facebook/react-native/issues/47377
Fixes https://github.com/facebook/react-native/issues/37124

We're having problems is a path contains a space ' ' because when autolinking,
the `add_subdirectory()` function of CMake consider the path with space as 2 parameters.

This fixes it by properly quoting the path.

Changelog:
[Android] [Fixed] - Properly handle paths with spaces in autolinking

Reviewed By: cipolleschi

Differential Revision: D65434413

fbshipit-source-id: b9147482f98f7e222405cc8d9e6f3c17a5f4ed02
2024-11-12 19:13:31 +00:00
Alan Lee e8c4faaf08 fix Modal content being cut off when Android Activity is edge-to-edge (#47339)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47339

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

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

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

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

Reviewed By: cortinico

Differential Revision: D65280014

fbshipit-source-id: 616ff739be55635f1295ef3bf8b997a27ef769ae
2024-11-12 19:12:32 +00:00
Nick Gerleman fbe38bb2a3 Fix missing emitter attributes on iOS TextInput when controlled component value specified using value instead of children (#47269)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47269

There were [reports](https://github.com/reactwg/react-native-releases/issues/595) that patching in the fixes for iOS controlled input did not work as expected.

I think tracked this down to a difference in how I tested, where the controlled component I used passed value as a child of the `TextInput`, instead of via `value`. Passing via `value` triggers a secondary bug, where we don't correctly pass a reference to correct ShadowView when creating attributedstring, specifically in the iOS TextInputShadowNode impl.

We previously passed nothing for the ShadowView (only the first two struct fields). This was exposed in D52589303 which enabled `-Wextra`, but there, I went with same behavior of passing empty ShadowView, instead of the correct behavior (like Android impl) of passing a ShadowView of the current ShadowNode.

After fixing this, we now correctly create event emitters in the passed attributedstring, which matches expectations for pargraph-level eventemitter now in typing attributes. We don't seem actually use this on iOS for TextInput right now (just Text), but this is likely the right foundation for events regardless.

Changelog:
[iOS][Fixed] - Fix missing emitter attributes on iOS TextInput when controlled component value specified using `value` instead of `children`

Reviewed By: cipolleschi

Differential Revision: D65108163

fbshipit-source-id: 499fe28439fabd2579eca6ded7fd13fd8ea2e43e
2024-11-12 19:11:55 +00:00
Nick Gerleman 40093d96d1 Fix cursor moving while typing quickly and autocorrection triggered in controlled single line TextInput on iOS (New Arch) (#46970)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/46970

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

This one is a bit of a doozy...

During auto-correct in UITextField (used for single line TextInput) iOS will mutate the buffer in two parts, non-atomically. After the first part, after iOS triggers `textFieldDidChange`, selection is in the wrong position. If we set full new AttributedText at this point, we propagate the incorrect cursor position, and it is never restored.

In the common case, where we are not mutating text in the controlled component, we shouldn't need to be setting AttributedString in the first place, and we do have an equality comparison there currently. But it is defeated because attributes are not identical. There are a few sources of that:
1. NSParagraphStyle is present in backing input, but not the AttributedString we are setting.
2. Backing text has an NSShadow with no color (does not render) not in the AttributedText
3. Event emitter attributes change on each update, and new text does not inherit the attributes.

The first two are part of the backing input `typingAttributes`, even if we set a dictionary without them. To solve for them, we make attribute comparison insensitive to the attribute values in a default initialized control. There is code around here fully falling back to attribute insensitive comparison, which we would ideally fix to instead role into this "effective" attribute comparison.

The event emitter attributes being misaligned is a real problem. We fix in a couple ways.
1. We treat the attribute values as equal if the backing event emitter is the same
2. We set paragraph level event emitter as a default attribute so the first typed character receives it

After these fixes, scenario in https://github.com/facebook/react-native-website/pull/4247 no longer repros in new arch. Typing in debug build also subjectively seems faster? (we are not doing second invalidation of the control on every keypress).

Changes which do mutate content may be susceptible to the same style of issue, though on web/`react-dom` in Chrome, this seems to not try to preserve selection at all if the selection is uncontrolled, so this seems like less of an issue.

I haven't yet looked at old arch, but my guess is we have similar issues there, and could be fixed in similar ways (though, we've been trying to avoid changing it as much as possible, and 0.76+ has new arch as default, so not sure if worth fixing in old impl as well if this is very long running issue).

Changelog:
[iOS][Fixed] - Fix cursor moving in iOS controlled single line TextInput on Autocorrection (New Arch)

Reviewed By: javache, philIip

Differential Revision: D64121570

fbshipit-source-id: 2b3bd8a3002c33b68af60ffabeffe01e25c7ccfe
2024-11-12 19:11:55 +00:00
Riccardo Cipolleschi 6f9ddd8f89 Add yoga to app search paths (#47195)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47195

When a user wants to create a Fabric Component i their app (not in a separate library) the app fails to build because:
- The custom component has to inherit from `RCTViewComponentView`
- `RCTViewComponentView` imports `ViewProps.h`
- `ViewProps.h` imports `HostPlatformViewProps.h`
- `HostPlatformViewProps.h` imports `BaseViewProps.h`
- `BaseViewProps.h` imports `YogaStylableProps.h`

which is a Yoga private header and the App has not visibility over it.

It is also not possible to fix this issue with forward declaring the `YogaStylableProps`, because `BaseViewProps` inherit from the yoga's props, so the compiler needs the full declaration of `YogaStylableProps` to work

This needs to be picked in 0.76

## Changelog
[iOS][Fixed] - Give apps access to Yoga headers

Reviewed By: blakef

Differential Revision: D64925222

fbshipit-source-id: e724076bbfb0a678948340dfab2ce609e6509533
2024-11-12 19:00:04 +00:00
Nick Gerleman 3ce4b80e6f Include existing attributes in newly typed text (#47018)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47018

This change makes it so that newly typed text in a TextInput will include the existing attributes present based on cursor position. E.g. if you type after an inner fragment with blue text, the next character will be blue (or, an event emitter specific to an inner fragment will also be expanded). This is a behavior change for the (admittedly rare) case of uncontrolled TextInput with initially present children AttributedText, but more often effect controlled components, before state update (we are after, less likely to need to reset AttributedString because of mismatch).

Originally included this in D64121570, but it's not needed to fix the common case since we include paragraph-level event emitter as part of default attributes, and has some of its own risk, so I decided it is better separate.

Changelog:
[iOS][Changed] - Include existing attributes in newly typed text

Reviewed By: cipolleschi

Differential Revision: D64352310

fbshipit-source-id: 90ef8c49f50186eadf777e81cf6af57e1aada207
2024-11-12 18:58:46 +00:00
Riccardo Cipolleschi a09df751eb Add TS types for Codegen (#46484)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/46484

We recently realized that we don't have TS types for Codegen.
These are needed to let our users use these types when writing Specs in TS

## Changelog
[General][Added] - Add CodegenTypes for TS

Reviewed By: christophpurrer

Differential Revision: D62644516

fbshipit-source-id: 92bb7e8998d31806f6eb63319fb6d406fcd65ad8
2024-11-12 18:58:36 +00:00
Blake Friedman 94d4bfd7c8 [LOCAL] Update Hermes
Adds fix: facebook/hermes@c2c4ee7
2024-11-12 18:57:54 +00:00
Riccardo Cipolleschi a35852f976 [LOCAL] Fix lint process 2024-10-31 11:20:25 +00:00
Szymon Rybczak 51b98c24bd Bump CLI to 15.0.1 (#47328) 2024-10-31 10:25:02 +00:00
Blake FriedmanandRick Hanlon bbe5e72768 fix logbox error stack (#47303)
* Re-enable integration tests (#46639)

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

These tests were skipped when we were switching to component stacks, which also hid a bug later in the stack. Re-enable them.

Changelog: [Internal]

Reviewed By: javache

Differential Revision: D63349616

fbshipit-source-id: ccde7d5bb3fcd9a27adf4af2068a160f02f7432a

* Add integration tests for console errors + ExceptionManager (#46636)

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

Adds more integration tests for LogBox (currently incorrect, but fixed in a later diff).

Changelog: [Internal]

Reviewed By: javache

Differential Revision: D63349614

fbshipit-source-id: 8f5c6545b48a1ed18aea08d4ecbecd7a6b9fa05a

* Refactor LogBox tests to spies (#46638)

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

This is annoying, but in the next diff that fixes a bug I need to test using the default warning filter instead of a mock (really, all this mocking is terrible, idk why I did it this way).

Unfortunately, in Jest you can't just reset mocks from `jest.mock`, `restoreMocks` only resets spies and not mocks (wild right).

So in this diff I converted all the `jest.mock` calls to `jest.spyOn`. I also corrected some of the mocks that require `monitorEvent: 'warning',` like the warning filter sets.

I also added a test that works without the fix.

Changelog: [Internal]

Reviewed By: javache

Differential Revision: D63349615

fbshipit-source-id: 4f2a5a8800c8fe1a10e3613d3c2d0ed02fca773e

* Fix errors with component stacks reported as warnings (#46637)

Summary:
Ok so this is a doozy.

## Overview
There was a report that some console.error calls were being shown as warnings in LogBox but as console.error in the console. The only time we should downlevel an error to a warning is if the custom warning filter says so (which is used for some noisy legacy warning filter warnings internally).

However, in when I switched from using the `Warning: ` prefix, to using the presence of component stacks, I subtly missed the default warning filter case.

In the internal warning filter, the `monitorEvent` is always set to something other than `unknown` and if it's set to `warning_unhandled` then `suppressDialog_LEGACY` is always false.

However, the default values for the warning filter are that `monitorEvent = 'unknown'` and `suppressDialog_LEGACY = true`. In this case, we would downlevel the error to a warning.

## What's the fix?
Change the default settings for the warning filter.

## What's the root cause?

Bad configuration combinations in a fragile system that needs cleaned up, and really really bad testing practices with excessive mocking and snapshot testing (I can say that, I wrote the tests)

## How could it have been caught?
It was, but I turned off the integration tests while landing the component stack changes because of mismatches between flags internally and in OSS, and never turned them back on.

Changelog: [General] [Fixed] - Fix logbox reporting React errors as Warnings

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

Reviewed By: huntie

Differential Revision: D63349613

Pulled By: rickhanlonii

fbshipit-source-id: 32e3fa4e2f2077114a6e9f4feac73673973ab50c

* [LOCAL] using older version of React Dev Tools

- Older version has old URL, updated tests
- Comments on test don't match what's being tested.  Updated.

---------

Co-authored-by: Rick Hanlon <rickhanlonii@meta.com>
2024-10-31 10:24:52 +00:00
Riccardo Cipolleschi dac6d508af [RN][JS] Fix setUpErrorHandling to show early JS errors (#47287) 2024-10-31 10:24:33 +00:00
Tommy Nguyen 0def73d1a6 fix: fix semver not being found in pnpm setups (#47310) 2024-10-31 10:24:21 +00:00
Blake Friedman 4fc2c8fd1f Update Podfile.lock
Changelog: [Internal]
2024-10-29 15:21:39 +00:00
React Native Bot b048659ceb Release 0.76.1
#publish-packages-to-npm&latest
2024-10-29 10:55:33 +00:00
Blake Friedman 201b517de0 [CI]: verify template is published method
This step called an old reference, this function identifier was updated.

Changelog: [Internal]
2024-10-28 14:35:29 +00:00
Robert Pasiński 980f4b42ca fix: AppRegistry not callable from Native in bridgeless (#46480)
Summary:
AppRegistry was not treated as a Callable Module in bridgeless mode. This is breaking headless tasks on Android.

Fixes:

 - https://github.com/facebook/react-native/issues/46050

## Changelog:

[ANDROID] [FIXED] - Made AppRegistry callable from Native code in Bridgeless (fixes headless tasks)

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

Test Plan: Used repro from linked issue

Reviewed By: javache

Differential Revision: D62637486

Pulled By: cortinico

fbshipit-source-id: 756527003ac6d712e76c02c188e280d15c010068
2024-10-28 14:23:31 +00:00
zhongwuzw 621d4ee298 Fixes regression of RCTWindowFrameDidChangeNotification not fired (#47236)
Summary:
Fixes https://github.com/facebook/react-native/issues/47234. regression from https://github.com/facebook/react-native/commit/391680fe844aad887e497912378c699aed13464b#diff-b7fda5d350ac535115fa683faa7317b43aa11f3448f95266ef9ff051c3753a6fL63

bypass-github-export-checks

## Changelog:

[IOS] [FIXED] - Fixes regression of RCTWindowFrameDidChangeNotification not fired

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

Test Plan: Demo in https://github.com/facebook/react-native/issues/47234.

Reviewed By: blakef

Differential Revision: D65058105

Pulled By: cipolleschi

fbshipit-source-id: 0e286182ed93f289cb853710e2e00801ef2d4f73
2024-10-28 14:20:09 +00:00
Riccardo Cipolleschi e8776240b4 Pin Xcodeproj to < 1.26.0 (#47237)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47237

The Xcodeproj gem has been released yesterday to version 1.26.0 and it broke the CI pipeline of react native.

This should fix the issue

## Changelog
[Internal] - Pin Xcodeproj gem to 1.26.0

Reviewed By: blakef

Differential Revision: D65057797

fbshipit-source-id: f4035a1d3c75dd4140eb1646ab2aa0ccb08fb16b
2024-10-28 14:20:04 +00:00
Joe Vilches defc0c8c21 Fix animating background colors in View (#47101)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47101

See https://github.com/facebook/react-native/issues/47011

borders do not have this problem because they call `removeAllAnimations` on the layer after changing it, which is what I am doing here

Changelog: [iOS] [fixed] - Fixed bug where background colors would sometimes animate when changing on Views

Reviewed By: cipolleschi

Differential Revision: D64493968

fbshipit-source-id: cf81549f21b124b67c6e7647c6ae827bfe80a9cf
2024-10-28 14:19:54 +00:00
Sunny Luo e56bd89eff Add jsBundleFile to DefaultReactNativeHost.kt (#47188)
Summary:
The JsBundleFilePath has been ignored when converting DefaultReactNativeHost to ReactHost

Changelog:
[Internal] [Changed] - Add jsBundleFile to DefaultReactNativeHost.kt

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

Reviewed By: javache

Differential Revision: D64914149

Pulled By: cortinico

fbshipit-source-id: d437ca81df5a170e0c5f01a22ccda83f43a09dd2
2024-10-28 14:19:49 +00:00
Riccardo Cipolleschi 807500a63e Exclude generation of app-defined components from RCTThirdPartyFabricComponentsProvider (#47176)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47176

While writing the guide for the New Architecture, we realized that we need to exclude the generation of the Cls function in the RCTThirdPartyFabricComponentsProvider for components defined in the app.

This is needed because a component that is defined in the app will have those function defined in the app project. However, the RCTThirdPartyFabricComponentsProvider is generated in Fabric, inside the Pods project.

The pod project needs to build in isolation from the app and cocoapods then link the app to the pods project. But the compilation of the pods project fails if one of the symbol needed by the pods lives in the app.

By disabling the generation of that function in th RCTThirdPartyFabricComponentsProvider, we can successfully build the app.

The downside is that the user needs to register the component manually, but this is not an issue because if they are writing a component in the app space, they have all the information tomanually register it in the AppDelegate

## Changelog
[iOS][Fixed] - Do not generate the ComponentCls function in the RCTThirdPartyFabricComponentsProvider for components deined in the app.

Reviewed By: cortinico, blakef

Differential Revision: D64739896

fbshipit-source-id: 0eca818ea0198532a611377d14a3ff4c95cb5fe3
2024-10-28 14:19:41 +00:00
Blake Friedman bea4535246 Let .xcode.env.local NODE_BINARY handle path spaces
Summary:
For users who may have node installed in a path with a space, this requires escaping.  For example:

```
NODE_BINARY=/Users/blakef/Library/Application Support/fnm/node-versions/v20.12.0/installation/bin/node
```

Needs to be:

```
NODE_BINARY=/Users/blakef/Library/Application\ Support/fnm/node-versions/v20.12.0/installation/bin/node
```

# Changelog
[iOS][Fixed] Generated NODE_BINARY in .xcode.env.local now supports paths with a space

Reviewed By: cipolleschi

Differential Revision: D64080118

fbshipit-source-id: 1045473e4fd284fc570fa538984618630be1af6d
2024-10-28 14:19:34 +00:00
Blake Friedman 699a94d938 Update Podfile.lock
Changelog: [Internal]
2024-10-23 13:58:04 -07:00
React Native Bot 2e10ba945f Release 0.76.0
#publish-packages-to-npm&latest
2024-10-23 16:09:59 +00:00
Riccardo Cipolleschi 007a8e12b8 [LOCAL] Fix template publishing (#47116) 2024-10-18 11:13:11 +01:00
Riccardo Cipolleschi 1be8c51173 [LOCAL] Bump Podfile.lock 2024-10-17 19:06:26 +01:00
React Native Bot 9f9e1a41ca Release 0.76.0-rc.6
#publish-packages-to-npm&next
2024-10-17 15:57:42 +00:00
Riccardo Cipolleschi c967deaa2d Revert "Fix Android AlertFragment Title Accessibility (#45395)"
This reverts commit 80a3ed7d0c.
2024-10-17 16:08:03 +01:00
Nicola Corti 55671c00e5 [0.76] Undo breaking change on UIManager eventDispatcher accessor (#47090)
Summary:

Whe migrating this interface to Kotlin we've subtly introduced a breaking change which is causing a lot of breakages in the ecosystem.

This is forcing users to do:
```
// Before
reactContext.getNativeModule(UIManagerModule::class.java)!!.eventDispatcher
// After
reactContext.getNativeModule(UIManagerModule::class.java)!!.getEventDispatcher()
```

This reverts this breaking change.

Plus the method had a generic parameters which was completely unnecessary so I'm removing it.


Changelog:
[Android] [Fixed] - Undo breaking change on UIManager eventDispatcher accessor

Reviewed By: cipolleschi

Differential Revision: D64533594
2024-10-17 14:40:04 +01:00
Nicola Corti ce1620616c Undo breaking change on ViewManagerDelegate.kt String params (#47086)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47086

When we migrated `ViewManagerDelegate` to Kotlin, we convered his string params to be `String` (rather than `String?`).

Existing implementation of this interface in OSS written in Kotlin were using `String?` due to this interface being in Java (and not being Nullsafe annotated).
Therefore now changing this interface from `String?` to `String` is a breaking change for them.

Affected libraries are:
https://github.com/search?q=%22fun+receiveCommand%28%22+%22commandId%3A+String%3F%22+%22args%3A+ReadableArray%22+language%3Akotlin+-org%3Afacebook+-is%3Afork&type=code&p=4

This prevents the breaking change and should be included in 0.76.

Changelog:
[Android] [Fixed] - Undo breaking change on ViewManagerDelegate.kt String params

Reviewed By: cipolleschi

Differential Revision: D64532446

fbshipit-source-id: aac286554ad0e35f557160f900bcbad1acc5930d
2024-10-17 14:38:33 +01:00
Blake Friedman ab0d812cc6 Update Podfile.lock
Changelog: [Internal]
2024-10-15 23:49:56 +01:00
React Native Bot 5e2f3e018c Release 0.76.0-rc.5
#publish-packages-to-npm&next
2024-10-15 17:25:47 +00:00
Blake Friedman 45ae0b44d5 Replace sh scripts with tested JS scripts to release template (#46363)
Summary:
The previous scripts to trigger the react-native-communty/template
release workflow has not been working. This is a rewrite is js, along
with some testing to make this more robust.

I've have a PR to combine the publish and tag steps in the template publication: https://github.com/react-native-community/template/pull/65, this takes advantage of that change.

Changelog: [Internal]

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

Test Plan:
1. Unit tests
2. Once the infrastructure lands in the `react-native-community/template` workflow, we can trigger a dry run.

## TODO:
- ~~Still needs to be used in the GH release workflow.~~
- ~~Template release workflow needs to land the dry_run input change.~~

## Changelog: [Internal]

Reviewed By: cipolleschi

Differential Revision: D62296008

Pulled By: blakef

fbshipit-source-id: 217326c44b1d820e36a1d847cf9ad24d228087c1
2024-10-15 14:47:59 +01:00
Alex Hunt 02b879b1e2 [0.76] Fix server.end() usage following Metro bump (#47023) 2024-10-15 11:39:02 +01:00
Blake Friedman 788dd2e681 [LOCAL] Fix cherry-pick error
Looks like #46787 wasn't picked correctly.
2024-10-15 11:26:52 +01:00
Rob Hogan 3f8d1fa286 [0.76] Update Metro to "^0.81.0" (#47013) 2024-10-15 10:13:05 +01:00
Gabriel Donadel 066128321d Make PackagerConnectionSettings class open again (#47005)
Summary:
When migrating `PackagerConnectionSettings` from Java to Kotlin in https://github.com/facebook/react-native/pull/45800 the new class ended up being declared as final, causing a breaking change in 0.76.

We should add the `open` directive to `PackagerConnectionSettings.kt` to restore the old behavior. That would be crucial for the `expo-dev-client` package, given that Expo needs to be able to extend this class in order to overwrite the `debugServerHost` value.

## Changelog:

[ANDROID] [FIXED] - Make PackagerConnectionSettings class open again

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

Test Plan: Run RNTester on Android

Reviewed By: huntie

Differential Revision: D64323645

Pulled By: cortinico

fbshipit-source-id: 6870a3dee929ba664e4c402f321f84af7704f892
2024-10-15 10:11:48 +01:00
Nicola Corti 60a2706e97 Gradle to 8.10.2 (#46656)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/46656

This contains the fix for:
- https://github.com/gradle/gradle/issues/30472

Changelog:
[Internal] [Changed] - Gradle to 8.10.2

Reviewed By: tdn120

Differential Revision: D63457979

fbshipit-source-id: 1439a9ce198c1df0dafa8f5088c079c3fb3d1543
2024-10-15 10:11:32 +01:00
Thibault Malbranche d91a12bc8b fix: override podspecs dependencies c++ version (#46888)
Summary:
Some dependencies would override C++ version like [this](https://github.com/mrousavy/react-native-vision-camera/blob/83abb0832a22b6b080f8412ed17b0992532b0eb2/VisionCamera.podspec#L36).

We force it back to be the current version set by react-native so that we are sure projects are using the correct version

[IOS] [FIXED] - Enforce we use the correct C++ version for all, even if dependency tries to set it

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

Test Plan:
This can be test via
https://github.com/Titozzz/cpp17bug

Reviewed By: blakef

Differential Revision: D64042099

Pulled By: cipolleschi

fbshipit-source-id: c36dda0a718e52e19d53c3e9d895315141cb040c
2024-10-15 10:10:41 +01:00
Alan Lee 111d013c03 fix crash for Modal not attached to window manager (2) (#46764)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/46764

This is a patched fix to earlier attempt (D63700769) and resolving crash due to`java.lang.IllegalArgumentException: View=DecorView@b9f88af[AdsManagerActivity] not attached to window manager`.
- removing ` !dialogWindow.isActive` check as it is always true resulting in always doing early return causing other bugs
- adding try/ catch instead so the code can still run but can catch the known exception without crashing

Changelog:
[Android][Fixed] - Fix crash for Modal not attached to window manager

Reviewed By: mdvacca

Differential Revision: D63712422

fbshipit-source-id: 85fb6df340eb1139f954c92b5f1daf0dc41671d2
2024-10-15 10:10:04 +01:00
Riccardo Cipolleschi 7e14ec5177 Exclude dSYM from the archive (#46472)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/46472

Currently, we are building the Debug symbols (dSYM) for hermes dSYM but we are not shipping them with the xcframework.
This is correct, because Debug symbols can increase the size of Hermes thus enalrging the iOS IPA and increasing the download time when installing pods.

We distribute the dSYM separatedly, in case users needs to symbolicate Hermes stack traces.

However the path to the dSYM still appears in the Info.plist of the universal XCFramework and this can cause issues when submitting an app to apple.

This change should remove those lines from the universal framework.

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

[Internal] - Remove dSYM path from Info.plist

Reviewed By: cortinico

Differential Revision: D62603425

fbshipit-source-id: 038ec3d6b056a3d6f5585c8125d0430f56f11bb9
2024-10-15 10:08:57 +01:00
89 changed files with 1647 additions and 827 deletions
@@ -0,0 +1,158 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
const {
publishTemplate,
verifyPublishedTemplate,
} = require('../publishTemplate');
const mockRun = jest.fn();
const mockSleep = jest.fn();
const mockGetNpmPackageInfo = jest.fn();
const silence = () => {};
jest.mock('../utils.js', () => ({
log: silence,
run: mockRun,
sleep: mockSleep,
getNpmPackageInfo: mockGetNpmPackageInfo,
}));
const getMockGithub = () => ({
rest: {
actions: {
createWorkflowDispatch: jest.fn(),
},
},
});
describe('#publishTemplate', () => {
beforeEach(jest.clearAllMocks);
it('checks commits for magic #publish-package-to-npm&latest string and sets latest', async () => {
mockRun.mockReturnValueOnce(`
The commit message
#publish-packages-to-npm&latest`);
const github = getMockGithub();
await publishTemplate(github, '0.76.0', true);
expect(github.rest.actions.createWorkflowDispatch).toHaveBeenCalledWith({
owner: 'react-native-community',
repo: 'template',
workflow_id: 'release.yaml',
ref: '0.76-stable',
inputs: {
dry_run: true,
is_latest_on_npm: true,
version: '0.76.0',
},
});
});
it('pubished as is_latest_on_npm = false if missing magic string', async () => {
mockRun.mockReturnValueOnce(`
The commit message without magic
`);
const github = getMockGithub();
await publishTemplate(github, '0.76.0', false);
expect(github.rest.actions.createWorkflowDispatch).toHaveBeenCalledWith({
owner: 'react-native-community',
repo: 'template',
workflow_id: 'release.yaml',
ref: '0.76-stable',
inputs: {
dry_run: false,
is_latest_on_npm: false,
version: '0.76.0',
},
});
});
});
describe('#verifyPublishedTemplate', () => {
beforeEach(jest.clearAllMocks);
it("waits on npm updating for version and not 'latest'", async () => {
const NOT_LATEST = false;
mockGetNpmPackageInfo
// template@<version>
.mockReturnValueOnce(Promise.reject('mock http/404'))
.mockReturnValueOnce(Promise.resolve());
mockSleep.mockReturnValueOnce(Promise.resolve()).mockImplementation(() => {
throw new Error('Should not be called again!');
});
const version = '0.77.0';
await verifyPublishedTemplate(version, NOT_LATEST);
expect(mockGetNpmPackageInfo).toHaveBeenLastCalledWith(
'@react-native-community/template',
version,
);
});
it('waits on npm updating version and latest tag', async () => {
const IS_LATEST = true;
const version = '0.77.0';
mockGetNpmPackageInfo
// template@latest → unknown tag
.mockReturnValueOnce(Promise.reject('mock http/404'))
// template@latest != version → old tag
.mockReturnValueOnce(Promise.resolve({version: '0.76.5'}))
// template@latest == version → correct tag
.mockReturnValueOnce(Promise.resolve({version}));
mockSleep
.mockReturnValueOnce(Promise.resolve())
.mockReturnValueOnce(Promise.resolve())
.mockImplementation(() => {
throw new Error('Should not be called again!');
});
await verifyPublishedTemplate(version, IS_LATEST);
expect(mockGetNpmPackageInfo).toHaveBeenCalledWith(
'@react-native-community/template',
'latest',
);
});
describe('timeouts', () => {
let mockProcess;
beforeEach(() => {
mockProcess = jest.spyOn(process, 'exit').mockImplementation(code => {
throw new Error(`process.exit(${code}) called!`);
});
});
afterEach(() => mockProcess.mockRestore());
it('will timeout if npm does not update package version after a set number of retries', async () => {
const RETRIES = 2;
mockGetNpmPackageInfo.mockReturnValue(Promise.reject('mock http/404'));
mockSleep.mockReturnValue(Promise.resolve());
await expect(() =>
verifyPublishedTemplate('0.77.0', true, RETRIES),
).rejects.toThrowError('process.exit(1) called!');
expect(mockGetNpmPackageInfo).toHaveBeenCalledTimes(RETRIES);
});
it('will timeout if npm does not update latest tag after a set number of retries', async () => {
const RETRIES = 7;
const IS_LATEST = true;
mockGetNpmPackageInfo.mockReturnValue(
Promise.resolve({version: '0.76.5'}),
);
mockSleep.mockReturnValue(Promise.resolve());
await expect(async () => {
await verifyPublishedTemplate('0.77.0', IS_LATEST, RETRIES);
}).rejects.toThrowError('process.exit(1) called!');
expect(mockGetNpmPackageInfo).toHaveBeenCalledTimes(RETRIES);
});
});
});
+103
View File
@@ -0,0 +1,103 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
const {run, sleep, getNpmPackageInfo, log} = require('./utils.js');
const TAG_AS_LATEST_REGEX = /#publish-packages-to-npm&latest/;
/**
* Should this commit be `latest` on npm?
*/
function isLatest() {
const commitMessage = run('git log -n1 --pretty=%B');
return TAG_AS_LATEST_REGEX.test(commitMessage);
}
module.exports.isLatest = isLatest;
/**
* Create a Github Action to publish the community template matching the released version
* of React Native.
*/
module.exports.publishTemplate = async (github, version, dryRun = true) => {
log(`📤 Get the ${TEMPLATE_NPM_PKG} repo to publish ${version}`);
const is_latest_on_npm = isLatest();
const majorMinor = /^v?(\d+\.\d+)/.exec(version);
if (!majorMinor) {
log(`🔥 can't capture MAJOR.MINOR from '${version}', giving up.`);
process.exit(1);
}
// MAJOR.MINOR-stable
const ref = `${majorMinor[1]}-stable`;
await github.rest.actions.createWorkflowDispatch({
owner: 'react-native-community',
repo: 'template',
workflow_id: 'release.yaml',
ref,
inputs: {
dry_run: dryRun,
is_latest_on_npm,
// 0.75.0-rc.0, note no 'v' prefix
version: version.replace(/^v/, ''),
},
});
};
const SLEEP_S = 10;
const MAX_RETRIES = 3 * 6; // 3 minutes
const TEMPLATE_NPM_PKG = '@react-native-community/template';
/**
* Will verify that @latest and the @<version> have been published.
*
* NOTE: This will infinitely query each step until successful, make sure the
* calling job has a timeout.
*/
module.exports.verifyPublishedTemplate = async (
version,
latest = false,
retries = MAX_RETRIES,
) => {
log(`🔍 Is ${TEMPLATE_NPM_PKG}@${version} on npm?`);
let count = retries;
while (count-- > 0) {
try {
const json = await getNpmPackageInfo(
TEMPLATE_NPM_PKG,
latest ? 'latest' : version,
);
log(`🎉 Found ${TEMPLATE_NPM_PKG}@${version} on npm`);
if (!latest) {
return;
}
if (json.version === version) {
log(`🎉 ${TEMPLATE_NPM_PKG}@latest → ${version} on npm`);
return;
}
log(
`🐌 ${TEMPLATE_NPM_PKG}@latest → ${pkg.version} on npm and not ${version} as expected, retrying...`,
);
} catch (e) {
log(`Nope, fetch failed: ${e.message}`);
}
await sleep(SLEEP_S);
}
let msg = `🚨 Timed out when trying to verify ${TEMPLATE_NPM_PKG}@${version} on npm`;
if (latest) {
msg += ' and latest tag points to this version.';
}
log(msg);
process.exit(1);
};
+29
View File
@@ -0,0 +1,29 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
const {execSync} = require('child_process');
function run(cmd) {
return execSync(cmd, 'utf8').toString().trim();
}
module.exports.run = run;
async function sleep(seconds) {
return new Promise(resolve => setTimeout(resolve, seconds * 1000));
}
module.exports.sleep = sleep;
async function getNpmPackageInfo(pkg, versionOrTag) {
return fetch(`https://registry.npmjs.org/${pkg}/${versionOrTag}`).then(resp =>
res.json(),
);
}
module.exports.getNpmPackageInfo = getNpmPackageInfo;
module.exports.log = (...args) => console.log(...args);
+15 -38
View File
@@ -191,46 +191,23 @@ jobs:
gha-npm-token: ${{ env.GHA_NPM_TOKEN }}
- name: Publish @react-native-community/template
id: publish-template-to-npm
shell: bash
run: |
COMMIT_MSG=$(git log -n1 --pretty=%B);
if grep -q '#publish-packages-to-npm&latest' <<< "$COMMIT_MSG"; then
echo "TAG=latest" >> $GITHUB_OUTPUT
IS_LATEST=true
else
IS_LATEST=false
fi
# Go from v0.75.0-rc.4 -> 0.75-stable, which is the template's branching scheme
VERSION=$(grep -oE '\d+\.\d+' <<< "${{ github.ref_name }}" | { read version; echo "$version-stable"; })
echo "VERSION=$VERSION" >> $GITHUB_OUTPUT
curl -L https://api.github.com/repos/react-native-community/template/actions/workflows/release.yaml/dispatches
-H "Accept: application/vnd.github.v3+json" \
-H "Authorization: Bearer $REACT_NATIVE_BOT_GITHUB_TOKEN" \
-d "{\"ref\":\"$VERSION\",\"inputs\":{\"version\":\"${{ github.ref_name }}\",\"is_latest_on_npm\":\"$IS_LATEST\"}}"
uses: actions/github-script@v6
with:
github-token: ${{ secrets.REACT_NATIVE_BOT_GITHUB_TOKEN }}
script: |
const {publishTemplate} = require('./.github/workflow-scripts/publishTemplate.js')
const version = "${{ github.ref_name }}"
const isDryRun = false
await publishTemplate(github, version, isDryRun);
- name: Wait for template to be published
timeout-minutes: 3
env:
VERSION: ${{ steps.publish-template-to-npm.outputs.VERSION }}
TAG: ${{ steps.publish-template-to-npm.outputs.TAG }}
shell: bash
run: |
echo "Waiting until @react-native-community/template is published to npm"
while true; do
if curl -o /dev/null -s -f "https://registry.npmjs.org/@react-native-community/template/$VERSION"; then
echo "Confirm that @react-native-community/template@$VERSION is published on npm"
break
fi
sleep 10
done
while [ "$TAG" == "latest" ]; do
CURRENT=$(curl -s "https://registry.npmjs.org/react-native/latest" | jq -r '.version');
if [ "$CURRENT" == "$VERSION" ]; then
echo "Confirm that @react-native-community/template@latest == $VERSION on npm"
break
fi
sleep 10
done
uses: actions/github-script@v6
with:
github-token: ${{ secrets.REACT_NATIVE_BOT_GITHUB_TOKEN }}
script: |
const {verifyPublishedTemplate, isLatest} = require('./.github/workflow-scripts/publishTemplate.js')
const version = "${{ github.ref_name }}"
await verifyPublishedTemplate(version, isLatest());
- name: Update rn-diff-purge to generate upgrade-support diff
run: |
curl -X POST https://api.github.com/repos/react-native-community/rn-diff-purge/dispatches \
+1
View File
@@ -5,3 +5,4 @@ ruby ">= 2.6.10"
gem 'cocoapods', '~> 1.13', '!= 1.15.0', '!= 1.15.1'
gem 'activesupport', '>= 6.1.7.5', '< 7.1.0'
gem 'xcodeproj', '< 1.26.0'
+1 -1
View File
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
+4 -4
View File
@@ -49,8 +49,8 @@
"@definitelytyped/dtslint": "^0.0.127",
"@jest/create-cache-key-function": "^29.6.3",
"@pkgjs/parseargs": "^0.11.0",
"@react-native/metro-babel-transformer": "0.76.0-rc.4",
"@react-native/metro-config": "0.76.0-rc.4",
"@react-native/metro-babel-transformer": "0.76.2",
"@react-native/metro-config": "0.76.2",
"@tsconfig/node18": "1.0.1",
"@types/react": "^18.2.6",
"@typescript-eslint/parser": "^7.1.1",
@@ -86,8 +86,8 @@
"jest": "^29.6.3",
"jest-junit": "^10.0.0",
"jscodeshift": "^0.14.0",
"metro-babel-register": "^0.81.0-alpha.2",
"metro-memory-fs": "^0.81.0-alpha.2",
"metro-babel-register": "^0.81.0",
"metro-memory-fs": "^0.81.0",
"micromatch": "^4.0.4",
"mkdirp": "^0.5.1",
"node-fetch": "^2.2.0",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/assets-registry",
"version": "0.76.0-rc.4",
"version": "0.76.2",
"description": "Asset support code for React Native.",
"license": "MIT",
"repository": {
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/babel-plugin-codegen",
"version": "0.76.0-rc.4",
"version": "0.76.2",
"description": "Babel plugin to generate native module and view manager code for React Native.",
"license": "MIT",
"repository": {
@@ -25,7 +25,7 @@
"index.js"
],
"dependencies": {
"@react-native/codegen": "0.76.0-rc.4"
"@react-native/codegen": "0.76.2"
},
"devDependencies": {
"@babel/core": "^7.25.2"
+9 -8
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/community-cli-plugin",
"version": "0.76.0-rc.4",
"version": "0.76.2",
"description": "Core CLI commands for React Native",
"keywords": [
"react-native",
@@ -22,19 +22,20 @@
"dist"
],
"dependencies": {
"@react-native/dev-middleware": "0.76.0-rc.4",
"@react-native/metro-babel-transformer": "0.76.0-rc.4",
"@react-native/dev-middleware": "0.76.2",
"@react-native/metro-babel-transformer": "0.76.2",
"chalk": "^4.0.0",
"execa": "^5.1.1",
"invariant": "^2.2.4",
"metro": "^0.81.0-alpha.2",
"metro-config": "^0.81.0-alpha.2",
"metro-core": "^0.81.0-alpha.2",
"metro": "^0.81.0",
"metro-config": "^0.81.0",
"metro-core": "^0.81.0",
"node-fetch": "^2.2.0",
"readline": "^1.3.0"
"readline": "^1.3.0",
"semver": "^7.1.3"
},
"devDependencies": {
"metro-resolver": "^0.81.0-alpha.2"
"metro-resolver": "^0.81.0"
},
"peerDependencies": {
"@react-native-community/cli-server-api": "*"
@@ -140,7 +140,7 @@ async function buildBundleWithConfig(
args.assetCatalogDest,
);
} finally {
server.end();
await server.end();
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/core-cli-utils",
"version": "0.76.0-rc.4",
"version": "0.76.2",
"description": "React Native CLI library for Frameworks to build on",
"license": "MIT",
"main": "./src/index.flow.js",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/debugger-frontend",
"version": "0.76.0-rc.4",
"version": "0.76.2",
"description": "Debugger frontend for React Native based on Chrome DevTools",
"keywords": [
"react-native",
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/dev-middleware",
"version": "0.76.0-rc.4",
"version": "0.76.2",
"description": "Dev server middleware for React Native",
"keywords": [
"react-native",
@@ -23,7 +23,7 @@
],
"dependencies": {
"@isaacs/ttlcache": "^1.4.1",
"@react-native/debugger-frontend": "0.76.0-rc.4",
"@react-native/debugger-frontend": "0.76.2",
"chrome-launcher": "^0.15.2",
"chromium-edge-launcher": "^0.2.0",
"connect": "^3.6.5",
@@ -1,6 +1,6 @@
{
"name": "@react-native/eslint-config",
"version": "0.76.0-rc.4",
"version": "0.76.2",
"description": "ESLint config for React Native",
"license": "MIT",
"repository": {
@@ -22,7 +22,7 @@
"dependencies": {
"@babel/core": "^7.25.2",
"@babel/eslint-parser": "^7.25.1",
"@react-native/eslint-plugin": "0.76.0-rc.4",
"@react-native/eslint-plugin": "0.76.2",
"@typescript-eslint/eslint-plugin": "^7.1.1",
"@typescript-eslint/parser": "^7.1.1",
"eslint-config-prettier": "^8.5.0",
@@ -1,6 +1,6 @@
{
"name": "@react-native/eslint-plugin",
"version": "0.76.0-rc.4",
"version": "0.76.2",
"description": "ESLint rules for @react-native/eslint-config",
"license": "MIT",
"repository": {
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/eslint-plugin-specs",
"version": "0.76.0-rc.4",
"version": "0.76.2",
"description": "ESLint rules to validate NativeModule and Component Specs",
"license": "MIT",
"repository": {
@@ -27,7 +27,7 @@
"@babel/core": "^7.25.2",
"@babel/plugin-transform-flow-strip-types": "^7.25.2",
"@babel/preset-flow": "^7.24.7",
"@react-native/codegen": "0.76.0-rc.4",
"@react-native/codegen": "0.76.2",
"make-dir": "^2.1.0",
"pirates": "^4.0.1",
"source-map-support": "0.5.0"
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/gradle-plugin",
"version": "0.76.0-rc.4",
"version": "0.76.2",
"description": "Gradle Plugin for React Native",
"license": "MIT",
"repository": {
@@ -59,15 +59,15 @@ abstract class GenerateAutolinkingNewArchitecturesFileTask : DefaultTask() {
val cxxModuleCMakeListsPath = dep.cxxModuleCMakeListsPath
if (libraryName != null && cmakeListsPath != null) {
// If user provided a custom cmakeListsPath, let's honor it.
val nativeFolderPath = cmakeListsPath.replace("CMakeLists.txt", "")
val nativeFolderPath = sanitizeCmakeListsPath(cmakeListsPath)
addDirectoryString +=
"add_subdirectory($nativeFolderPath ${libraryName}_autolinked_build)"
"add_subdirectory(\"$nativeFolderPath\" ${libraryName}_autolinked_build)"
}
if (cxxModuleCMakeListsPath != null) {
// If user provided a custom cxxModuleCMakeListsPath, let's honor it.
val nativeFolderPath = cxxModuleCMakeListsPath.replace("CMakeLists.txt", "")
val nativeFolderPath = sanitizeCmakeListsPath(cxxModuleCMakeListsPath)
addDirectoryString +=
"\nadd_subdirectory($nativeFolderPath ${libraryName}_cxxmodule_autolinked_build)"
"\nadd_subdirectory(\"$nativeFolderPath\" ${libraryName}_cxxmodule_autolinked_build)"
}
addDirectoryString
}
@@ -159,6 +159,9 @@ abstract class GenerateAutolinkingNewArchitecturesFileTask : DefaultTask() {
const val COMPONENT_DESCRIPTOR_FILENAME = "ComponentDescriptors.h"
const val COMPONENT_INCLUDE_PATH = "react/renderer/components"
internal fun sanitizeCmakeListsPath(cmakeListsPath: String): String =
cmakeListsPath.replace("CMakeLists.txt", "").replace(" ", "\\ ")
// language=cmake
val CMAKE_TEMPLATE =
"""
@@ -11,6 +11,7 @@ import com.facebook.react.model.ModelAutolinkingConfigJson
import com.facebook.react.model.ModelAutolinkingDependenciesJson
import com.facebook.react.model.ModelAutolinkingDependenciesPlatformAndroidJson
import com.facebook.react.model.ModelAutolinkingDependenciesPlatformJson
import com.facebook.react.tasks.GenerateAutolinkingNewArchitecturesFileTask.Companion.sanitizeCmakeListsPath
import com.facebook.react.tests.createTestTask
import org.assertj.core.api.Assertions.assertThat
import org.junit.Rule
@@ -145,9 +146,9 @@ class GenerateAutolinkingNewArchitecturesFileTaskTest {
# or link against a old prefab target (this is needed for React Native 0.76 on).
set(REACTNATIVE_MERGED_SO true)
add_subdirectory(./a/directory/ aPackage_autolinked_build)
add_subdirectory(./another/directory/ anotherPackage_autolinked_build)
add_subdirectory(./another/directory/cxx/ anotherPackage_cxxmodule_autolinked_build)
add_subdirectory("./a/directory/" aPackage_autolinked_build)
add_subdirectory("./another/directory/with\ spaces/" anotherPackage_autolinked_build)
add_subdirectory("./another/directory/cxx/" anotherPackage_cxxmodule_autolinked_build)
set(AUTOLINKED_LIBRARIES
react_codegen_aPackage
@@ -258,6 +259,24 @@ class GenerateAutolinkingNewArchitecturesFileTaskTest {
.trimIndent())
}
@Test
fun sanitizeCmakeListsPath_withPathEndingWithFileName_removesFilename() {
val input = "./a/directory/CMakeLists.txt"
assertThat(sanitizeCmakeListsPath(input)).isEqualTo("./a/directory/")
}
@Test
fun sanitizeCmakeListsPath_withSpaces_removesSpaces() {
val input = "./a/dir ectory/with spaces/"
assertThat(sanitizeCmakeListsPath(input)).isEqualTo("./a/dir\\ ectory/with\\ spaces/")
}
@Test
fun sanitizeCmakeListsPath_withPathEndingWithFileNameAndSpaces_sanitizesIt() {
val input = "./a/dir ectory/CMakeLists.txt"
assertThat(sanitizeCmakeListsPath(input)).isEqualTo("./a/dir\\ ectory/")
}
private val testDependencies =
listOf(
ModelAutolinkingDependenciesPlatformAndroidJson(
@@ -276,7 +295,7 @@ class GenerateAutolinkingNewArchitecturesFileTaskTest {
buildTypes = emptyList(),
libraryName = "anotherPackage",
componentDescriptors = listOf("AnotherPackageComponentDescriptor"),
cmakeListsPath = "./another/directory/CMakeLists.txt",
cmakeListsPath = "./another/directory/with spaces/CMakeLists.txt",
cxxModuleCMakeListsPath = "./another/directory/cxx/CMakeLists.txt",
cxxModuleHeaderName = "AnotherCxxModule",
cxxModuleCMakeListsModuleName = "another_cxxModule",
+1
View File
@@ -4,3 +4,4 @@ ruby ">= 2.6.10"
gem 'cocoapods', '~> 1.13', '!= 1.15.0', '!= 1.15.1'
gem 'activesupport', '>= 6.1.7.5', '< 7.1.0'
gem 'xcodeproj', '< 1.26.0'
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
+6 -6
View File
@@ -1,6 +1,6 @@
{
"name": "helloworld",
"version": "0.76.0-rc.4",
"version": "0.76.2",
"private": true,
"scripts": {
"bootstrap": "node ./cli.js bootstrap",
@@ -13,16 +13,16 @@
},
"dependencies": {
"react": "18.3.1",
"react-native": "0.76.0-rc.4"
"react-native": "0.76.2"
},
"devDependencies": {
"@babel/core": "^7.25.2",
"@babel/preset-env": "^7.25.3",
"@babel/runtime": "^7.25.0",
"@react-native/babel-preset": "0.76.0-rc.4",
"@react-native/core-cli-utils": "0.76.0-rc.4",
"@react-native/eslint-config": "0.76.0-rc.4",
"@react-native/metro-config": "0.76.0-rc.4",
"@react-native/babel-preset": "0.76.2",
"@react-native/core-cli-utils": "0.76.2",
"@react-native/eslint-config": "0.76.2",
"@react-native/metro-config": "0.76.2",
"babel-jest": "^29.6.3",
"chalk": "^4.1.2",
"commander": "^12.0.0",
@@ -1,6 +1,6 @@
{
"name": "@react-native/hermes-inspector-msggen",
"version": "0.76.0-rc.4",
"version": "0.76.2",
"private": true,
"description": "Hermes Inspector Message Generator for React Native",
"license": "MIT",
+5 -5
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/metro-config",
"version": "0.76.0-rc.4",
"version": "0.76.2",
"description": "Metro configuration for React Native.",
"license": "MIT",
"repository": {
@@ -26,9 +26,9 @@
"dist"
],
"dependencies": {
"@react-native/js-polyfills": "0.76.0-rc.4",
"@react-native/metro-babel-transformer": "0.76.0-rc.4",
"metro-config": "^0.81.0-alpha.2",
"metro-runtime": "^0.81.0-alpha.2"
"@react-native/js-polyfills": "0.76.2",
"@react-native/metro-babel-transformer": "0.76.2",
"metro-config": "^0.81.0",
"metro-runtime": "^0.81.0"
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/normalize-colors",
"version": "0.76.0-rc.4",
"version": "0.76.2",
"description": "Color normalization for React Native.",
"license": "MIT",
"repository": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/js-polyfills",
"version": "0.76.0-rc.4",
"version": "0.76.2",
"description": "Polyfills for React Native.",
"license": "MIT",
"repository": {
@@ -1,6 +1,6 @@
{
"name": "@react-native/babel-preset",
"version": "0.76.0-rc.4",
"version": "0.76.2",
"description": "Babel preset for React Native applications",
"main": "src/index.js",
"repository": {
@@ -55,8 +55,8 @@
"@babel/plugin-transform-typescript": "^7.25.2",
"@babel/plugin-transform-unicode-regex": "^7.24.7",
"@babel/template": "^7.25.0",
"@react-native/babel-plugin-codegen": "0.76.0-rc.4",
"babel-plugin-syntax-hermes-parser": "^0.23.1",
"@react-native/babel-plugin-codegen": "0.76.2",
"babel-plugin-syntax-hermes-parser": "^0.25.1",
"babel-plugin-transform-flow-enums": "^0.0.2",
"react-refresh": "^0.14.0"
},
+1 -1
View File
@@ -25,7 +25,7 @@ function isTSXSource(fileName) {
const loose = true;
const defaultPlugins = [
[require('babel-plugin-syntax-hermes-parser')],
[require('babel-plugin-syntax-hermes-parser'), {parseLangTypes: 'flow'}],
[require('babel-plugin-transform-flow-enums')],
[require('@babel/plugin-transform-block-scoping')],
[require('@babel/plugin-transform-class-properties'), {loose}],
@@ -1,6 +1,6 @@
{
"name": "@react-native/metro-babel-transformer",
"version": "0.76.0-rc.4",
"version": "0.76.2",
"description": "Babel transformer for React Native applications.",
"main": "src/index.js",
"repository": {
@@ -16,7 +16,7 @@
"license": "MIT",
"dependencies": {
"@babel/core": "^7.25.2",
"@react-native/babel-preset": "0.76.0-rc.4",
"@react-native/babel-preset": "0.76.2",
"hermes-parser": "0.23.1",
"nullthrows": "^1.1.1"
},
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@react-native/bots",
"description": "React Native Bots",
"version": "0.76.0-rc.4",
"version": "0.76.2",
"private": true,
"license": "MIT",
"repository": {
@@ -1,6 +1,6 @@
{
"name": "@react-native/codegen-typescript-test",
"version": "0.76.0-rc.4",
"version": "0.76.2",
"private": true,
"description": "TypeScript related unit test for @react-native/codegen",
"license": "MIT",
@@ -19,7 +19,7 @@
"prepare": "yarn run build"
},
"dependencies": {
"@react-native/codegen": "0.76.0-rc.4"
"@react-native/codegen": "0.76.2"
},
"devDependencies": {
"@babel/core": "^7.25.2",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/codegen",
"version": "0.76.0-rc.4",
"version": "0.76.2",
"description": "Code generation tools for React Native",
"license": "MIT",
"repository": {
+5 -5
View File
@@ -1,6 +1,6 @@
{
"name": "react-native-info",
"version": "0.76.0-rc.4",
"version": "0.76.2",
"main": "build/index.js",
"license": "MIT",
"private": true,
@@ -17,10 +17,10 @@
"directory": "packages/react-native-info"
},
"dependencies": {
"@react-native-community/cli-config": "15.0.0-alpha.2",
"@react-native-community/cli-platform-apple": "15.0.0-alpha.2",
"@react-native-community/cli-tools": "15.0.0-alpha.2",
"@react-native-community/cli-types": "15.0.0-alpha.2",
"@react-native-community/cli-config": "15.0.1",
"@react-native-community/cli-platform-apple": "15.0.1",
"@react-native-community/cli-tools": "15.0.1",
"@react-native-community/cli-types": "15.0.1",
"commander": "^12.0.0",
"fs-extra": "^11.2.0",
"yaml": "^2.4.1"
@@ -1,6 +1,6 @@
{
"name": "@react-native/popup-menu-android",
"version": "0.76.0-rc.4",
"version": "0.76.2",
"description": "PopupMenu for the Android platform",
"main": "index.js",
"files": [
@@ -17,7 +17,7 @@
],
"license": "MIT",
"devDependencies": {
"@react-native/codegen": "0.76.0-rc.4"
"@react-native/codegen": "0.76.2"
},
"peerDependencies": {
"@types/react": "^18.2.6",
@@ -1,6 +1,6 @@
{
"name": "@react-native/oss-library-example",
"version": "0.76.0-rc.4",
"version": "0.76.2",
"private": true,
"description": "Package that includes native module exapmle, native component example, targets both the old and the new architecture. It should serve as an example of a real-world OSS library.",
"license": "MIT",
@@ -26,8 +26,8 @@
],
"devDependencies": {
"@babel/core": "^7.25.2",
"@react-native/babel-preset": "0.76.0-rc.4",
"react-native": "0.76.0-rc.4"
"@react-native/babel-preset": "0.76.2",
"react-native": "0.76.2"
},
"peerDependencies": {
"react": "*",
@@ -1,7 +1,7 @@
{
"name": "@react-native/test-renderer",
"private": true,
"version": "0.76.0-rc.4",
"version": "0.76.2",
"description": "A Test rendering library for React Native",
"license": "MIT",
"devDependencies": {
@@ -76,6 +76,7 @@
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [self createRootViewController];
[self setRootView:rootView toRootViewController:rootViewController];
_window.windowScene.delegate = self;
_window.rootViewController = rootViewController;
[_window makeKeyAndVisible];
}
@@ -63,7 +63,7 @@ Pod::Spec.new do |s|
"CLANG_CXX_LANGUAGE_STANDARD" => rct_cxx_language_standard(),
"DEFINES_MODULE" => "YES"
}
s.user_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/Headers/Private/React-Core\""}
s.user_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/Headers/Private/React-Core\" \"$(PODS_ROOT)/Headers/Private/Yoga\""}
s.dependency "React-Core"
s.dependency "RCT-Folly", folly_version
+2 -2
View File
@@ -16,8 +16,8 @@ const version: $ReadOnly<{
}> = {
major: 0,
minor: 76,
patch: 0,
prerelease: 'rc.4',
patch: 2,
prerelease: null,
};
module.exports = {version};
+1 -7
View File
@@ -21,13 +21,7 @@ ExceptionsManager.installConsoleErrorReporter();
if (!global.__fbDisableExceptionsManager) {
const handleError = (e: mixed, isFatal: boolean) => {
try {
// TODO(T196834299): We should really use a c++ turbomodule for this
if (
!global.RN$handleException ||
!global.RN$handleException(e, isFatal)
) {
ExceptionsManager.handleException(e, isFatal);
}
ExceptionsManager.handleException(e, isFatal);
} catch (ee) {
console.log('Failed to print error: ', ee.message);
throw e;
+2 -2
View File
@@ -82,9 +82,9 @@ let warningFilter: WarningFilter = function (format) {
return {
finalFormat: format,
forceDialogImmediately: false,
suppressDialog_LEGACY: true,
suppressDialog_LEGACY: false,
suppressCompletely: false,
monitorEvent: 'unknown',
monitorEvent: 'warning_unhandled',
monitorListVersion: 0,
monitorSampleRate: 1,
};
@@ -11,45 +11,29 @@
import {
DoesNotUseKey,
FragmentWithProp,
ManualConsoleError,
ManualConsoleErrorWithStack,
} from './__fixtures__/ReactWarningFixtures';
import * as React from 'react';
const LogBoxData = require('../Data/LogBoxData');
const TestRenderer = require('react-test-renderer');
const installLogBox = () => {
const LogBox = require('../LogBox');
const ExceptionsManager = require('../../Core/ExceptionsManager.js');
const installLogBox = () => {
const LogBox = require('../LogBox').default;
LogBox.install();
};
const uninstallLogBox = () => {
const LogBox = require('../LogBox');
const LogBox = require('../LogBox').default;
LogBox.uninstall();
};
const BEFORE_SLASH_RE = /(?:\/[a-zA-Z]+\/)(.+?)(?:\/.+)\//;
const cleanPath = message => {
return message.replace(BEFORE_SLASH_RE, '/path/to/');
};
const cleanLog = logs => {
return logs.map(log => {
return {
...log,
componentStack: log.componentStack.map(stack => ({
...stack,
fileName: cleanPath(stack.fileName),
})),
};
});
};
// TODO(T71117418): Re-enable skipped LogBox integration tests once React component
// stack frames are the same internally and in open source.
// eslint-disable-next-line jest/no-disabled-tests
describe.skip('LogBox', () => {
// TODO: we can remove all the symetric matchers once OSS lands component stack frames.
// For now, the component stack parsing differs in ways we can't easily detect in this test.
describe('LogBox', () => {
const {error, warn} = console;
const mockError = jest.fn();
const mockWarn = jest.fn();
@@ -57,10 +41,14 @@ describe.skip('LogBox', () => {
beforeEach(() => {
jest.resetModules();
jest.restoreAllMocks();
jest.spyOn(console, 'error').mockImplementation(() => {});
mockError.mockClear();
mockWarn.mockClear();
// Reset ExceptionManager patching.
if (console._errorOriginal) {
console._errorOriginal = null;
}
(console: any).error = mockError;
(console: any).warn = mockWarn;
});
@@ -79,7 +67,10 @@ describe.skip('LogBox', () => {
// so we can assert on what React logs.
jest.spyOn(console, 'error');
const output = TestRenderer.create(<DoesNotUseKey />);
let output;
TestRenderer.act(() => {
output = TestRenderer.create(<DoesNotUseKey />);
});
// The key error should always be the highest severity.
// In LogBox, we expect these errors to:
@@ -88,16 +79,37 @@ describe.skip('LogBox', () => {
// - Pass to console.error, with a "Warning" prefix so it does not pop a RedBox.
expect(output).toBeDefined();
expect(mockWarn).not.toBeCalled();
expect(console.error.mock.calls[0].map(cleanPath)).toMatchSnapshot(
'Log sent from React',
);
expect(cleanLog(spy.mock.calls[0])).toMatchSnapshot('Log added to LogBox');
expect(mockError.mock.calls[0].map(cleanPath)).toMatchSnapshot(
'Log passed to console error',
);
expect(console.error).toBeCalledTimes(1);
expect(console.error.mock.calls[0]).toEqual([
'Warning: Each child in a list should have a unique "key" prop.%s%s See https://reactjs.org/link/warning-keys for more information.%s',
'\n\nCheck the render method of `DoesNotUseKey`.',
'',
expect.stringMatching('at DoesNotUseKey'),
]);
expect(spy).toHaveBeenCalledWith({
level: 'error',
category: expect.stringContaining(
'Warning: Each child in a list should have a unique',
),
componentStack: expect.anything(),
componentStackType: 'stack',
message: {
content:
'Warning: Each child in a list should have a unique "key" prop.\n\nCheck the render method of `DoesNotUseKey`. See https://reactjs.org/link/warning-keys for more information.',
substitutions: [
{length: 45, offset: 62},
{length: 0, offset: 107},
],
},
});
// The Warning: prefix is added due to a hack in LogBox to prevent double logging.
expect(mockError.mock.calls[0][0].startsWith('Warning: ')).toBe(true);
// We also interpolate the string before passing to the underlying console method.
expect(mockError.mock.calls[0]).toEqual([
expect.stringMatching(
'Warning: Each child in a list should have a unique "key" prop.\n\nCheck the render method of `DoesNotUseKey`. See https://reactjs.org/link/warning-keys for more information.\n at ',
),
]);
});
it('integrates with React and handles a fragment warning in LogBox', () => {
@@ -108,7 +120,10 @@ describe.skip('LogBox', () => {
// so we can assert on what React logs.
jest.spyOn(console, 'error');
const output = TestRenderer.create(<FragmentWithProp />);
let output;
TestRenderer.act(() => {
output = TestRenderer.create(<FragmentWithProp />);
});
// The fragment warning is not as severe. For this warning we don't want to
// pop open a dialog, so we show a collapsed error UI.
@@ -118,15 +133,125 @@ describe.skip('LogBox', () => {
// - Pass to console.error, with a "Warning" prefix so it does not pop a RedBox.
expect(output).toBeDefined();
expect(mockWarn).not.toBeCalled();
expect(console.error.mock.calls[0].map(cleanPath)).toMatchSnapshot(
'Log sent from React',
);
expect(cleanLog(spy.mock.calls[0])).toMatchSnapshot('Log added to LogBox');
expect(mockError.mock.calls[0].map(cleanPath)).toMatchSnapshot(
'Log passed to console error',
);
expect(console.error).toBeCalledTimes(1);
expect(console.error.mock.calls[0]).toEqual([
'Warning: Invalid prop `%s` supplied to `React.Fragment`. React.Fragment can only have `key` and `children` props.%s',
'invalid',
expect.stringMatching('at FragmentWithProp'),
]);
expect(spy).toHaveBeenCalledWith({
level: 'error',
category: expect.stringContaining('Warning: Invalid prop'),
componentStack: expect.anything(),
componentStackType: expect.stringMatching(/(stack|legacy)/),
message: {
content:
'Warning: Invalid prop `invalid` supplied to `React.Fragment`. React.Fragment can only have `key` and `children` props.',
substitutions: [{length: 7, offset: 23}],
},
});
// The Warning: prefix is added due to a hack in LogBox to prevent double logging.
expect(mockError.mock.calls[0][0].startsWith('Warning: ')).toBe(true);
// We also interpolate the string before passing to the underlying console method.
expect(mockError.mock.calls[0]).toEqual([
expect.stringMatching(
'Warning: Invalid prop `invalid` supplied to `React.Fragment`. React.Fragment can only have `key` and `children` props.\n at FragmentWithProp',
),
]);
});
it('handles a manual console.error without a component stack in LogBox', () => {
const LogBox = require('../LogBox').default;
const spy = jest.spyOn(LogBox, 'addException');
installLogBox();
// console.error handling depends on installing the ExceptionsManager error reporter.
ExceptionsManager.installConsoleErrorReporter();
// Spy console.error after LogBox is installed
// so we can assert on what React logs.
jest.spyOn(console, 'error');
let output;
TestRenderer.act(() => {
output = TestRenderer.create(<ManualConsoleError />);
});
// Manual console errors should show a collapsed error dialog.
// When there is no component stack, we expect these errors to:
// - Go to the LogBox patch and fall through to console.error.
// - Get picked up by the ExceptionsManager console.error override.
// - Get passed back to LogBox via addException (non-fatal).
expect(output).toBeDefined();
expect(mockWarn).not.toBeCalled();
expect(spy).toBeCalledTimes(1);
expect(console.error).toBeCalledTimes(1);
expect(console.error.mock.calls[0]).toEqual(['Manual console error']);
expect(spy).toHaveBeenCalledWith({
id: 1,
isComponentError: false,
isFatal: false,
name: 'console.error',
originalMessage: 'Manual console error',
message: 'console.error: Manual console error',
extraData: expect.anything(),
componentStack: null,
stack: expect.anything(),
});
// No Warning: prefix is added due since this is falling through.
expect(mockError.mock.calls[0]).toEqual(['Manual console error']);
});
it('handles a manual console.error with a component stack in LogBox', () => {
const spy = jest.spyOn(LogBoxData, 'addLog');
installLogBox();
// console.error handling depends on installing the ExceptionsManager error reporter.
ExceptionsManager.installConsoleErrorReporter();
// Spy console.error after LogBox is installed
// so we can assert on what React logs.
jest.spyOn(console, 'error');
let output;
TestRenderer.act(() => {
output = TestRenderer.create(<ManualConsoleErrorWithStack />);
});
// Manual console errors should show a collapsed error dialog.
// When there is a component stack, we expect these errors to:
// - Go to the LogBox patch and be detected as a React error.
// - Check the warning filter to see if there is a fiter setting.
// - Call console.error with the parsed error.
// - Get picked up by ExceptionsManager console.error override.
// - Log to console.error.
expect(output).toBeDefined();
expect(mockWarn).not.toBeCalled();
expect(console.error).toBeCalledTimes(1);
expect(spy).toBeCalledTimes(1);
expect(console.error.mock.calls[0]).toEqual([
expect.stringContaining(
'Manual console error\n at ManualConsoleErrorWithStack',
),
]);
expect(spy).toHaveBeenCalledWith({
level: 'error',
category: expect.stringContaining('Warning: Manual console error'),
componentStack: expect.anything(),
componentStackType: 'stack',
message: {
content: 'Warning: Manual console error',
substitutions: [],
},
});
// The Warning: prefix is added due to a hack in LogBox to prevent double logging.
// We also interpolate the string before passing to the underlying console method.
expect(mockError.mock.calls[0]).toEqual([
expect.stringMatching(
'Warning: Manual console error\n at ManualConsoleErrorWithStack',
),
]);
});
});
@@ -13,6 +13,7 @@
const LogBoxData = require('../Data/LogBoxData');
const LogBox = require('../LogBox').default;
const ExceptionsManager = require('../../Core/ExceptionsManager.js');
declare var console: any;
@@ -34,15 +35,18 @@ describe('LogBox', () => {
beforeEach(() => {
jest.resetModules();
jest.restoreAllMocks();
console.error = jest.fn();
console.log = jest.fn();
console.warn = jest.fn();
});
afterEach(() => {
LogBox.uninstall();
// Reset ExceptionManager patching.
if (console._errorOriginal) {
console._errorOriginal = null;
}
console.error = error;
console.log = log;
console.warn = warn;
});
@@ -95,7 +99,7 @@ describe('LogBox', () => {
});
it('registers warnings', () => {
jest.mock('../Data/LogBoxData');
jest.spyOn(LogBoxData, 'addLog');
LogBox.install();
@@ -105,13 +109,14 @@ describe('LogBox', () => {
});
it('reports a LogBox exception if we fail to add warnings', () => {
jest.mock('../Data/LogBoxData');
const mockError = new Error('Simulated error');
jest.spyOn(LogBoxData, 'addLog');
jest.spyOn(LogBoxData, 'reportLogBoxError');
// Picking a random implementation detail to simulate throwing.
(LogBoxData.isMessageIgnored: any).mockImplementation(() => {
jest.spyOn(LogBoxData, 'isMessageIgnored').mockImplementation(() => {
throw mockError;
});
const mockError = new Error('Simulated error');
LogBox.install();
@@ -123,7 +128,8 @@ describe('LogBox', () => {
});
it('only registers errors beginning with "Warning: "', () => {
jest.mock('../Data/LogBoxData');
jest.spyOn(LogBoxData, 'addLog');
jest.spyOn(LogBoxData, 'checkWarningFilter');
LogBox.install();
@@ -133,7 +139,8 @@ describe('LogBox', () => {
});
it('registers react errors with the formatting from filter', () => {
jest.mock('../Data/LogBoxData');
jest.spyOn(LogBoxData, 'addLog');
jest.spyOn(LogBoxData, 'checkWarningFilter');
mockFilterResult({
finalFormat: 'Custom format',
@@ -157,7 +164,8 @@ describe('LogBox', () => {
});
it('registers errors with component stack as errors by default', () => {
jest.mock('../Data/LogBoxData');
jest.spyOn(LogBoxData, 'addLog');
jest.spyOn(LogBoxData, 'checkWarningFilter');
mockFilterResult({});
@@ -174,7 +182,8 @@ describe('LogBox', () => {
});
it('registers errors with component stack as errors by default if not found in warning filter', () => {
jest.mock('../Data/LogBoxData');
jest.spyOn(LogBoxData, 'addLog');
jest.spyOn(LogBoxData, 'checkWarningFilter');
mockFilterResult({
monitorEvent: 'warning_unhandled',
@@ -193,10 +202,12 @@ describe('LogBox', () => {
});
it('registers errors with component stack with legacy suppression as warning', () => {
jest.mock('../Data/LogBoxData');
jest.spyOn(LogBoxData, 'addLog');
jest.spyOn(LogBoxData, 'checkWarningFilter');
mockFilterResult({
suppressDialog_LEGACY: true,
monitorEvent: 'warning',
});
LogBox.install();
@@ -211,10 +222,12 @@ describe('LogBox', () => {
});
it('registers errors with component stack and a forced dialog as fatals', () => {
jest.mock('../Data/LogBoxData');
jest.spyOn(LogBoxData, 'addLog');
jest.spyOn(LogBoxData, 'checkWarningFilter');
mockFilterResult({
forceDialogImmediately: true,
monitorEvent: 'warning',
});
LogBox.install();
@@ -229,7 +242,8 @@ describe('LogBox', () => {
});
it('registers warning module errors with the formatting from filter', () => {
jest.mock('../Data/LogBoxData');
jest.spyOn(LogBoxData, 'addLog');
jest.spyOn(LogBoxData, 'checkWarningFilter');
mockFilterResult({
finalFormat: 'Custom format',
@@ -248,7 +262,8 @@ describe('LogBox', () => {
});
it('registers warning module errors as errors by default', () => {
jest.mock('../Data/LogBoxData');
jest.spyOn(LogBoxData, 'addLog');
jest.spyOn(LogBoxData, 'checkWarningFilter');
mockFilterResult({});
@@ -262,10 +277,12 @@ describe('LogBox', () => {
});
it('registers warning module errors with only legacy suppression as warning', () => {
jest.mock('../Data/LogBoxData');
jest.spyOn(LogBoxData, 'addLog');
jest.spyOn(LogBoxData, 'checkWarningFilter');
mockFilterResult({
suppressDialog_LEGACY: true,
monitorEvent: 'warning',
});
LogBox.install();
@@ -277,10 +294,12 @@ describe('LogBox', () => {
});
it('registers warning module errors with a forced dialog as fatals', () => {
jest.mock('../Data/LogBoxData');
jest.spyOn(LogBoxData, 'addLog');
jest.spyOn(LogBoxData, 'checkWarningFilter');
mockFilterResult({
forceDialogImmediately: true,
monitorEvent: 'warning',
});
LogBox.install();
@@ -292,10 +311,12 @@ describe('LogBox', () => {
});
it('ignores warning module errors that are suppressed completely', () => {
jest.mock('../Data/LogBoxData');
jest.spyOn(LogBoxData, 'addLog');
jest.spyOn(LogBoxData, 'checkWarningFilter');
mockFilterResult({
suppressCompletely: true,
monitorEvent: 'warning',
});
LogBox.install();
@@ -305,10 +326,11 @@ describe('LogBox', () => {
});
it('ignores warning module errors that are pattern ignored', () => {
jest.mock('../Data/LogBoxData');
jest.spyOn(LogBoxData, 'checkWarningFilter');
jest.spyOn(LogBoxData, 'isMessageIgnored').mockReturnValue(true);
jest.spyOn(LogBoxData, 'addLog');
mockFilterResult({});
(LogBoxData.isMessageIgnored: any).mockReturnValue(true);
LogBox.install();
@@ -317,10 +339,11 @@ describe('LogBox', () => {
});
it('ignores warning module errors that are from LogBox itself', () => {
jest.mock('../Data/LogBoxData');
jest.spyOn(LogBoxData, 'checkWarningFilter');
jest.spyOn(LogBoxData, 'isLogBoxErrorMessage').mockReturnValue(true);
jest.spyOn(LogBoxData, 'addLog');
mockFilterResult({});
(LogBoxData.isLogBoxErrorMessage: any).mockReturnValue(true);
LogBox.install();
@@ -329,8 +352,9 @@ describe('LogBox', () => {
});
it('ignores logs that are pattern ignored"', () => {
jest.mock('../Data/LogBoxData');
(LogBoxData.isMessageIgnored: any).mockReturnValue(true);
jest.spyOn(LogBoxData, 'checkWarningFilter');
jest.spyOn(LogBoxData, 'isMessageIgnored').mockReturnValue(true);
jest.spyOn(LogBoxData, 'addLog');
LogBox.install();
@@ -339,8 +363,8 @@ describe('LogBox', () => {
});
it('does not add logs that are from LogBox itself"', () => {
jest.mock('../Data/LogBoxData');
(LogBoxData.isLogBoxErrorMessage: any).mockReturnValue(true);
jest.spyOn(LogBoxData, 'isLogBoxErrorMessage').mockReturnValue(true);
jest.spyOn(LogBoxData, 'addLog');
LogBox.install();
@@ -349,7 +373,7 @@ describe('LogBox', () => {
});
it('ignores logs starting with "(ADVICE)"', () => {
jest.mock('../Data/LogBoxData');
jest.spyOn(LogBoxData, 'addLog');
LogBox.install();
@@ -358,7 +382,7 @@ describe('LogBox', () => {
});
it('does not ignore logs formatted to start with "(ADVICE)"', () => {
jest.mock('../Data/LogBoxData');
jest.spyOn(LogBoxData, 'addLog');
LogBox.install();
@@ -376,7 +400,7 @@ describe('LogBox', () => {
});
it('ignores console methods after uninstalling', () => {
jest.mock('../Data/LogBoxData');
jest.spyOn(LogBoxData, 'addLog');
LogBox.install();
LogBox.uninstall();
@@ -389,7 +413,7 @@ describe('LogBox', () => {
});
it('does not add logs after uninstalling', () => {
jest.mock('../Data/LogBoxData');
jest.spyOn(LogBoxData, 'addLog');
LogBox.install();
LogBox.uninstall();
@@ -406,7 +430,7 @@ describe('LogBox', () => {
});
it('does not add exceptions after uninstalling', () => {
jest.mock('../Data/LogBoxData');
jest.spyOn(LogBoxData, 'addException');
LogBox.install();
LogBox.uninstall();
@@ -482,4 +506,80 @@ describe('LogBox', () => {
'Custom: after installing for the second time',
);
});
it('registers errors with component stack as errors by default, when ExceptionManager is registered first', () => {
jest.spyOn(LogBoxData, 'checkWarningFilter');
jest.spyOn(LogBoxData, 'addLog');
ExceptionsManager.installConsoleErrorReporter();
LogBox.install();
console.error(
'HIT\n at Text (/path/to/Component:30:175)\n at DoesNotUseKey',
);
expect(LogBoxData.addLog).toBeCalledWith(
expect.objectContaining({level: 'error'}),
);
expect(LogBoxData.checkWarningFilter).toBeCalledWith(
'HIT\n at Text (/path/to/Component:30:175)\n at DoesNotUseKey',
);
});
it('registers errors with component stack as errors by default, when ExceptionManager is registered second', () => {
jest.spyOn(LogBoxData, 'checkWarningFilter');
jest.spyOn(LogBoxData, 'addLog');
LogBox.install();
ExceptionsManager.installConsoleErrorReporter();
console.error(
'HIT\n at Text (/path/to/Component:30:175)\n at DoesNotUseKey',
);
expect(LogBoxData.addLog).toBeCalledWith(
expect.objectContaining({level: 'error'}),
);
expect(LogBoxData.checkWarningFilter).toBeCalledWith(
'HIT\n at Text (/path/to/Component:30:175)\n at DoesNotUseKey',
);
});
it('registers errors without component stack as errors by default, when ExceptionManager is registered first', () => {
jest.spyOn(LogBoxData, 'checkWarningFilter');
jest.spyOn(LogBoxData, 'addException');
ExceptionsManager.installConsoleErrorReporter();
LogBox.install();
console.error('HIT');
// Errors without a component stack skip the warning filter and
// fall through to the ExceptionManager, which are then reported
// back to LogBox as non-fatal exceptions, in a convuluted dance
// in the most legacy cruft way.
expect(LogBoxData.addException).toBeCalledWith(
expect.objectContaining({originalMessage: 'HIT'}),
);
expect(LogBoxData.checkWarningFilter).not.toBeCalled();
});
it('registers errors without component stack as errors by default, when ExceptionManager is registered second', () => {
jest.spyOn(LogBoxData, 'checkWarningFilter');
jest.spyOn(LogBoxData, 'addException');
LogBox.install();
ExceptionsManager.installConsoleErrorReporter();
console.error('HIT');
// Errors without a component stack skip the warning filter and
// fall through to the ExceptionManager, which are then reported
// back to LogBox as non-fatal exceptions, in a convuluted dance
// in the most legacy cruft way.
expect(LogBoxData.addException).toBeCalledWith(
expect.objectContaining({originalMessage: 'HIT'}),
);
expect(LogBoxData.checkWarningFilter).not.toBeCalled();
});
});
@@ -30,3 +30,27 @@ export const FragmentWithProp = () => {
</React.Fragment>
);
};
export const ManualConsoleError = () => {
console.error('Manual console error');
return (
<React.Fragment>
{['foo', 'bar'].map(item => (
<Text key={item}>{item}</Text>
))}
</React.Fragment>
);
};
export const ManualConsoleErrorWithStack = () => {
console.error(
'Manual console error\n at ManualConsoleErrorWithStack (/path/to/ManualConsoleErrorWithStack:30:175)\n at TestApp',
);
return (
<React.Fragment>
{['foo', 'bar'].map(item => (
<Text key={item}>{item}</Text>
))}
</React.Fragment>
);
};
+3 -3
View File
@@ -13,7 +13,7 @@ import type {RootTag} from '../Types/RootTagTypes';
import type {IPerformanceLogger} from '../Utilities/createPerformanceLogger';
import type {DisplayModeType} from './DisplayMode';
import BatchedBridge from '../BatchedBridge/BatchedBridge';
import registerCallableModule from '../Core/registerCallableModule';
import BugReporting from '../BugReporting/BugReporting';
import createPerformanceLogger from '../Utilities/createPerformanceLogger';
import infoLog from '../Utilities/infoLog';
@@ -363,8 +363,8 @@ global.RN$SurfaceRegistry = {
if (global.RN$Bridgeless === true) {
console.log('Bridgeless mode is enabled');
} else {
BatchedBridge.registerCallableModule('AppRegistry', AppRegistry);
}
registerCallableModule('AppRegistry', AppRegistry);
module.exports = AppRegistry;
@@ -35,6 +35,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, assign, readonly) CGFloat zoomScale;
@property (nonatomic, assign, readonly) CGPoint contentOffset;
@property (nonatomic, assign, readonly) UIEdgeInsets contentInset;
@property (nullable, nonatomic, copy) NSDictionary<NSAttributedStringKey, id> *typingAttributes;
// This protocol disallows direct access to `selectedTextRange` property because
// unwise usage of it can break the `delegate` behavior. So, we always have to
@@ -23,8 +23,8 @@ NSDictionary* RCTGetReactNativeVersion(void)
__rnVersion = @{
RCTVersionMajor: @(0),
RCTVersionMinor: @(76),
RCTVersionPatch: @(0),
RCTVersionPrerelease: @"rc.4",
RCTVersionPatch: @(2),
RCTVersionPrerelease: [NSNull null],
};
});
return __rnVersion;
@@ -61,6 +61,13 @@ static NSSet<NSNumber *> *returnKeyTypesSet;
*/
BOOL _comingFromJS;
BOOL _didMoveToWindow;
/*
* Newly initialized default typing attributes contain a no-op NSParagraphStyle and NSShadow. These cause inequality
* between the AttributedString backing the input and those generated from state. We store these attributes to make
* later comparison insensitive to them.
*/
NSDictionary<NSAttributedStringKey, id> *_originalTypingAttributes;
}
#pragma mark - UIView overrides
@@ -76,6 +83,7 @@ static NSSet<NSNumber *> *returnKeyTypesSet;
_ignoreNextTextInputCall = NO;
_comingFromJS = NO;
_didMoveToWindow = NO;
_originalTypingAttributes = [_backedTextInputView.typingAttributes copy];
[self addSubview:_backedTextInputView];
[self initializeReturnKeyType];
@@ -84,6 +92,20 @@ static NSSet<NSNumber *> *returnKeyTypesSet;
return self;
}
- (void)updateEventEmitter:(const EventEmitter::Shared &)eventEmitter
{
[super updateEventEmitter:eventEmitter];
NSMutableDictionary<NSAttributedStringKey, id> *defaultAttributes =
[_backedTextInputView.defaultTextAttributes mutableCopy];
RCTWeakEventEmitterWrapper *eventEmitterWrapper = [RCTWeakEventEmitterWrapper new];
eventEmitterWrapper.eventEmitter = _eventEmitter;
defaultAttributes[RCTAttributedStringEventEmitterKey] = eventEmitterWrapper;
_backedTextInputView.defaultTextAttributes = defaultAttributes;
}
- (void)didMoveToWindow
{
[super didMoveToWindow];
@@ -236,8 +258,11 @@ static NSSet<NSNumber *> *returnKeyTypesSet;
}
if (newTextInputProps.textAttributes != oldTextInputProps.textAttributes) {
_backedTextInputView.defaultTextAttributes =
NSMutableDictionary<NSAttributedStringKey, id> *defaultAttributes =
RCTNSTextAttributesFromTextAttributes(newTextInputProps.getEffectiveTextAttributes(RCTFontSizeMultiplier()));
defaultAttributes[RCTAttributedStringEventEmitterKey] =
_backedTextInputView.defaultTextAttributes[RCTAttributedStringEventEmitterKey];
_backedTextInputView.defaultTextAttributes = defaultAttributes;
}
if (newTextInputProps.selectionColor != oldTextInputProps.selectionColor) {
@@ -418,6 +443,7 @@ static NSSet<NSNumber *> *returnKeyTypesSet;
- (void)textInputDidChangeSelection
{
[self _updateTypingAttributes];
if (_comingFromJS) {
return;
}
@@ -674,9 +700,26 @@ static NSSet<NSNumber *> *returnKeyTypesSet;
[_backedTextInputView scrollRangeToVisible:NSMakeRange(offsetStart, 0)];
}
[self _restoreTextSelection];
[self _updateTypingAttributes];
_lastStringStateWasUpdatedWith = attributedString;
}
// Ensure that newly typed text will inherit any custom attributes. We follow the logic of RN Android, where attributes
// to the left of the cursor are copied into new text, unless we are at the start of the field, in which case we will
// copy the attributes from text to the right. This allows consistency between backed input and new AttributedText
// https://github.com/facebook/react-native/blob/3102a58df38d96f3dacef0530e4dbb399037fcd2/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/internal/span/SetSpanOperation.kt#L30
- (void)_updateTypingAttributes
{
if (_backedTextInputView.attributedText.length > 0) {
NSUInteger offsetStart = [_backedTextInputView offsetFromPosition:_backedTextInputView.beginningOfDocument
toPosition:_backedTextInputView.selectedTextRange.start];
NSUInteger samplePoint = offsetStart == 0 ? 0 : offsetStart - 1;
_backedTextInputView.typingAttributes = [_backedTextInputView.attributedText attributesAtIndex:samplePoint
effectiveRange:NULL];
}
}
- (void)_setMultiline:(BOOL)multiline
{
[_backedTextInputView removeFromSuperview];
@@ -732,9 +775,10 @@ static NSSet<NSNumber *> *returnKeyTypesSet;
_backedTextInputView.markedTextRange || _backedTextInputView.isSecureTextEntry || fontHasBeenUpdatedBySystem;
if (shouldFallbackToBareTextComparison) {
return ([newText.string isEqualToString:oldText.string]);
return [newText.string isEqualToString:oldText.string];
} else {
return ([newText isEqualToAttributedString:oldText]);
return RCTIsAttributedStringEffectivelySame(
newText, oldText, _originalTypingAttributes, static_cast<const TextInputProps &>(*_props).textAttributes);
}
}
@@ -833,6 +833,8 @@ static RCTBorderStyle RCTBorderStyleFromBorderStyle(BorderStyle borderStyle)
_backgroundColorLayer.mask = maskLayer;
_backgroundColorLayer.cornerRadius = 0;
}
[_backgroundColorLayer removeAllAnimations];
}
// borders
@@ -3306,7 +3306,6 @@ public final class com/facebook/react/modules/core/TimingModule : com/facebook/f
public fun createTimer (DDDZ)V
public fun deleteTimer (D)V
public fun emitTimeDriftWarning (Ljava/lang/String;)V
public fun initialize ()V
public fun invalidate ()V
public fun setSendIdleEvents (Z)V
}
@@ -3798,13 +3797,13 @@ public abstract class com/facebook/react/packagerconnection/NotificationOnlyHand
public final fun onRequest (Ljava/lang/Object;Lcom/facebook/react/packagerconnection/Responder;)V
}
public final class com/facebook/react/packagerconnection/PackagerConnectionSettings {
public class com/facebook/react/packagerconnection/PackagerConnectionSettings {
public fun <init> (Landroid/content/Context;)V
public final fun getAdditionalOptionsForPackager ()Ljava/util/Map;
public final fun getDebugServerHost ()Ljava/lang/String;
public fun getDebugServerHost ()Ljava/lang/String;
public final fun getPackageName ()Ljava/lang/String;
public final fun setAdditionalOptionForPackager (Ljava/lang/String;Ljava/lang/String;)V
public final fun setDebugServerHost (Ljava/lang/String;)V
public fun setDebugServerHost (Ljava/lang/String;)V
}
public final class com/facebook/react/packagerconnection/ReconnectingWebSocket : okhttp3/WebSocketListener {
@@ -557,7 +557,6 @@ android {
listOf(
"src/main/res/devsupport",
"src/main/res/shell",
"src/main/res/views/alert",
"src/main/res/views/modal",
"src/main/res/views/uimanager"))
java.exclude("com/facebook/react/processing")
@@ -36,7 +36,7 @@ if(CMAKE_HOST_WIN32)
endif()
file(GLOB input_SRC CONFIGURE_DEPENDS
*.cpp
${REACT_ANDROID_DIR}/cmake-utils/default-app-setup/*.cpp
${BUILD_DIR}/generated/autolinking/src/main/jni/*.cpp)
add_library(${CMAKE_PROJECT_NAME} SHARED ${input_SRC})
@@ -1,4 +1,4 @@
VERSION_NAME=0.76.0-rc.4
VERSION_NAME=0.76.2
react.internal.publishingGroup=com.facebook.react
android.useAndroidX=true
@@ -124,15 +124,11 @@ public abstract class HeadlessJsTaskService extends Service implements HeadlessJ
@Override
public void onDestroy() {
super.onDestroy();
ReactContext reactContext = getReactContext();
if (getReactNativeHost().hasInstance()) {
ReactInstanceManager reactInstanceManager = getReactNativeHost().getReactInstanceManager();
ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
if (reactContext != null) {
HeadlessJsTaskContext headlessJsTaskContext =
HeadlessJsTaskContext.getInstance(reactContext);
headlessJsTaskContext.removeTaskEventListener(this);
}
if (reactContext != null) {
HeadlessJsTaskContext headlessJsTaskContext = HeadlessJsTaskContext.getInstance(reactContext);
headlessJsTaskContext.removeTaskEventListener(this);
}
if (sWakeLock != null) {
sWakeLock.release();
@@ -12,6 +12,7 @@ import androidx.annotation.AnyThread
import androidx.annotation.UiThread
import com.facebook.infer.annotation.ThreadConfined
import com.facebook.react.common.annotations.UnstableReactNativeAPI
import com.facebook.react.uimanager.events.EventDispatcher
@OptIn(UnstableReactNativeAPI::class)
public interface UIManager : PerformanceCounter {
@@ -78,7 +79,7 @@ public interface UIManager : PerformanceCounter {
public fun dispatchCommand(reactTag: Int, commandId: String, commandArgs: ReadableArray?)
/** @return the [EventDispatcher] object that is used by this class. */
public fun <T> getEventDispatcher(): T
public val eventDispatcher: EventDispatcher
/**
* Used by native animated module to bypass the process of updating the values through the shadow
@@ -111,7 +111,7 @@ protected constructor(
packages,
jsMainModuleName,
bundleAssetName ?: "index",
null,
jsBundleFile,
isHermesEnabled ?: true,
useDeveloperSupport,
)
@@ -1021,7 +1021,6 @@ public class FabricUIManager
@Override
@NonNull
@SuppressWarnings("unchecked")
public EventDispatcher getEventDispatcher() {
return mEventDispatcher;
}
@@ -65,6 +65,7 @@ public open class JavaTimerManager(
init {
reactApplicationContext.addLifecycleEventListener(this)
HeadlessJsTaskContext.getInstance(reactApplicationContext).addTaskEventListener(this)
}
override fun onHostPause() {
@@ -103,6 +104,7 @@ public open class JavaTimerManager(
}
public open fun onInstanceDestroy() {
HeadlessJsTaskContext.getInstance(reactApplicationContext).removeTaskEventListener(this)
reactApplicationContext.removeLifecycleEventListener(this)
clearFrameCallback()
clearChoreographerIdleCallback()
@@ -12,7 +12,6 @@ import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.WritableArray
import com.facebook.react.common.annotations.VisibleForTesting
import com.facebook.react.devsupport.interfaces.DevSupportManager
import com.facebook.react.jstasks.HeadlessJsTaskContext
import com.facebook.react.module.annotations.ReactModule
/** Native module for JS timer execution. Timers fire on frame boundaries. */
@@ -24,11 +23,6 @@ public class TimingModule(
private val javaTimerManager: JavaTimerManager =
JavaTimerManager(reactContext, this, ReactChoreographer.getInstance(), devSupportManager)
override fun initialize() {
HeadlessJsTaskContext.getInstance(getReactApplicationContext())
.addTaskEventListener(javaTimerManager)
}
override fun createTimer(
callbackIDDouble: Double,
durationDouble: Double,
@@ -68,8 +62,6 @@ public class TimingModule(
}
override fun invalidate() {
val headlessJsTaskContext = HeadlessJsTaskContext.getInstance(getReactApplicationContext())
headlessJsTaskContext.removeTaskEventListener(javaTimerManager)
javaTimerManager.onInstanceDestroy()
}
@@ -12,20 +12,11 @@ import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.TypedArray;
import android.os.Build;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.core.view.AccessibilityDelegateCompat;
import androidx.core.view.ViewCompat;
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
import androidx.fragment.app.DialogFragment;
import com.facebook.infer.annotation.Assertions;
import com.facebook.infer.annotation.Nullsafe;
import com.facebook.react.R;
/** A fragment used to display the dialog. */
@Nullsafe(Nullsafe.Mode.LOCAL)
@@ -75,55 +66,15 @@ public class AlertFragment extends DialogFragment implements DialogInterface.OnC
return isAppCompat;
}
/**
* Creates a custom dialog title View that has the role of "Heading" and focusable for
* accessibility purposes.
*
* @returns accessible TextView title
*/
private static View getAccessibleTitle(Context activityContext, String titleText) {
LayoutInflater inflater = LayoutInflater.from(activityContext);
// This layout matches the sizing and styling of AlertDialog's title_template (minus the icon)
// since the whole thing gets tossed out when setting a custom title
View titleContainer = inflater.inflate(R.layout.alert_title_layout, null);
TextView accessibleTitle =
Assertions.assertNotNull(titleContainer.findViewById(R.id.alert_title));
accessibleTitle.setText(titleText);
accessibleTitle.setFocusable(true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
accessibleTitle.setAccessibilityHeading(true);
} else {
ViewCompat.setAccessibilityDelegate(
accessibleTitle,
new AccessibilityDelegateCompat() {
@Override
public void onInitializeAccessibilityNodeInfo(
View view, AccessibilityNodeInfoCompat info) {
super.onInitializeAccessibilityNodeInfo(accessibleTitle, info);
info.setHeading(true);
}
});
}
return titleContainer;
}
/**
* Creates a dialog compatible only with AppCompat activities. This function should be kept in
* sync with {@link createAppDialog}.
*/
private static Dialog createAppCompatDialog(
Context activityContext, Bundle arguments, DialogInterface.OnClickListener fragment) {
AlertDialog.Builder builder = new AlertDialog.Builder(activityContext);
AlertDialog.Builder builder =
new AlertDialog.Builder(activityContext).setTitle(arguments.getString(ARG_TITLE));
if (arguments.containsKey(ARG_TITLE)) {
String title = Assertions.assertNotNull(arguments.getString(ARG_TITLE));
View accessibleTitle = getAccessibleTitle(activityContext, title);
builder.setCustomTitle(accessibleTitle);
}
if (arguments.containsKey(ARG_BUTTON_POSITIVE)) {
builder.setPositiveButton(arguments.getString(ARG_BUTTON_POSITIVE), fragment);
}
@@ -154,13 +105,10 @@ public class AlertFragment extends DialogFragment implements DialogInterface.OnC
@Deprecated(since = "0.75.0", forRemoval = true)
private static Dialog createAppDialog(
Context activityContext, Bundle arguments, DialogInterface.OnClickListener fragment) {
android.app.AlertDialog.Builder builder = new android.app.AlertDialog.Builder(activityContext);
android.app.AlertDialog.Builder builder =
new android.app.AlertDialog.Builder(activityContext)
.setTitle(arguments.getString(ARG_TITLE));
if (arguments.containsKey(ARG_TITLE)) {
String title = Assertions.assertNotNull(arguments.getString(ARG_TITLE));
View accessibleTitle = getAccessibleTitle(activityContext, title);
builder.setCustomTitle(accessibleTitle);
}
if (arguments.containsKey(ARG_BUTTON_POSITIVE)) {
builder.setPositiveButton(arguments.getString(ARG_BUTTON_POSITIVE), fragment);
}
@@ -17,6 +17,6 @@ public class ReactNativeVersion {
public static final Map<String, Object> VERSION = MapBuilder.<String, Object>of(
"major", 0,
"minor", 76,
"patch", 0,
"prerelease", "rc.4");
"patch", 2,
"prerelease", null);
}
@@ -15,13 +15,13 @@ import android.preference.PreferenceManager
import com.facebook.common.logging.FLog
import com.facebook.react.modules.systeminfo.AndroidInfoHelpers
public class PackagerConnectionSettings(private val appContext: Context) {
public open class PackagerConnectionSettings(private val appContext: Context) {
private val preferences: SharedPreferences =
PreferenceManager.getDefaultSharedPreferences(appContext)
public val packageName: String = appContext.packageName
private val _additionalOptionsForPackager: MutableMap<String, String> = mutableMapOf()
public var debugServerHost: String
public open var debugServerHost: String
get() {
// Check host setting first. If empty try to detect emulator type and use default
// hostname for those
@@ -22,7 +22,7 @@ import com.facebook.yoga.YogaConstants
public abstract class BaseViewManagerDelegate<T : View, U : BaseViewManagerInterface<T>>(
@Suppress("NoHungarianNotation") @JvmField protected val mViewManager: U
) : ViewManagerDelegate<T> {
override public fun setProperty(view: T, propName: String, value: Any?) {
override public fun setProperty(view: T, propName: String?, value: Any?) {
when (propName) {
ViewProps.ACCESSIBILITY_ACTIONS ->
mViewManager.setAccessibilityActions(view, value as ReadableArray?)
@@ -104,6 +104,6 @@ public abstract class BaseViewManagerDelegate<T : View, U : BaseViewManagerInter
}
}
override public fun receiveCommand(view: T, commandName: String, args: ReadableArray?): Unit =
override public fun receiveCommand(view: T, commandName: String?, args: ReadableArray?): Unit =
Unit
}
@@ -18,7 +18,24 @@ import com.facebook.react.bridge.ReadableArray
* @param <T> the type of the view supported by this delegate </T>
*/
public interface ViewManagerDelegate<T : View?> {
public fun setProperty(view: T, propName: String, value: Any?)
public fun receiveCommand(view: T, commandName: String, args: ReadableArray?)
/**
* Sets a property on a view managed by this view manager.
*
* @param view the view to set the property on
* @param propName the name of the property to set (NOTE: should be `String` but is kept as
* `String?` to avoid breaking changes)
* @param value the value to set the property to
*/
public fun setProperty(view: T, propName: String?, value: Any?)
/**
* Executes a command from JS to the view
*
* @param view the view to execute the command on
* @param commandName the name of the command to execute (NOTE: should be `String` but is kept as
* `String?` to avoid breaking changes)
* @param args the arguments to pass to the command
*/
public fun receiveCommand(view: T, commandName: String?, args: ReadableArray?)
}
@@ -26,6 +26,7 @@ import android.view.WindowManager
import android.view.accessibility.AccessibilityEvent
import android.widget.FrameLayout
import androidx.annotation.UiThread
import com.facebook.common.logging.FLog
import com.facebook.react.R
import com.facebook.react.bridge.GuardedRunnable
import com.facebook.react.bridge.LifecycleEventListener
@@ -33,6 +34,7 @@ import com.facebook.react.bridge.ReactContext
import com.facebook.react.bridge.UiThreadUtil
import com.facebook.react.bridge.WritableMap
import com.facebook.react.bridge.WritableNativeMap
import com.facebook.react.common.ReactConstants
import com.facebook.react.common.annotations.VisibleForTesting
import com.facebook.react.config.ReactFeatureFlags
import com.facebook.react.uimanager.JSPointerDispatcher
@@ -294,7 +296,14 @@ public class ReactModalHostView(context: ThemedReactContext) :
* changed. This has the pleasant side-effect of us not having to preface all Modals with "top:
* statusBarHeight", since that margin will be included in the FrameLayout.
*/
get() = FrameLayout(context).apply { addView(dialogRootViewGroup) }
get() =
FrameLayout(context).apply {
addView(dialogRootViewGroup)
if (!statusBarTranslucent) {
// this is needed to prevent content hiding behind systems bars < API 30
this.fitsSystemWindows = true
}
}
/**
* updateProperties will update the properties that do not require us to recreate the dialog
@@ -306,29 +315,37 @@ public class ReactModalHostView(context: ThemedReactContext) :
val dialogWindow =
checkNotNull(dialog.window) { "dialog must have window when we call updateProperties" }
val currentActivity = getCurrentActivity()
if (currentActivity == null || currentActivity.isFinishing) {
if (currentActivity == null || currentActivity.isFinishing || currentActivity.isDestroyed) {
// If the activity has disappeared, then we shouldn't update the window associated to the
// Dialog.
return
}
val activityWindow = currentActivity.window
if (activityWindow != null) {
val activityWindowFlags = activityWindow.attributes.flags
if ((activityWindowFlags and WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0) {
dialogWindow.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
} else {
dialogWindow.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
try {
val activityWindow = currentActivity.window
if (activityWindow != null) {
val activityWindowFlags = activityWindow.attributes.flags
if ((activityWindowFlags and WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0) {
dialogWindow.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
} else {
dialogWindow.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
}
}
}
dialogWindow.setStatusBarTranslucency(statusBarTranslucent)
dialogWindow.setStatusBarTranslucency(statusBarTranslucent)
if (transparent) {
dialogWindow.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
} else {
dialogWindow.setDimAmount(0.5f)
dialogWindow.setFlags(
WindowManager.LayoutParams.FLAG_DIM_BEHIND, WindowManager.LayoutParams.FLAG_DIM_BEHIND)
if (transparent) {
dialogWindow.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
} else {
dialogWindow.setDimAmount(0.5f)
dialogWindow.setFlags(
WindowManager.LayoutParams.FLAG_DIM_BEHIND, WindowManager.LayoutParams.FLAG_DIM_BEHIND)
}
} catch (e: IllegalArgumentException) {
// This is to prevent a crash from the following error, without a clear repro steps:
// java.lang.IllegalArgumentException: View=DecorView@c94931b[XxxActivity] not attached to
// window manager
FLog.e(
ReactConstants.TAG, "ReactModalHostView: error while setting window flags: ", e.message)
}
}
@@ -1,22 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical|start"
android:orientation="horizontal"
android:paddingStart="?android:attr/dialogPreferredPadding"
android:paddingTop="18dp"
android:paddingEnd="?android:attr/dialogPreferredPadding">
<TextView
android:id="@+id/alert_title"
style="?android:attr/windowTitleStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true"
android:textAlignment="viewStart"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textSize="18sp" />
</LinearLayout>
@@ -92,7 +92,7 @@ class RootViewTest {
val eventEmitterModuleMock = mock(RCTEventEmitter::class.java)
whenever(catalystInstanceMock.getNativeModule(UIManagerModule::class.java))
.thenReturn(uiManager)
whenever(uiManager.getEventDispatcher()).thenReturn(eventDispatcher)
whenever(uiManager.eventDispatcher).thenReturn(eventDispatcher)
// RootView IDs is React Native follow the 11, 21, 31, ... progression.
val rootViewId = 11
@@ -86,7 +86,7 @@ class NativeAnimatedNodeTraversalTest {
uiManagerMock = mock(UIManagerModule::class.java)
eventDispatcherMock = mock(EventDispatcher::class.java)
whenever(uiManagerMock.getEventDispatcher()).thenAnswer { eventDispatcherMock }
whenever(uiManagerMock.eventDispatcher).thenAnswer { eventDispatcherMock }
whenever(uiManagerMock.constants).thenAnswer {
mapOf("customDirectEventTypes" to emptyMap<Any, Any>())
}
@@ -488,7 +488,7 @@ class TouchEventDispatchTest {
spy(FabricUIManager(reactContext, viewManagerRegistry, batchEventDispatchedListener))
uiManager.initialize()
eventDispatcher = uiManager.getEventDispatcher()
eventDispatcher = uiManager.eventDispatcher
// Ignore scheduled choreographer work
val reactChoreographerMock = mock(ReactChoreographer::class.java)
@@ -17,6 +17,7 @@ import com.facebook.react.bridge.UIManagerListener
import com.facebook.react.bridge.WritableMap
import com.facebook.react.common.annotations.UnstableReactNativeAPI
import com.facebook.react.fabric.interop.UIBlockViewResolver
import com.facebook.react.uimanager.events.EventDispatcher
@OptIn(UnstableReactNativeAPI::class)
class FakeUIManager : UIManager, UIBlockViewResolver {
@@ -65,7 +66,10 @@ class FakeUIManager : UIManager, UIBlockViewResolver {
error("Not yet implemented")
}
override fun <T : Any?> getEventDispatcher(): T {
override val eventDispatcher: EventDispatcher
get() = TODO("Not yet implemented")
fun <T : Any?> getEventDispatcher(): T {
error("Not yet implemented")
}
@@ -17,8 +17,8 @@ namespace facebook::react {
constexpr struct {
int32_t Major = 0;
int32_t Minor = 76;
int32_t Patch = 0;
std::string_view Prerelease = "rc.4";
int32_t Patch = 2;
std::string_view Prerelease = "";
} ReactNativeVersion;
} // namespace facebook::react
@@ -83,7 +83,7 @@ AttributedString TextInputShadowNode::getAttributedString(
.string = getConcreteProps().text,
.textAttributes = textAttributes,
// TODO: Is this really meant to be by value?
.parentShadowView = ShadowView{}});
.parentShadowView = ShadowView(*this)});
auto attachments = Attachments{};
BaseTextShadowNode::buildAttributedString(
@@ -110,7 +110,8 @@ void TextInputShadowNode::updateStateIfNeeded(
(!state.layoutManager || state.layoutManager == textLayoutManager_) &&
"`StateData` refers to a different `TextLayoutManager`");
if (state.reactTreeAttributedString == reactTreeAttributedString &&
if (state.reactTreeAttributedString.isContentEqual(
reactTreeAttributedString) &&
state.layoutManager == textLayoutManager_) {
return;
}
@@ -22,7 +22,7 @@ NSString *const RCTTextAttributesAccessibilityRoleAttributeName = @"Accessibilit
/*
* Creates `NSTextAttributes` from given `facebook::react::TextAttributes`
*/
NSDictionary<NSAttributedStringKey, id> *RCTNSTextAttributesFromTextAttributes(
NSMutableDictionary<NSAttributedStringKey, id> *RCTNSTextAttributesFromTextAttributes(
const facebook::react::TextAttributes &textAttributes);
/*
@@ -41,6 +41,17 @@ NSString *RCTNSStringFromStringApplyingTextTransform(NSString *string, facebook:
void RCTApplyBaselineOffset(NSMutableAttributedString *attributedText);
/*
* Whether two `NSAttributedString` lead to the same underlying displayed text, even if they are not strictly equal.
* I.e. is one string substitutable for the other when backing a control (which may have some ignorable attributes
* provided).
*/
BOOL RCTIsAttributedStringEffectivelySame(
NSAttributedString *text1,
NSAttributedString *text2,
NSDictionary<NSAttributedStringKey, id> *insensitiveAttributes,
const facebook::react::TextAttributes &baseTextAttributes);
@interface RCTWeakEventEmitterWrapper : NSObject
@property (nonatomic, assign) facebook::react::SharedEventEmitter eventEmitter;
@end
@@ -35,6 +35,24 @@ using namespace facebook::react;
_weakEventEmitter.reset();
}
- (BOOL)isEqual:(id)object
{
// We consider the underlying EventEmitter as the identity
if (![object isKindOfClass:[self class]]) {
return NO;
}
auto thisEventEmitter = [self eventEmitter];
auto otherEventEmitter = [((RCTWeakEventEmitterWrapper *)object) eventEmitter];
return thisEventEmitter == otherEventEmitter;
}
- (NSUInteger)hash
{
// We consider the underlying EventEmitter as the identity
return (NSUInteger)_weakEventEmitter.lock().get();
}
@end
inline static UIFontWeight RCTUIFontWeightFromInteger(NSInteger fontWeight)
@@ -178,7 +196,8 @@ inline static UIColor *RCTEffectiveBackgroundColorFromTextAttributes(const TextA
return effectiveBackgroundColor ?: [UIColor clearColor];
}
NSDictionary<NSAttributedStringKey, id> *RCTNSTextAttributesFromTextAttributes(const TextAttributes &textAttributes)
NSMutableDictionary<NSAttributedStringKey, id> *RCTNSTextAttributesFromTextAttributes(
const TextAttributes &textAttributes)
{
NSMutableDictionary<NSAttributedStringKey, id> *attributes = [NSMutableDictionary dictionaryWithCapacity:10];
@@ -302,7 +321,7 @@ NSDictionary<NSAttributedStringKey, id> *RCTNSTextAttributesFromTextAttributes(c
attributes[RCTTextAttributesAccessibilityRoleAttributeName] = [NSString stringWithUTF8String:roleStr.c_str()];
}
return [attributes copy];
return attributes;
}
void RCTApplyBaselineOffset(NSMutableAttributedString *attributedText)
@@ -466,3 +485,147 @@ NSString *RCTNSStringFromStringApplyingTextTransform(NSString *string, TextTrans
return string;
}
}
static BOOL RCTIsParagraphStyleEffectivelySame(
NSParagraphStyle *style1,
NSParagraphStyle *style2,
const TextAttributes &baseTextAttributes)
{
if (style1 == nil || style2 == nil) {
return style1 == nil && style2 == nil;
}
// The NSParagraphStyle included as part of typingAttributes may eventually resolve "natural" directions to
// physical direction, so we should compare resolved directions
auto naturalAlignment =
baseTextAttributes.layoutDirection.value_or(LayoutDirection::LeftToRight) == LayoutDirection::LeftToRight
? NSTextAlignmentLeft
: NSTextAlignmentRight;
NSWritingDirection naturalBaseWritingDirection = baseTextAttributes.baseWritingDirection.has_value()
? RCTNSWritingDirectionFromWritingDirection(baseTextAttributes.baseWritingDirection.value())
: [NSParagraphStyle defaultWritingDirectionForLanguage:nil];
if (style1.alignment == NSTextAlignmentNatural || style1.baseWritingDirection == NSWritingDirectionNatural) {
NSMutableParagraphStyle *mutableStyle1 = [style1 mutableCopy];
style1 = mutableStyle1;
if (mutableStyle1.alignment == NSTextAlignmentNatural) {
mutableStyle1.alignment = naturalAlignment;
}
if (mutableStyle1.baseWritingDirection == NSWritingDirectionNatural) {
mutableStyle1.baseWritingDirection = naturalBaseWritingDirection;
}
}
if (style2.alignment == NSTextAlignmentNatural || style2.baseWritingDirection == NSWritingDirectionNatural) {
NSMutableParagraphStyle *mutableStyle2 = [style2 mutableCopy];
style2 = mutableStyle2;
if (mutableStyle2.alignment == NSTextAlignmentNatural) {
mutableStyle2.alignment = naturalAlignment;
}
if (mutableStyle2.baseWritingDirection == NSWritingDirectionNatural) {
mutableStyle2.baseWritingDirection = naturalBaseWritingDirection;
}
}
return [style1 isEqual:style2];
}
static BOOL RCTIsAttributeEffectivelySame(
NSAttributedStringKey attributeKey,
NSDictionary<NSAttributedStringKey, id> *attributes1,
NSDictionary<NSAttributedStringKey, id> *attributes2,
NSDictionary<NSAttributedStringKey, id> *insensitiveAttributes,
const TextAttributes &baseTextAttributes)
{
id attribute1 = attributes1[attributeKey] ?: insensitiveAttributes[attributeKey];
id attribute2 = attributes2[attributeKey] ?: insensitiveAttributes[attributeKey];
// Normalize attributes which can inexact but still effectively the same
if ([attributeKey isEqualToString:NSParagraphStyleAttributeName]) {
return RCTIsParagraphStyleEffectivelySame(attribute1, attribute2, baseTextAttributes);
}
// Otherwise rely on built-in comparison
return [attribute1 isEqual:attribute2];
}
BOOL RCTIsAttributedStringEffectivelySame(
NSAttributedString *text1,
NSAttributedString *text2,
NSDictionary<NSAttributedStringKey, id> *insensitiveAttributes,
const TextAttributes &baseTextAttributes)
{
if (![text1.string isEqualToString:text2.string]) {
return NO;
}
// We check that for every fragment in the old string
// 1. The new string's fragment overlapping the first spans the same characters
// 2. The attributes of each matching fragment are the same, ignoring those which match insensitive attibutes
__block BOOL areAttributesSame = YES;
[text1 enumerateAttributesInRange:NSMakeRange(0, text1.length)
options:0
usingBlock:^(
NSDictionary<NSAttributedStringKey, id> *text1Attributes,
NSRange text1Range,
BOOL *text1Stop) {
[text2 enumerateAttributesInRange:text1Range
options:0
usingBlock:^(
NSDictionary<NSAttributedStringKey, id> *text2Attributes,
NSRange text2Range,
BOOL *text2Stop) {
if (!NSEqualRanges(text1Range, text2Range)) {
areAttributesSame = NO;
*text1Stop = YES;
*text2Stop = YES;
return;
}
// Compare every attribute in text1 to the corresponding attribute
// in text2, or the set of insensitive attributes if not present
for (NSAttributedStringKey key in text1Attributes) {
if (!RCTIsAttributeEffectivelySame(
key,
text1Attributes,
text2Attributes,
insensitiveAttributes,
baseTextAttributes)) {
areAttributesSame = NO;
*text1Stop = YES;
*text2Stop = YES;
return;
}
}
for (NSAttributedStringKey key in text2Attributes) {
// We have already compared this attribute if it is present in
// both
if (text1Attributes[key] != nil) {
continue;
}
// But we still need to compare attributes if it is only present
// in text 2, to compare against insensitive attributes
if (!RCTIsAttributeEffectivelySame(
key,
text1Attributes,
text2Attributes,
insensitiveAttributes,
baseTextAttributes)) {
areAttributesSame = NO;
*text1Stop = YES;
*text2Stop = YES;
return;
}
}
}];
}];
return areAttributesSame;
}
+1 -1
View File
@@ -204,7 +204,7 @@ async function main() {
const proc = spawn(
'npx',
['@react-native-community/cli', ...process.argv.slice(2)],
['@react-native-community/cli@latest', ...process.argv.slice(2)],
{
stdio: 'inherit',
},
+10 -10
View File
@@ -1,6 +1,6 @@
{
"name": "react-native",
"version": "0.76.0-rc.4",
"version": "0.76.2",
"description": "A framework for building native apps using React",
"license": "MIT",
"repository": {
@@ -109,13 +109,13 @@
},
"dependencies": {
"@jest/create-cache-key-function": "^29.6.3",
"@react-native/assets-registry": "0.76.0-rc.4",
"@react-native/codegen": "0.76.0-rc.4",
"@react-native/community-cli-plugin": "0.76.0-rc.4",
"@react-native/gradle-plugin": "0.76.0-rc.4",
"@react-native/js-polyfills": "0.76.0-rc.4",
"@react-native/normalize-colors": "0.76.0-rc.4",
"@react-native/virtualized-lists": "0.76.0-rc.4",
"@react-native/assets-registry": "0.76.2",
"@react-native/codegen": "0.76.2",
"@react-native/community-cli-plugin": "0.76.2",
"@react-native/gradle-plugin": "0.76.2",
"@react-native/js-polyfills": "0.76.2",
"@react-native/normalize-colors": "0.76.2",
"@react-native/virtualized-lists": "0.76.2",
"abort-controller": "^3.0.0",
"anser": "^1.4.9",
"ansi-regex": "^5.0.0",
@@ -131,8 +131,8 @@
"jest-environment-node": "^29.6.3",
"jsc-android": "^250231.0.0",
"memoize-one": "^5.0.0",
"metro-runtime": "^0.81.0-alpha.2",
"metro-source-map": "^0.81.0-alpha.2",
"metro-runtime": "^0.81.0",
"metro-source-map": "^0.81.0",
"mkdirp": "^0.5.1",
"nullthrows": "^1.1.1",
"pretty-format": "^29.7.0",
@@ -12,19 +12,33 @@ class NewArchitectureHelper
@@NewArchWarningEmitted = false # Used not to spam warnings to the user.
def self.set_clang_cxx_language_standard_if_needed(installer)
cxxBuildsettingsName = "CLANG_CXX_LANGUAGE_STANDARD"
projects = installer.aggregate_targets
.map{ |t| t.user_project }
.uniq{ |p| p.path }
projects.each do |project|
Pod::UI.puts("Setting CLANG_CXX_LANGUAGE_STANDARD to #{ Helpers::Constants::cxx_language_standard } on #{ project.path }")
Pod::UI.puts("Setting #{cxxBuildsettingsName} to #{ Helpers::Constants::cxx_language_standard } on #{ project.path }")
project.build_configurations.each do |config|
config.build_settings["CLANG_CXX_LANGUAGE_STANDARD"] = Helpers::Constants::cxx_language_standard
config.build_settings[cxxBuildsettingsName] = Helpers::Constants::cxx_language_standard
end
project.save()
end
installer.target_installation_results.pod_target_installation_results.each do |pod_name, target_installation_result|
target_installation_result.native_target.build_configurations.each do |config|
config.build_settings[cxxBuildsettingsName] = Helpers::Constants::cxx_language_standard
end
end
# Override targets that would set spec.xcconfig to define c++ version
installer.aggregate_targets.each do |aggregate_target|
aggregate_target.xcconfigs.each do |config_name, config_file|
config_file.attributes[cxxBuildsettingsName] = Helpers::Constants::cxx_language_standard
end
end
end
def self.computeFlags(is_new_arch_enabled)
@@ -3,6 +3,8 @@
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
require 'shellwords'
require_relative "./helpers.rb"
# Utilities class for React Native Cocoapods
@@ -237,8 +239,8 @@ class ReactNativePodsUtils
# When installing pods with a yarn alias, yarn creates a fake yarn and node executables
# in a temporary folder.
# Using `node --print "process.argv[0]";` we are able to retrieve the actual path from which node is running.
# see https://github.com/facebook/react-native/issues/43285 for more info
node_binary = `node --print "process.argv[0]";`
# see https://github.com/facebook/react-native/issues/43285 for more info. We've tweaked this slightly.
node_binary = Shellwords.escape(`node --print "process.argv[0]"`.strip)
system("echo 'export NODE_BINARY=#{node_binary}' > #{file_path}.local")
end
end
@@ -489,11 +489,22 @@ function rootCodegenTargetNeedsThirdPartyComponentProvider(pkgJson, platform) {
return !pkgJsonIncludesGeneratedCode(pkgJson) && platform === 'ios';
}
function dependencyNeedsThirdPartyComponentProvider(schemaInfo, platform) {
function dependencyNeedsThirdPartyComponentProvider(
schemaInfo,
platform,
appCodegenConfigSpec,
) {
// Filter the react native core library out.
// In the future, core library and third party library should
// use the same way to generate/register the fabric components.
return !isReactNativeCoreLibrary(schemaInfo.library.config.name, platform);
// We also have to filter out the the components defined in the app
// because the RCTThirdPartyComponentProvider is generated inside Fabric,
// which lives in a different target from the app and it has no visibility over
// the symbols defined in the app.
return (
!isReactNativeCoreLibrary(schemaInfo.library.config.name, platform) &&
schemaInfo.library.config.name !== appCodegenConfigSpec
);
}
function mustGenerateNativeCode(includeLibraryPath, schemaInfo) {
@@ -704,8 +715,12 @@ function execute(projectRoot, targetPlatform, baseOutputPath) {
if (
rootCodegenTargetNeedsThirdPartyComponentProvider(pkgJson, platform)
) {
const filteredSchemas = schemaInfos.filter(
dependencyNeedsThirdPartyComponentProvider,
const filteredSchemas = schemaInfos.filter(schemaInfo =>
dependencyNeedsThirdPartyComponentProvider(
schemaInfo,
platform,
pkgJson.codegenConfig?.name,
),
);
const schemas = filteredSchemas.map(schemaInfo => schemaInfo.schema);
const supportedApplePlatforms = filteredSchemas.map(
+1 -1
View File
@@ -1 +1 @@
hermes-2024-09-09-RNv0.76.0-db6d12e202e15f7a446d8848d6ca8f7abb3cfb32
hermes-2024-11-12-RNv0.76.2-5b4aa20c719830dcf5684832b89a6edb95ac3d64
+6
View File
@@ -41,6 +41,7 @@ declare module 'react-native/Libraries/Utilities/codegenNativeComponent' {
declare module 'react-native/Libraries/Types/CodegenTypes' {
import type {NativeSyntheticEvent} from 'react-native';
import type {EventSubscription} from 'react-native/Libraries/vendor/emitter/EventEmitter';
// Event types
// We're not using the PaperName, it is only used to codegen view config settings
@@ -59,6 +60,7 @@ declare module 'react-native/Libraries/Types/CodegenTypes' {
export type Float = number;
export type Int32 = number;
export type UnsafeObject = object;
export type UnsafeMixed = unknown;
type DefaultTypes = number | boolean | string | ReadonlyArray<string>;
// Default handling, ignore the unused value
@@ -71,4 +73,8 @@ declare module 'react-native/Libraries/Types/CodegenTypes' {
Type extends DefaultTypes,
Value extends Type | string | undefined | null,
> = Type | undefined | null;
export type EventEmitter<T> = (
handler: (arg: T) => void | Promise<void>,
) => EventSubscription;
}
+1
View File
@@ -8,3 +8,4 @@ ruby ">= 2.6.10"
gem 'cocoapods', '~> 1.13', '!= 1.15.0', '!= 1.15.1'
gem 'rexml'
gem 'activesupport', '>= 6.1.7.5', '< 7.1.0'
gem 'xcodeproj', '< 1.26.0'
File diff suppressed because it is too large Load Diff
+6 -6
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/tester",
"version": "0.76.0-rc.4",
"version": "0.76.2",
"private": true,
"description": "React Native tester app.",
"license": "MIT",
@@ -23,8 +23,8 @@
"clean-ios": "rm -rf build/generated/ios Pods Podfile.lock"
},
"dependencies": {
"@react-native/oss-library-example": "0.76.0-rc.4",
"@react-native/popup-menu-android": "0.76.0-rc.4",
"@react-native/oss-library-example": "0.76.2",
"@react-native/popup-menu-android": "0.76.2",
"flow-enums-runtime": "^0.0.6",
"invariant": "^2.2.4",
"nullthrows": "^1.1.1"
@@ -42,8 +42,8 @@
}
},
"devDependencies": {
"@react-native-community/cli": "15.0.0-alpha.2",
"@react-native-community/cli-platform-android": "15.0.0-alpha.2",
"@react-native-community/cli-platform-ios": "15.0.0-alpha.2"
"@react-native-community/cli": "15.0.1",
"@react-native-community/cli-platform-android": "15.0.1",
"@react-native-community/cli-platform-ios": "15.0.1"
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/typescript-config",
"version": "0.76.0-rc.4",
"version": "0.76.2",
"description": "Default TypeScript configuration for React Native apps",
"license": "MIT",
"repository": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/virtualized-lists",
"version": "0.76.0-rc.4",
"version": "0.76.2",
"description": "Virtualized lists for React Native.",
"license": "MIT",
"repository": {
+240 -168
View File
@@ -1091,7 +1091,18 @@
"@babel/plugin-transform-modules-commonjs" "^7.24.7"
"@babel/plugin-transform-typescript" "^7.24.7"
"@babel/register@^7.13.16", "@babel/register@^7.24.6":
"@babel/register@7.22.5":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.22.5.tgz#e4d8d0f615ea3233a27b5c6ada6750ee59559939"
integrity sha512-vV6pm/4CijSQ8Y47RH5SopXzursN35RQINfGJkmOlcpAtGuf94miFvIPhCKGQN7WGIcsgG1BHEX2KVdTYwTwUQ==
dependencies:
clone-deep "^4.0.1"
find-cache-dir "^2.0.0"
make-dir "^2.1.0"
pirates "^4.0.5"
source-map-support "^0.5.16"
"@babel/register@^7.13.16":
version "7.24.6"
resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.24.6.tgz#59e21dcc79e1d04eed5377633b0f88029a6bef9e"
integrity sha512-WSuFCc2wCqMeXkz/i3yfAAsxwWflEgbVkZzivgAmXl/MxrXeoYFZOOPllbC8R8WTF7u61wSRQtDVZ1879cdu6w==
@@ -1123,7 +1134,20 @@
"@babel/parser" "^7.25.0"
"@babel/types" "^7.25.0"
"@babel/traverse--for-generate-function-map@npm:@babel/traverse@^7.25.3", "@babel/traverse@^7.24.7", "@babel/traverse@^7.24.8", "@babel/traverse@^7.25.0", "@babel/traverse@^7.25.1", "@babel/traverse@^7.25.2", "@babel/traverse@^7.25.3", "@babel/traverse@^7.25.4":
"@babel/traverse--for-generate-function-map@npm:@babel/traverse@^7.25.3":
version "7.25.6"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.25.6.tgz#04fad980e444f182ecf1520504941940a90fea41"
integrity sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==
dependencies:
"@babel/code-frame" "^7.24.7"
"@babel/generator" "^7.25.6"
"@babel/parser" "^7.25.6"
"@babel/template" "^7.25.0"
"@babel/types" "^7.25.6"
debug "^4.3.1"
globals "^11.1.0"
"@babel/traverse@^7.24.7", "@babel/traverse@^7.24.8", "@babel/traverse@^7.25.0", "@babel/traverse@^7.25.1", "@babel/traverse@^7.25.2", "@babel/traverse@^7.25.3", "@babel/traverse@^7.25.4":
version "7.25.6"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.25.6.tgz#04fad980e444f182ecf1520504941940a90fea41"
integrity sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==
@@ -1747,45 +1771,55 @@
optionalDependencies:
npmlog "2 || ^3.1.0 || ^4.0.0"
"@react-native-community/cli-clean@15.0.0-alpha.2":
version "15.0.0-alpha.2"
resolved "https://registry.yarnpkg.com/@react-native-community/cli-clean/-/cli-clean-15.0.0-alpha.2.tgz#c6598086cd1432deaa2bed82f6d2833feb112091"
integrity sha512-QNq5lZpoxGHIneKBB1S8hSpvgFYGST7CP1GWrgrmOaIieNFsh2oWhTePzGyxUgxr0i0qzolmWwuwqqyIPMUSyQ==
"@react-native-community/cli-clean@15.0.1":
version "15.0.1"
resolved "https://registry.yarnpkg.com/@react-native-community/cli-clean/-/cli-clean-15.0.1.tgz#80ce09ffe0d62bb265447007f24dc8dcbf8fe7d3"
integrity sha512-flGTfT005UZvW2LAXVowZ/7ri22oiiZE4pPgMvc8klRxO5uofKIRuohgiHybHtiCo/HNqIz45JmZJvuFrhc4Ow==
dependencies:
"@react-native-community/cli-tools" "15.0.0-alpha.2"
"@react-native-community/cli-tools" "15.0.1"
chalk "^4.1.2"
execa "^5.0.0"
fast-glob "^3.3.2"
"@react-native-community/cli-config@15.0.0-alpha.2":
version "15.0.0-alpha.2"
resolved "https://registry.yarnpkg.com/@react-native-community/cli-config/-/cli-config-15.0.0-alpha.2.tgz#fe535e9174593041ec0c8e6abbb9cb4127195315"
integrity sha512-gkmVP7s5sR74HOz2unPsRdNTEmwQyzpeEcB2OI3g35WAyccpYO7OpmpE1PlQ0O9qKdQlQJKbL7fq2DhqswVAdg==
"@react-native-community/cli-config-apple@15.0.1":
version "15.0.1"
resolved "https://registry.yarnpkg.com/@react-native-community/cli-config-apple/-/cli-config-apple-15.0.1.tgz#2d845599eada1b479df6716a25dc871c3d202f38"
integrity sha512-GEHUx4NRp9W9or6vygn0TgNeFkcJdNjrtko0vQEJAS4gJdWqP/9LqqwJNlUfaW5jHBN7TKALAMlfRmI12Op3sg==
dependencies:
"@react-native-community/cli-tools" "15.0.0-alpha.2"
"@react-native-community/cli-tools" "15.0.1"
chalk "^4.1.2"
execa "^5.0.0"
fast-glob "^3.3.2"
"@react-native-community/cli-config@15.0.1":
version "15.0.1"
resolved "https://registry.yarnpkg.com/@react-native-community/cli-config/-/cli-config-15.0.1.tgz#fe44472757ebca4348fe4861ceaf9d4daff26767"
integrity sha512-SL3/9zIyzQQPKWei0+W1gNHxCPurrxqpODUWnVLoP38DNcvYCGtsRayw/4DsXgprZfBC+FsscNpd3IDJrG59XA==
dependencies:
"@react-native-community/cli-tools" "15.0.1"
chalk "^4.1.2"
cosmiconfig "^9.0.0"
deepmerge "^4.3.0"
fast-glob "^3.3.2"
joi "^17.2.1"
"@react-native-community/cli-debugger-ui@15.0.0-alpha.2":
version "15.0.0-alpha.2"
resolved "https://registry.yarnpkg.com/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-15.0.0-alpha.2.tgz#8ee14142c270c83fb5072050cad4f97e99ec5e5a"
integrity sha512-odOFpsOgbCc2si2+D16eyeY4h4u3qu12XssRGV8VqvhKLh0khQ/wA6y01/1ghy1sA0Pus1LyBwFEix6X3epXBw==
"@react-native-community/cli-debugger-ui@15.0.1":
version "15.0.1"
resolved "https://registry.yarnpkg.com/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-15.0.1.tgz#bed0d7af5ecb05222bdb7d6e74e21326a583bcf1"
integrity sha512-xkT2TLS8zg5r7Vl9l/2f7JVUoFECnVBS+B5ivrSu2PNZhKkr9lRmJFxC9aVLFb5lIxQQKNDvEyiIDNfP7wjJiA==
dependencies:
serve-static "^1.13.1"
"@react-native-community/cli-doctor@15.0.0-alpha.2":
version "15.0.0-alpha.2"
resolved "https://registry.yarnpkg.com/@react-native-community/cli-doctor/-/cli-doctor-15.0.0-alpha.2.tgz#d83c4146111c5f3c2e2468d6cdcb4e76ed0e4e37"
integrity sha512-kcBwSUMmD0AGP+kvlxTkzGlMLxOqCZIJ6pBbpnTPAhSjYrvYzHNZTTYqeggcACR7mlERot0t6tJvXeGHP1s59g==
"@react-native-community/cli-doctor@15.0.1":
version "15.0.1"
resolved "https://registry.yarnpkg.com/@react-native-community/cli-doctor/-/cli-doctor-15.0.1.tgz#63cc42e7302f2bfa3739b29fea57b68d5d68fa03"
integrity sha512-YCu44lZR3zZxJJYVTqYZFz9cT9KBfbKI4q2MnKOvkamt00XY3usooMqfuwBAdvM/yvpx7M5w8kbM/nPyj4YCvQ==
dependencies:
"@react-native-community/cli-config" "15.0.0-alpha.2"
"@react-native-community/cli-platform-android" "15.0.0-alpha.2"
"@react-native-community/cli-platform-apple" "15.0.0-alpha.2"
"@react-native-community/cli-platform-ios" "15.0.0-alpha.2"
"@react-native-community/cli-tools" "15.0.0-alpha.2"
"@react-native-community/cli-config" "15.0.1"
"@react-native-community/cli-platform-android" "15.0.1"
"@react-native-community/cli-platform-apple" "15.0.1"
"@react-native-community/cli-platform-ios" "15.0.1"
"@react-native-community/cli-tools" "15.0.1"
chalk "^4.1.2"
command-exists "^1.2.8"
deepmerge "^4.3.0"
@@ -1798,44 +1832,43 @@
wcwidth "^1.0.1"
yaml "^2.2.1"
"@react-native-community/cli-platform-android@15.0.0-alpha.2":
version "15.0.0-alpha.2"
resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-android/-/cli-platform-android-15.0.0-alpha.2.tgz#479f743086fb3c853d9a8038e26035d25776db7c"
integrity sha512-cKHbENaYreKCRtF8cSgTX3mn8XeupTVNzF57tWtOq6Prs+9Bd8ZsOylFZEvkyb3wY1S+BFDAXebAGzbL9ZlY3w==
"@react-native-community/cli-platform-android@15.0.1":
version "15.0.1"
resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-android/-/cli-platform-android-15.0.1.tgz#9706fe454d0e2af4680c3ea1937830c93041a35f"
integrity sha512-QlAMomj6H6TY6pHwjTYMsHDQLP5eLzjAmyW1qb03w/kyS/72elK2bjsklNWJrscFY9TMQLqw7qoAsXf1m5t/dg==
dependencies:
"@react-native-community/cli-tools" "15.0.0-alpha.2"
"@react-native-community/cli-tools" "15.0.1"
chalk "^4.1.2"
execa "^5.0.0"
fast-glob "^3.3.2"
fast-xml-parser "^4.4.1"
logkitty "^0.7.1"
"@react-native-community/cli-platform-apple@15.0.0-alpha.2":
version "15.0.0-alpha.2"
resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-apple/-/cli-platform-apple-15.0.0-alpha.2.tgz#561272ec7bf6cbedf8737cf1b71566b63e9b704b"
integrity sha512-eXE6KES4mNWQA1c/d+aWQnNsgjD7rdrsMAH4t0xOhXn4XWCw1FF6Y7PjUY8fi784RFIzEYB2xiVMvWQsC6BmAQ==
"@react-native-community/cli-platform-apple@15.0.1":
version "15.0.1"
resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-apple/-/cli-platform-apple-15.0.1.tgz#af3c9bc910c96e823a488c21e7d68a9b4a07c8d1"
integrity sha512-iQj1Dt2fr/Q7X2CQhyhWnece3eLDCark1osfiwpViksOfTH2WdpNS3lIwlFcIKhsieFU7YYwbNuFqQ3tF9Dlvw==
dependencies:
"@react-native-community/cli-tools" "15.0.0-alpha.2"
"@react-native-community/cli-config-apple" "15.0.1"
"@react-native-community/cli-tools" "15.0.1"
chalk "^4.1.2"
execa "^5.0.0"
fast-glob "^3.3.2"
fast-xml-parser "^4.4.1"
ora "^5.4.1"
"@react-native-community/cli-platform-ios@15.0.0-alpha.2":
version "15.0.0-alpha.2"
resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-ios/-/cli-platform-ios-15.0.0-alpha.2.tgz#c237e561d60d3aa463d51327b37e6943910f7bb5"
integrity sha512-7teqYOMf7SnBmUbSeGklDS2lJCpAa1LKzmy/L8vFiayWImUTJHKzkJyZNzhmiLSImcibFYVH7uaD2DWuFNcrOQ==
"@react-native-community/cli-platform-ios@15.0.1":
version "15.0.1"
resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-ios/-/cli-platform-ios-15.0.1.tgz#a1cb78c3d43b9c2bbb411a074ef11364f2a94bbf"
integrity sha512-6pKzXEIgGL20eE1uOn8iSsNBlMzO1LG+pQOk+7mvD172EPhKm/lRzUVDX5gO/2jvsGoNw6VUW0JX1FI2firwqA==
dependencies:
"@react-native-community/cli-platform-apple" "15.0.0-alpha.2"
"@react-native-community/cli-platform-apple" "15.0.1"
"@react-native-community/cli-server-api@15.0.0-alpha.2":
version "15.0.0-alpha.2"
resolved "https://registry.yarnpkg.com/@react-native-community/cli-server-api/-/cli-server-api-15.0.0-alpha.2.tgz#37dcfe41cc7204e01290c616c9262e5e71f70424"
integrity sha512-e4bHsl/J006+coMTOpj6i44QPDat/X2s1sc3rqQkFL5vHIduB+Z6IyDI+W9F5uHrJhtQukE5NdajkjcXyjGLVA==
"@react-native-community/cli-server-api@15.0.1":
version "15.0.1"
resolved "https://registry.yarnpkg.com/@react-native-community/cli-server-api/-/cli-server-api-15.0.1.tgz#e7975e7638343248835fd379803d557c0ae24d75"
integrity sha512-f3rb3t1ELLaMSX5/LWO/IykglBIgiP3+pPnyl8GphHnBpf3bdIcp7fHlHLemvHE06YxT2nANRxRPjy1gNskenA==
dependencies:
"@react-native-community/cli-debugger-ui" "15.0.0-alpha.2"
"@react-native-community/cli-tools" "15.0.0-alpha.2"
"@react-native-community/cli-debugger-ui" "15.0.1"
"@react-native-community/cli-tools" "15.0.1"
compression "^1.7.1"
connect "^3.6.5"
errorhandler "^1.5.1"
@@ -1844,10 +1877,10 @@
serve-static "^1.13.1"
ws "^6.2.3"
"@react-native-community/cli-tools@15.0.0-alpha.2":
version "15.0.0-alpha.2"
resolved "https://registry.yarnpkg.com/@react-native-community/cli-tools/-/cli-tools-15.0.0-alpha.2.tgz#0c02c61a30730814925d6c1e08d43b57ec083f24"
integrity sha512-XzjIFizlqLtwHqhFJHbYfedFOIebFEt1bdLSsHi2HSiZQlltW8KTwWiHC1VHfoEpePErvP2/jsx/dZtX7wNNSw==
"@react-native-community/cli-tools@15.0.1":
version "15.0.1"
resolved "https://registry.yarnpkg.com/@react-native-community/cli-tools/-/cli-tools-15.0.1.tgz#3cc5398da72b5d365eb4a30468ebce2bf37fa591"
integrity sha512-N79A+u/94roanfmNohVcNGu6Xg+0idh63JHZFLC9OJJuZwTifGMLDfSTHZATpR1J7rebozQ5ClcSUePavErnSg==
dependencies:
appdirsjs "^1.2.4"
chalk "^4.1.2"
@@ -1856,29 +1889,30 @@
mime "^2.4.1"
open "^6.2.0"
ora "^5.4.1"
prompts "^2.4.2"
semver "^7.5.2"
shell-quote "^1.7.3"
sudo-prompt "^9.0.0"
"@react-native-community/cli-types@15.0.0-alpha.2":
version "15.0.0-alpha.2"
resolved "https://registry.yarnpkg.com/@react-native-community/cli-types/-/cli-types-15.0.0-alpha.2.tgz#12d62c7e928115758bbb7de6ded3d21a57dbb7b9"
integrity sha512-5gLZKQLG4ejrMEzdBw0KaGcX7jTTpWoGypxqL+8sQ7Pkenklfsr1RJRFxv+hzO/yX9psMFMgZUXluLajWwuvcg==
"@react-native-community/cli-types@15.0.1":
version "15.0.1"
resolved "https://registry.yarnpkg.com/@react-native-community/cli-types/-/cli-types-15.0.1.tgz#ebdb5bc76ade44b2820174fdcb2a3a05999686ec"
integrity sha512-sWiJ62kkGu2mgYni2dsPxOMBzpwTjNsDH1ubY4mqcNEI9Zmzs0vRwwDUEhYqwNGys9+KpBKoZRrT2PAlhO84xA==
dependencies:
joi "^17.2.1"
"@react-native-community/cli@15.0.0-alpha.2":
version "15.0.0-alpha.2"
resolved "https://registry.yarnpkg.com/@react-native-community/cli/-/cli-15.0.0-alpha.2.tgz#e465127a176a9eac3f0c1e4a16bd1830627fbbfb"
integrity sha512-Yf7kupKmEuytelafCNeNug4ZAC0i7GPgKVyXfRhwVtVp5ykXtWcng2bqPa4YRl4fgWgu5JhoOQhVMEV1cUDzAA==
"@react-native-community/cli@15.0.1":
version "15.0.1"
resolved "https://registry.yarnpkg.com/@react-native-community/cli/-/cli-15.0.1.tgz#d703d55cc6540ce3d29fd2fbf3303bea0ffd96f2"
integrity sha512-xIGPytx2bj5HxFk0c7S25AVuJowHmEFg5LFC9XosKc0TSOjP1r6zGC6OqC/arQV/pNuqmZN2IFnpgJn0Bn+hhQ==
dependencies:
"@react-native-community/cli-clean" "15.0.0-alpha.2"
"@react-native-community/cli-config" "15.0.0-alpha.2"
"@react-native-community/cli-debugger-ui" "15.0.0-alpha.2"
"@react-native-community/cli-doctor" "15.0.0-alpha.2"
"@react-native-community/cli-server-api" "15.0.0-alpha.2"
"@react-native-community/cli-tools" "15.0.0-alpha.2"
"@react-native-community/cli-types" "15.0.0-alpha.2"
"@react-native-community/cli-clean" "15.0.1"
"@react-native-community/cli-config" "15.0.1"
"@react-native-community/cli-debugger-ui" "15.0.1"
"@react-native-community/cli-doctor" "15.0.1"
"@react-native-community/cli-server-api" "15.0.1"
"@react-native-community/cli-tools" "15.0.1"
"@react-native-community/cli-types" "15.0.1"
chalk "^4.1.2"
commander "^9.4.1"
deepmerge "^4.3.0"
@@ -2810,6 +2844,20 @@ babel-plugin-syntax-hermes-parser@0.23.1, babel-plugin-syntax-hermes-parser@^0.2
dependencies:
hermes-parser "0.23.1"
babel-plugin-syntax-hermes-parser@0.24.0:
version "0.24.0"
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.24.0.tgz#79d0c73daae7bd7d4b07f64ee281c75aa48845cf"
integrity sha512-J4wETqz7ehbyYl2uge65zsfr0Ue+0yJYYMMkGAWpZc0fB02z4JAcx+mJEXVU14yiihGwqVUlR7oS4/gDYOxUdA==
dependencies:
hermes-parser "0.24.0"
babel-plugin-syntax-hermes-parser@^0.25.1:
version "0.25.1"
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.25.1.tgz#58b539df973427fcfbb5176a3aec7e5dee793cb0"
integrity sha512-IVNpGzboFLfXZUAwkLFcI/bnqVbwky0jP3eBno4HKtqvQJAHBLdgxiG6lQ4to0+Q/YCN3PO0od5NZwIKyY4REQ==
dependencies:
hermes-parser "0.25.1"
babel-plugin-syntax-trailing-function-commas@^7.0.0-beta.0:
version "7.0.0-beta.0"
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-7.0.0-beta.0.tgz#aa213c1435e2bffeb6fca842287ef534ad05d5cf"
@@ -4890,6 +4938,16 @@ hermes-estree@0.23.1:
resolved "https://registry.yarnpkg.com/hermes-estree/-/hermes-estree-0.23.1.tgz#d0bac369a030188120ee7024926aabe5a9f84fdb"
integrity sha512-eT5MU3f5aVhTqsfIReZ6n41X5sYn4IdQL0nvz6yO+MMlPxw49aSARHLg/MSehQftyjnrE8X6bYregzSumqc6cg==
hermes-estree@0.24.0:
version "0.24.0"
resolved "https://registry.yarnpkg.com/hermes-estree/-/hermes-estree-0.24.0.tgz#487dc1ddc0bae698c2d79f34153ac9bf62d7b3c0"
integrity sha512-LyoXLB7IFzeZW0EvAbGZacbxBN7t6KKSDqFJPo3Ydow7wDlrDjXwsdiAHV6XOdvEN9MEuWXsSIFN4tzpyrXIHw==
hermes-estree@0.25.1:
version "0.25.1"
resolved "https://registry.yarnpkg.com/hermes-estree/-/hermes-estree-0.25.1.tgz#6aeec17d1983b4eabf69721f3aa3eb705b17f480"
integrity sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==
hermes-parser@0.23.1:
version "0.23.1"
resolved "https://registry.yarnpkg.com/hermes-parser/-/hermes-parser-0.23.1.tgz#e5de648e664f3b3d84d01b48fc7ab164f4b68205"
@@ -4897,6 +4955,20 @@ hermes-parser@0.23.1:
dependencies:
hermes-estree "0.23.1"
hermes-parser@0.24.0:
version "0.24.0"
resolved "https://registry.yarnpkg.com/hermes-parser/-/hermes-parser-0.24.0.tgz#2ed19d079efc0848eb1f800f0c393a074c4696fb"
integrity sha512-IJooSvvu2qNRe7oo9Rb04sUT4omtZqZqf9uq9WM25Tb6v3usmvA93UqfnnoWs5V0uYjEl9Al6MNU10MCGKLwpg==
dependencies:
hermes-estree "0.24.0"
hermes-parser@0.25.1:
version "0.25.1"
resolved "https://registry.yarnpkg.com/hermes-parser/-/hermes-parser-0.25.1.tgz#5be0e487b2090886c62bd8a11724cd766d5f54d1"
integrity sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==
dependencies:
hermes-estree "0.25.1"
hermes-transform@0.23.1:
version "0.23.1"
resolved "https://registry.yarnpkg.com/hermes-transform/-/hermes-transform-0.23.1.tgz#ea6d401117db8398de9723dc1cf936a9a3c8477b"
@@ -6360,76 +6432,76 @@ merge2@^1.3.0, merge2@^1.4.1:
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
metro-babel-register@^0.81.0-alpha.2:
version "0.81.0-alpha.2"
resolved "https://registry.yarnpkg.com/metro-babel-register/-/metro-babel-register-0.81.0-alpha.2.tgz#3ed905de8b7079a63483871e692bb17deabe656c"
integrity sha512-XBSStCShFqU487ee7gfj23N9tU65NN9axIv/BxL9Kl1bA91/lXn82X8QaAlcyzOv8+ulSm96h1JN/jnmCVotgA==
metro-babel-register@^0.81.0:
version "0.81.0"
resolved "https://registry.yarnpkg.com/metro-babel-register/-/metro-babel-register-0.81.0.tgz#05e9deda5633e38aceb7120b1865cbbc63c5b8ef"
integrity sha512-CU9D49k9ti02ebHXuYlbDNPdBj0C4SnCDIGk328epmcO0p++WzFSWWO92cGc7i0HqKyzgeMskPGJV825Eh7zSg==
dependencies:
"@babel/core" "^7.25.2"
"@babel/plugin-proposal-export-namespace-from" "^7.18.9"
"@babel/plugin-transform-flow-strip-types" "^7.25.2"
"@babel/plugin-transform-modules-commonjs" "^7.24.8"
"@babel/preset-typescript" "^7.24.7"
"@babel/register" "^7.24.6"
"@babel/register" "7.22.5"
babel-plugin-replace-ts-export-assignment "^0.0.2"
babel-plugin-syntax-hermes-parser "0.23.1"
babel-plugin-syntax-hermes-parser "0.24.0"
babel-plugin-transform-flow-enums "^0.0.2"
escape-string-regexp "^1.0.5"
flow-enums-runtime "^0.0.6"
metro-babel-transformer@0.81.0-alpha.2:
version "0.81.0-alpha.2"
resolved "https://registry.yarnpkg.com/metro-babel-transformer/-/metro-babel-transformer-0.81.0-alpha.2.tgz#b4e3173c342c986c0b98acd72c64ee4da4c37ee1"
integrity sha512-OGjDXZGthGnMKH6GGrCYomXl5JT3CXhbPQe9Q0T2+AvFG5OYj4/SAhxqPZ0LgJ+aGAubCD30WoYJ+CZ0H1eEmg==
metro-babel-transformer@0.81.0:
version "0.81.0"
resolved "https://registry.yarnpkg.com/metro-babel-transformer/-/metro-babel-transformer-0.81.0.tgz#cf468eafea52e4d8a77844eb7257f8a76e9d9d94"
integrity sha512-Dc0QWK4wZIeHnyZ3sevWGTnnSkIDDn/SWyfrn99zbKbDOCoCYy71PAn9uCRrP/hduKLJQOy+tebd63Rr9D8tXg==
dependencies:
"@babel/core" "^7.25.2"
flow-enums-runtime "^0.0.6"
hermes-parser "0.23.1"
hermes-parser "0.24.0"
nullthrows "^1.1.1"
metro-cache-key@0.81.0-alpha.2:
version "0.81.0-alpha.2"
resolved "https://registry.yarnpkg.com/metro-cache-key/-/metro-cache-key-0.81.0-alpha.2.tgz#85dff024d894b44f9d61422786063074e6345403"
integrity sha512-XE6LdsTrz5lBWznCKUBGrGlwQrbrHp37Q0SLRgG3xGDI33QmGD8U9DdY4siyGUdo+JD+h1T1RfAM72zWefn9Sw==
metro-cache-key@0.81.0:
version "0.81.0"
resolved "https://registry.yarnpkg.com/metro-cache-key/-/metro-cache-key-0.81.0.tgz#5db34fa1a323a2310205bda7abd0df9614e36f45"
integrity sha512-qX/IwtknP9bQZL78OK9xeSvLM/xlGfrs6SlUGgHvrxtmGTRSsxcyqxR+c+7ch1xr05n62Gin/O44QKg5V70rNQ==
dependencies:
flow-enums-runtime "^0.0.6"
metro-cache@0.81.0-alpha.2:
version "0.81.0-alpha.2"
resolved "https://registry.yarnpkg.com/metro-cache/-/metro-cache-0.81.0-alpha.2.tgz#044d1132c66ffb6f49a4c5c70591296e0125908f"
integrity sha512-fAnaC/PTY0CxG4oaHWYd6JIKUF7lPswHEQvrAcULohdc7qdaOlLZwhIn5+IbhGoi2wYmygNtJAQ75dmaW5udQw==
metro-cache@0.81.0:
version "0.81.0"
resolved "https://registry.yarnpkg.com/metro-cache/-/metro-cache-0.81.0.tgz#90470d10d190ad708f04c6e337eec2c7cddb3db0"
integrity sha512-DyuqySicHXkHUDZFVJmh0ygxBSx6pCKUrTcSgb884oiscV/ROt1Vhye+x+OIHcsodyA10gzZtrVtxIFV4l9I4g==
dependencies:
exponential-backoff "^3.1.1"
flow-enums-runtime "^0.0.6"
metro-core "0.81.0-alpha.2"
metro-core "0.81.0"
metro-config@0.81.0-alpha.2, metro-config@^0.81.0-alpha.2:
version "0.81.0-alpha.2"
resolved "https://registry.yarnpkg.com/metro-config/-/metro-config-0.81.0-alpha.2.tgz#a110744b72c1397d818568b3b4dc8e096fb58393"
integrity sha512-HcAxiXW3nahJBKB2RmM7v+Y1hDsBw0tQWIksmIoRTEm6LqF0XbrONEg0MS5sGvWSe3TH3+hG/CWA9Brs9kuKuA==
metro-config@0.81.0, metro-config@^0.81.0:
version "0.81.0"
resolved "https://registry.yarnpkg.com/metro-config/-/metro-config-0.81.0.tgz#8f8074033cb7e9ddb5b0459642adf6880bc9fbc1"
integrity sha512-6CinEaBe3WLpRlKlYXXu8r1UblJhbwD6Gtnoib5U8j6Pjp7XxMG9h/DGMeNp9aGLDu1OieUqiXpFo7O0/rR5Kg==
dependencies:
connect "^3.6.5"
cosmiconfig "^5.0.5"
flow-enums-runtime "^0.0.6"
jest-validate "^29.6.3"
metro "0.81.0-alpha.2"
metro-cache "0.81.0-alpha.2"
metro-core "0.81.0-alpha.2"
metro-runtime "0.81.0-alpha.2"
metro "0.81.0"
metro-cache "0.81.0"
metro-core "0.81.0"
metro-runtime "0.81.0"
metro-core@0.81.0-alpha.2, metro-core@^0.81.0-alpha.2:
version "0.81.0-alpha.2"
resolved "https://registry.yarnpkg.com/metro-core/-/metro-core-0.81.0-alpha.2.tgz#bf997b05bda00491194c95934ce5b1374f8d093e"
integrity sha512-U8bknkQK0a15F5ZPku5QP/ZmnYxhbYY5X+Pw0Gx+rpkeWf8vdfB+4r/usuzIh9kaZErZHTZNEMI7dZ4/4boRpQ==
metro-core@0.81.0, metro-core@^0.81.0:
version "0.81.0"
resolved "https://registry.yarnpkg.com/metro-core/-/metro-core-0.81.0.tgz#d0b634f9cf97849b7730c59457ab7a439811d4c8"
integrity sha512-CVkM5YCOAFkNMvJai6KzA0RpztzfEKRX62/PFMOJ9J7K0uq/UkOFLxcgpcncMIrfy0PbfEj811b69tjULUQe1Q==
dependencies:
flow-enums-runtime "^0.0.6"
lodash.throttle "^4.1.1"
metro-resolver "0.81.0-alpha.2"
metro-resolver "0.81.0"
metro-file-map@0.81.0-alpha.2:
version "0.81.0-alpha.2"
resolved "https://registry.yarnpkg.com/metro-file-map/-/metro-file-map-0.81.0-alpha.2.tgz#450310f28da447f6e6438acf1bc387895c58d416"
integrity sha512-bR/V5oKIk2OTNpTx9Xy2pYKDEUYbngUs/YsLFDkK4YFuO1FDJZxTcPr6sgMSJignz/AC2gx/oO3zpbO7I3GKJQ==
metro-file-map@0.81.0:
version "0.81.0"
resolved "https://registry.yarnpkg.com/metro-file-map/-/metro-file-map-0.81.0.tgz#af0ccf4f8db4fd8429f78f231faa49dde2c402c3"
integrity sha512-zMDI5uYhQCyxbye/AuFx/pAbsz9K+vKL7h1ShUXdN2fz4VUPiyQYRsRqOoVG1DsiCgzd5B6LW0YW77NFpjDQeg==
dependencies:
anymatch "^3.0.3"
debug "^2.2.0"
@@ -6445,69 +6517,69 @@ metro-file-map@0.81.0-alpha.2:
optionalDependencies:
fsevents "^2.3.2"
metro-memory-fs@^0.81.0-alpha.2:
version "0.81.0-alpha.2"
resolved "https://registry.yarnpkg.com/metro-memory-fs/-/metro-memory-fs-0.81.0-alpha.2.tgz#241280cc64ade326f1ffb1df6fc77506de7f9858"
integrity sha512-4owL5ha/vNmwZvHhIQ48lZ1gSqbaIHOpt1Mmv3iQoe/z9Foe+SYLTPbCU3Dt5yK9oWDvkBYKag66LxPoCsPLRA==
metro-memory-fs@^0.81.0:
version "0.81.0"
resolved "https://registry.yarnpkg.com/metro-memory-fs/-/metro-memory-fs-0.81.0.tgz#f11ac95bb294f3fd4c933cf93ab9ee6da626d352"
integrity sha512-hbmyOuVigPU81Kd+CUCq7tXgEkrHmteWG1WJHTEwldoLHuYUzSeaoE8LlLUbqPF+OPW0asYx/cTDrfNM8KCuqw==
dependencies:
flow-enums-runtime "^0.0.6"
metro-minify-terser@0.81.0-alpha.2:
version "0.81.0-alpha.2"
resolved "https://registry.yarnpkg.com/metro-minify-terser/-/metro-minify-terser-0.81.0-alpha.2.tgz#bd844986ef08f6c5f7ae57828ae973256bb27000"
integrity sha512-cAqqFWP5UO0ImNu7c3xIrXCLltvm9OIng2kIe/+nU9CC70K7pATxdtWpC0PA9dt2MsfY2583i3pu/rr5qIY0Yw==
metro-minify-terser@0.81.0:
version "0.81.0"
resolved "https://registry.yarnpkg.com/metro-minify-terser/-/metro-minify-terser-0.81.0.tgz#8b0abe977d63a99b99fa94d53678ef3170d5b659"
integrity sha512-U2ramh3W822ZR1nfXgIk+emxsf5eZSg10GbQrT0ZizImK8IZ5BmJY+BHRIkQgHzWFpExOVxC7kWbGL1bZALswA==
dependencies:
flow-enums-runtime "^0.0.6"
terser "^5.15.0"
metro-resolver@0.81.0-alpha.2, metro-resolver@^0.81.0-alpha.2:
version "0.81.0-alpha.2"
resolved "https://registry.yarnpkg.com/metro-resolver/-/metro-resolver-0.81.0-alpha.2.tgz#30402262f96ee1f1aa43408b1f91508a50da1be5"
integrity sha512-C4KGAki0jeUq1wqFrsD0R6FgmYL+6weDuze/5SolMmBflaU03hY9ZiQUsNuEWgU7+OG+A0q6PBwcskBUXBpW6Q==
metro-resolver@0.81.0, metro-resolver@^0.81.0:
version "0.81.0"
resolved "https://registry.yarnpkg.com/metro-resolver/-/metro-resolver-0.81.0.tgz#141f4837e1e0c5a1810ea02f2d9be3c9f6cf3766"
integrity sha512-Uu2Q+buHhm571cEwpPek8egMbdSTqmwT/5U7ZVNpK6Z2ElQBBCxd7HmFAslKXa7wgpTO2FAn6MqGeERbAtVDUA==
dependencies:
flow-enums-runtime "^0.0.6"
metro-runtime@0.81.0-alpha.2, metro-runtime@^0.81.0-alpha.2:
version "0.81.0-alpha.2"
resolved "https://registry.yarnpkg.com/metro-runtime/-/metro-runtime-0.81.0-alpha.2.tgz#216f02d5473799379403db71a0a6ec1b791197f6"
integrity sha512-uP+7ejq7R+WOV39TucJsgeRalA8jlw5l3JtID+Iu8zZvzJT0WO4VlINAFVS5n6Xk7tK+dkqGH1oF0lst1X+qNw==
metro-runtime@0.81.0, metro-runtime@^0.81.0:
version "0.81.0"
resolved "https://registry.yarnpkg.com/metro-runtime/-/metro-runtime-0.81.0.tgz#63af9b3fec15d1f307d89ef4881f5ba2c592291e"
integrity sha512-6oYB5HOt37RuGz2eV4A6yhcl+PUTwJYLDlY9vhT+aVjbUWI6MdBCf69vc4f5K5Vpt+yOkjy+2LDwLS0ykWFwYw==
dependencies:
"@babel/runtime" "^7.25.0"
flow-enums-runtime "^0.0.6"
metro-source-map@0.81.0-alpha.2, metro-source-map@^0.81.0-alpha.2:
version "0.81.0-alpha.2"
resolved "https://registry.yarnpkg.com/metro-source-map/-/metro-source-map-0.81.0-alpha.2.tgz#c8264efda5e312cb87a9b0ac78b7eb0e6808c92a"
integrity sha512-R5obOY4guE8D2fckCjoYrf+NHWwiorOBPSLr9jXLKXqdo7c3dCG9Fp9U1vJc4qKTJjhHN+bHND/+Ih8UPHH9zg==
metro-source-map@0.81.0, metro-source-map@^0.81.0:
version "0.81.0"
resolved "https://registry.yarnpkg.com/metro-source-map/-/metro-source-map-0.81.0.tgz#ca83964124bb227d5f0bdb1ee304dbfe635f869e"
integrity sha512-TzsVxhH83dyxg4A4+L1nzNO12I7ps5IHLjKGZH3Hrf549eiZivkdjYiq/S5lOB+p2HiQ+Ykcwtmcja95LIC62g==
dependencies:
"@babel/traverse" "^7.25.3"
"@babel/traverse--for-generate-function-map" "npm:@babel/traverse@^7.25.3"
"@babel/types" "^7.25.2"
flow-enums-runtime "^0.0.6"
invariant "^2.2.4"
metro-symbolicate "0.81.0-alpha.2"
metro-symbolicate "0.81.0"
nullthrows "^1.1.1"
ob1 "0.81.0-alpha.2"
ob1 "0.81.0"
source-map "^0.5.6"
vlq "^1.0.0"
metro-symbolicate@0.81.0-alpha.2:
version "0.81.0-alpha.2"
resolved "https://registry.yarnpkg.com/metro-symbolicate/-/metro-symbolicate-0.81.0-alpha.2.tgz#7aebb285b516b03df09ac8b3cc57611f7642db94"
integrity sha512-S5v09d93mg3C8iGwAZwhDwiDg5kW7DnGi9OOvb8+gtBJ9EzxV9/z3BPG1NFkzQ/ymnIEUcaQ1N8BpEgrXnsI6g==
metro-symbolicate@0.81.0:
version "0.81.0"
resolved "https://registry.yarnpkg.com/metro-symbolicate/-/metro-symbolicate-0.81.0.tgz#b7b1eae8bfd6ad2a922fa2bcb9f2144e464adafb"
integrity sha512-C/1rWbNTPYp6yzID8IPuQPpVGzJ2rbWYBATxlvQ9dfK5lVNoxcwz77hjcY8ISLsRRR15hyd/zbjCNKPKeNgE1Q==
dependencies:
flow-enums-runtime "^0.0.6"
invariant "^2.2.4"
metro-source-map "0.81.0-alpha.2"
metro-source-map "0.81.0"
nullthrows "^1.1.1"
source-map "^0.5.6"
through2 "^2.0.1"
vlq "^1.0.0"
metro-transform-plugins@0.81.0-alpha.2:
version "0.81.0-alpha.2"
resolved "https://registry.yarnpkg.com/metro-transform-plugins/-/metro-transform-plugins-0.81.0-alpha.2.tgz#7fd204f91975c4dc8145d613b54f982ec892ba84"
integrity sha512-VtK38ytQ9mK1v/JOm1wW1AvZjO/Fsd8krNZy6riRj2fstcKkNx6LL1j5TtwINBUjCY1WPrpunQtG+Wc98LMiHQ==
metro-transform-plugins@0.81.0:
version "0.81.0"
resolved "https://registry.yarnpkg.com/metro-transform-plugins/-/metro-transform-plugins-0.81.0.tgz#614c0e50593df545487b3f3383fed810c608fb32"
integrity sha512-uErLAPBvttGCrmGSCa0dNHlOTk3uJFVEVWa5WDg6tQ79PRmuYRwzUgLhVzn/9/kyr75eUX3QWXN79Jvu4txt6Q==
dependencies:
"@babel/core" "^7.25.2"
"@babel/generator" "^7.25.0"
@@ -6516,29 +6588,29 @@ metro-transform-plugins@0.81.0-alpha.2:
flow-enums-runtime "^0.0.6"
nullthrows "^1.1.1"
metro-transform-worker@0.81.0-alpha.2:
version "0.81.0-alpha.2"
resolved "https://registry.yarnpkg.com/metro-transform-worker/-/metro-transform-worker-0.81.0-alpha.2.tgz#a18a386139c9e74e189e5bc94c6d6028aba35ba7"
integrity sha512-DBzR0gf7rBB42NDFuZ9hfTrvpSNDnKSHsp+TKMBtsVRtb3UpbnuH1iiO7HNV7Dro5E8nNjkYuUnLE6tC6CNFYQ==
metro-transform-worker@0.81.0:
version "0.81.0"
resolved "https://registry.yarnpkg.com/metro-transform-worker/-/metro-transform-worker-0.81.0.tgz#43e63c95014f36786f0e1a132c778c6392950de7"
integrity sha512-HrQ0twiruhKy0yA+9nK5bIe3WQXZcC66PXTvRIos61/EASLAP2DzEmW7IxN/MGsfZegN2UzqL2CG38+mOB45vg==
dependencies:
"@babel/core" "^7.25.2"
"@babel/generator" "^7.25.0"
"@babel/parser" "^7.25.3"
"@babel/types" "^7.25.2"
flow-enums-runtime "^0.0.6"
metro "0.81.0-alpha.2"
metro-babel-transformer "0.81.0-alpha.2"
metro-cache "0.81.0-alpha.2"
metro-cache-key "0.81.0-alpha.2"
metro-minify-terser "0.81.0-alpha.2"
metro-source-map "0.81.0-alpha.2"
metro-transform-plugins "0.81.0-alpha.2"
metro "0.81.0"
metro-babel-transformer "0.81.0"
metro-cache "0.81.0"
metro-cache-key "0.81.0"
metro-minify-terser "0.81.0"
metro-source-map "0.81.0"
metro-transform-plugins "0.81.0"
nullthrows "^1.1.1"
metro@0.81.0-alpha.2, metro@^0.81.0-alpha.2:
version "0.81.0-alpha.2"
resolved "https://registry.yarnpkg.com/metro/-/metro-0.81.0-alpha.2.tgz#69059bda8f4194809d206cfae89ff2f06a53e5a7"
integrity sha512-ZfL5IjEEuMtM5A5tVKL2LNv/WO6Gj1RhdIsW+3uz3BB0Y/ZqMdfp61qVWNCV7kGWMqunee3ER0P1EUuPHfIb0Q==
metro@0.81.0, metro@^0.81.0:
version "0.81.0"
resolved "https://registry.yarnpkg.com/metro/-/metro-0.81.0.tgz#cffe9b7d597728dee8b57903ca155417b7c13a4f"
integrity sha512-kzdzmpL0gKhEthZ9aOV7sTqvg6NuTxDV8SIm9pf9sO8VVEbKrQk5DNcwupOUjgPPFAuKUc2NkT0suyT62hm2xg==
dependencies:
"@babel/code-frame" "^7.24.7"
"@babel/core" "^7.25.2"
@@ -6556,24 +6628,24 @@ metro@0.81.0-alpha.2, metro@^0.81.0-alpha.2:
error-stack-parser "^2.0.6"
flow-enums-runtime "^0.0.6"
graceful-fs "^4.2.4"
hermes-parser "0.23.1"
hermes-parser "0.24.0"
image-size "^1.0.2"
invariant "^2.2.4"
jest-worker "^29.6.3"
jsc-safe-url "^0.2.2"
lodash.throttle "^4.1.1"
metro-babel-transformer "0.81.0-alpha.2"
metro-cache "0.81.0-alpha.2"
metro-cache-key "0.81.0-alpha.2"
metro-config "0.81.0-alpha.2"
metro-core "0.81.0-alpha.2"
metro-file-map "0.81.0-alpha.2"
metro-resolver "0.81.0-alpha.2"
metro-runtime "0.81.0-alpha.2"
metro-source-map "0.81.0-alpha.2"
metro-symbolicate "0.81.0-alpha.2"
metro-transform-plugins "0.81.0-alpha.2"
metro-transform-worker "0.81.0-alpha.2"
metro-babel-transformer "0.81.0"
metro-cache "0.81.0"
metro-cache-key "0.81.0"
metro-config "0.81.0"
metro-core "0.81.0"
metro-file-map "0.81.0"
metro-resolver "0.81.0"
metro-runtime "0.81.0"
metro-source-map "0.81.0"
metro-symbolicate "0.81.0"
metro-transform-plugins "0.81.0"
metro-transform-worker "0.81.0"
mime-types "^2.1.27"
nullthrows "^1.1.1"
serialize-error "^2.1.0"
@@ -6851,10 +6923,10 @@ oauth-sign@~0.9.0:
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
ob1@0.81.0-alpha.2:
version "0.81.0-alpha.2"
resolved "https://registry.yarnpkg.com/ob1/-/ob1-0.81.0-alpha.2.tgz#45ac7fc423577fee88425476908793905df6a3c5"
integrity sha512-wii3uNfV58CK6KzM6o1HzlUAYZJbsbNm3dQHMQJeTok6jZzF/aDYZrbuI4U4V4HkKxrHL2QgRf2rKDlDU9Au9g==
ob1@0.81.0:
version "0.81.0"
resolved "https://registry.yarnpkg.com/ob1/-/ob1-0.81.0.tgz#dc3154cca7aa9c2eb58f5ac63e9ee23ff4c6f520"
integrity sha512-6Cvrkxt1tqaRdWqTAMcVYEiO5i1xcF9y7t06nFdjFqkfPsEloCf8WwhXdwBpNUkVYSQlSGS7cDgVQR86miBfBQ==
dependencies:
flow-enums-runtime "^0.0.6"
@@ -7177,7 +7249,7 @@ pinpoint@^1.1.0:
resolved "https://registry.yarnpkg.com/pinpoint/-/pinpoint-1.1.0.tgz#0cf7757a6977f1bf7f6a32207b709e377388e874"
integrity sha512-+04FTD9x7Cls2rihLlo57QDCcHoLBGn5Dk51SwtFBWkUWLxZaBXyNVpCw1S+atvE7GmnFjeaRZ0WLq3UYuqAdg==
pirates@^4.0.1, pirates@^4.0.4, pirates@^4.0.6:
pirates@^4.0.1, pirates@^4.0.4, pirates@^4.0.5, pirates@^4.0.6:
version "4.0.6"
resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9"
integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==