Summary:
This PR follows up on https://github.com/facebook/react-native/issues/47182 and https://github.com/facebook/react-native/issues/47348 by adding `force-cache`, the final missing option to align caching controls with the existing behavior on iOS.
Local caching behavior remains unchanged: if a cached image is available locally, it will be returned; otherwise, a network request will be made.
When an image request is sent over the network, the `force-cache` option sent from the sent fJS side will now use the `okhttp3.CacheControl.FORCE_CACHE` directive.
## Changelog:
[ANDROID] [ADDED] - Image `force-cache` caching control option
Pull Request resolved: https://github.com/facebook/react-native/pull/47426
Test Plan:
New example added to the RNTester under the cache policy examples. Then inspecting that the cache control is set correctly before sending it in the `okhttp3.Request` builder.
```kt
FLog.w("ReactNative", "fetching uri: %s, with cacheControl: %s", uri, cacheControlBuilder.build().toString())
// fetching uri: https:...png?cacheBust=force-cache, with cacheControl: no-store, max-stale=2147483647, only-if-cached
```
This case was a bit more tricky to test in terms of e2e as it would involve some caching in the server as well, I'm open to suggestions to make this more complete.
Reviewed By: javache
Differential Revision: D65490360
Pulled By: Abbondanzo
fbshipit-source-id: f807a9793f85caea39c59a370d057b9a1d450a78
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47520
Right now, when a 3p library needs to register a component in the component system, we have to crawl the library to try and get the mappng, best effort.
With this approach, we are enriching the `codegenConfig` property to allow library developers to define the mapping themselves.
For example:
```json
//...
"codegenConfig": {
//..
"ios": {
"componentProvider": {
"RNTMyNativeView": "RNTMyNativeViewComponentView"
}
}
},
```
means that the JS component `RNTMyNativeView` will be mapped to the `RNTMyNativeViewComponentView` class.
This also work for local apps, and it warns the users about what libraries are using the deprecated approach, so they can open an issue or a PR to those libraries.
## Changelog:
[iOS][Added] - Allow 3p developers to specify the association between components and classes in Fabric
Reviewed By: dmytrorykun
Differential Revision: D65666061
fbshipit-source-id: 692e753635873ff9260e131d2d18ed226b2378c2
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47518
This change reintroduce the generation of the `RCTThirdPartyComponentProvider` but in the right place and with the right patterns.
1. We are generating it in the user space, not in the node_modules (fixes the circular dependency)
2. We are not using weak function signature that have to be implicitly linked to some symbols found during compilation
The change needs to crawl the folder to retrieve the information it needs. We need to implement it this way not to be breaking with respect of the current implementation.
The assumption is that components have a function in their `.mm` file with this shape:
```objc
Class<RCTComponentViewProtocol> <componentName>Cls(void)
{
return <ComponentViewClass>.class;
}
```
I verified on GH that all the libraries out there follow this pattern.
A better approach will let library owner to specify the association of `componentName, componentClass` in the `codegenConfig`.
We will implement that as the next step and we will support both for some versions for backward compatibility.
## Changelog
[iOS][Changed] - Change how components automatically register
Reviewed By: dmytrorykun
Differential Revision: D65614347
fbshipit-source-id: a378b8bc31c1ab3d49552f2f6a4c86c3b578746b
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47517
The `RCTThirdPartyLibraryComponentProvider` has been introduced to automate the component registration of third party libraries in the apps. However, it has some serious flaws:
* It is generated in the React/Fabric folder, which means that it is generated in node_modules
* It is generated when the user installs the components in the app, which means that we can't prebuild and redistribute React Native as a binary
* it does not work with Frameworks and dynamic linking: in this scenarion, Fabric must build in isolation and if there are third party libraries involved, the lookup of the `xxxCls` function will fail
This change removes the generation of the `RCTThirdPartyLibraryComponentProvider`. In the next diffs we will implement a different mechanism to register components
## Changelog
[iOS][Changed] - Stop generating the RCTThirdPartyLibraryComponentProvider
Reviewed By: dmytrorykun
Differential Revision: D65601939
fbshipit-source-id: 9cc8c46102827d124b93b8aa6705b5e6014695c1
Summary:
Resolve warning on ios build:
```
.../ios/Pods/Headers/Public/React-Core/React/RCTAppearance.h:16:60 A function declaration without a prototype is deprecated in all versions of C
```
## Changelog:
<!-- Help reviewers and the release process by writing your own changelog entry.
Pick one each for the category and type tags:
[ANDROID|GENERAL|IOS|INTERNAL] [BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY] - Message
For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests
-->
[IOS] [FIXED] - Resolve deprecated function prototype warning in RCTAppearance.h
Pull Request resolved: https://github.com/facebook/react-native/pull/47564
Test Plan:
Jest Result (`yarn test`):
```
Test Suites: 234 passed, 234 total
Tests: 2 skipped, 4899 passed, 4901 total
Snapshots: 1687 passed, 1687 total
Time: 46.387 s
Ran all test suites.
```
Reviewed By: cipolleschi
Differential Revision: D65816584
Pulled By: javache
fbshipit-source-id: 212021c39dfde7e638752940e67a9f964d2194ab
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47531
When the activity is paused, or destroyed, we should disable the devsupportmanager. (This performs cleanup).
When the activity is resumed, we should re-enable devsupportmanager. (This performs re-initialization).
Changelog: [Internal]
Reviewed By: sammy-SC
Differential Revision: D65689053
fbshipit-source-id: 99de0906b8cdc84f56b4d334ac0eeecc7b436dd5
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47528
After the js pipeline fails to handle the error, reset the hasHandledFatalError var.
Changelog: [Internal]
Reviewed By: sammy-SC
Differential Revision: D65678387
fbshipit-source-id: ac7cd4724954ea78bf33542e208c5f5d3dba5383
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47529
RuntimeExecutor, RuntimeScheduler, etc. can execute arbitrary c++ on the javascript thread.
If that c++ throws a non-jsi::JSError, it will bypass the js error handler (and start tearing down the react instance 😱).
Let's have the js error handler manage all exceptions raised while native is calling into js. This is more sane.
Changelog: [Internal]
Reviewed By: sammy-SC
Differential Revision: D64626610
fbshipit-source-id: 40132f24b4e2737ae3f055fbd09153111404e5bf
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47468
Across our scroll view implementations on iOS, we fire `onMomentumScrollEnd` whenever the scroll view finishes decelerating, whether it comes from a user's touch or call to `setContentOffset` with animations. But we omit dispatching the `onMomentumScrollBegin` event in the latter cases.
This change updates both old and new architecture to dispatch `onMomentumScrollBegin` when a view-command-driven scroll occurs with animation, like `scrollTo` or `scrollToEnd`.
Changelog:
[iOS][Fixed] - Fixed `onMomentumScrollBegin` event not firing on command-driven scroll events
Reviewed By: javache
Differential Revision: D65556000
fbshipit-source-id: bc4b778c63d8a032e1d8e00b9d4d5f83a5d651d6
Summary:
Follow up from https://github.com/facebook/react-native/issues/47433, adding some missing scenarios in the unit tests for the image component in Android.
## Changelog:
[INTERNAL] [ADDED] - Improving Android `ImageResizeMode` unit tests
Pull Request resolved: https://github.com/facebook/react-native/pull/47527
Test Plan:
```bash
yarn test-android
```
Reviewed By: fabriziocucci
Differential Revision: D65735794
Pulled By: Abbondanzo
fbshipit-source-id: a420274c78d9eadf0439870cfaae4d16247c6034
Summary:
On android the isGrayScaleEnabled method of AccessibilityInfo always returns false due to missing implementation. This PR fills the gap by providing the native module logic for checking grayscale mode.
## Changelog:
- Added native module code to check for grayscale mode on android
- Updated js accessibility info module to return the correct promise instead of default false for isGrayScaleEnabled()
- Moved the test for isGrayScaleEnabled() out of ios scope to common Android and iOS scope
[ANDROID] [ADDED] - logic to check for grayscale mode on android
Pull Request resolved: https://github.com/facebook/react-native/pull/47497
Test Plan:
Tested on :
- Google Pixel 7 Pro (Android 14)
- OnePlus 12 (Android 14)
- Pixel 6 (Android 15)
Reviewed By: cortinico
Differential Revision: D65662583
Pulled By: javache
fbshipit-source-id: 39f9ce37c9375b5380257847395393045eedbadc
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47494
Changelog: [General][Changed] AttributedString `appendFragment` and `prependFragment` take an rval instead of a const ref; append/prependAttributedString have been removed
Reviewed By: mdvacca
Differential Revision: D65603864
fbshipit-source-id: 1160a9e2064470f826bea66736b4fce13caa3a73
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47543
TaskCompletionSource is public but it shouldn't, in this diff I'm making it intenral
changelog: [Android][Breaking] Reduce visibility of TaskCompletionSource class
Reviewed By: javache
Differential Revision: D65738324
fbshipit-source-id: 61db35a408162c53398b20e45a52f3eb46de1eae
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47540
Continuation is only used inside RN, we should make it internal
changelog: [Android][Changed] Reduce visibility of Continuation to internal, although this interface wasn't being exposed in any public API
Reviewed By: javache
Differential Revision: D65738329
fbshipit-source-id: 6fb1b9e9a253eafad0f6eb1e4c1363d6254846da
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47548
changelog: [internal]
This race condition only shows itself with flag `useOptimizedEventBatchingOnAndroid`
# Problem
EventBeat assumes method `induce` will be called repeatedly on every UI tick. This is true for iOS and existing implementation of event beat on Android. The first early exist inside of `induce` method is built with this assumption.
`useOptimizedEventBatchingOnAndroid` on Android changes this. `induce` will only be called after FabricUIManager.onRequestEventBeat is invoked and then it will stop. For one `FabricUIManager.onRequestEventBeat` call, `EventBeat::induce` is called once. And there is a chance for race condition.
Here is a simplified implementation of `induce`. This method may be called many times in sequence. The caller will set [isRequested_](https://github.com/facebook/react-native/blob/main/packages/react-native/ReactCommon/react/renderer/core/EventBeat.cpp#L25) and then invoke [FabricUIManager.onRequestEventBeat](https://github.com/facebook/react-native/blob/main/packages/react-native/ReactAndroid/src/main/jni/react/fabric/AndroidEventBeat.cpp#L43). Notice how `FabricUIManager.onRequestEventBeat` is debounced if `isRequested_` flag is true.
```
void EventBeat::induce() const {
if (!isRequested_ || isBeatCallbackScheduled_) {
// isRequested_ is not set to false in case isBeatCallbackScheduled_) is true.
return;
}
isRequested_ = false;
isBeatCallbackScheduled_ = true;
auto beat = std::function<void(jsi::Runtime&)>(
// on JS queue
isBeatCallbackScheduled_ = false;
// beatCallback_(runtime)
}
runtimeScheduler_.scheduleWork(std::move(beat));
}
```
This can get into a state where `isRequested_` is not reset back to false even though `EventBeat::induce` is called when `isBeatCallbackScheduled_` is true.
`AndroidEventBeat::request` -> `isRequested_` is set to true -> `FabricUIManager::onRequestEventBeat` -> `EventBeat::induce` -> `isRequested_` is set to false -> `isBeatCallbackScheduled_` is set to true -> `AndroidEventBeat::request` -> `FabricUIManager::onRequestEventBeat` -> `EventBeat::induce` (early exit because `isBeatCallbackScheduled_` is true) -> `beat` is executed on the JS thread.
From this point on, subsequent calls to `AndroidEventBeat::request` are always debounced because flag `isRequested_` is true.
Any subsequent event on Android will end up calling `EventBeat::induce` and the mechanism gets unstuck.
# The fix
The fix is simple, any time `EventBeat::induce` is called, make sure `request_` flag is set to false. This then satisfied the expectation of `useOptimizedEventBatchingOnAndroid` optimisation.
Reviewed By: rubennorte
Differential Revision: D65566258
fbshipit-source-id: 5f15da8f5cb722b329f9f72b9ddca8e2cac04144
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
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47534
This diff is introducing a new method to destroy React instance that allows the caller to be notified when the destroy finishes
This is necessary for apps to act upon destroy of the react instance
changelog: [internal] internal
Reviewed By: shwanton
Differential Revision: D65721107
fbshipit-source-id: 2d3d9755db38461ba381b86c72df5869c542379b
Summary:
All `removeEventListener` methods was removed 2596b2f695 perviously but seems a `BackHandler` was missed
This can be a breaking change for some third-party modules.
**Migration**: Use `remove` on the EventSubscription from `addEventListener`:
```diff
useEffect(()=>{
+ const subscription = NativeModule.removeListener(name, listener);
+ return ()=>subscription.remove();
},[])
```
## Changelog:
[GENERAL] [REMOVED] - Remove `BackHandler.removeEventListener`
Pull Request resolved: https://github.com/facebook/react-native/pull/45892
Test Plan: ...
Reviewed By: huntie
Differential Revision: D65663591
Pulled By: javache
fbshipit-source-id: 01b804cd6ec77ea4916a0ced7fee551d045f1684
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47383
CatalystInstance is deprecated and will be removed in new architecture
changelog: [Android][Changed] Deprecate CatalystInstance in old architecture
Reviewed By: cortinico
Differential Revision: D65430643
fbshipit-source-id: 96ba91c45760ead8155f9f28b6fad523be75929e
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47525
This API is awkward for nullsafe code. Adding an extension allows Kotlin code to use `applyTextTransform()` on either nullable or non-null strings:
```
val a: String = string.applyTextTransform(...)
val b: String? = nullableString?.applyTextTransform(...)
```
Changelog:
[Android][Added] TextTransform ktx
Reviewed By: javache
Differential Revision: D65618709
fbshipit-source-id: 28a0fe61a0eaf27aa9677af39d932982f3b694b2
Summary:
`react.ref_as_prop=experimental.partial_support` will expose errors where a ref prop is passed to a function component without ref prop. This diff pre-suppresses the newly exposed errors.
Changelog: [Internal]
Reviewed By: gkz
Differential Revision: D65686695
fbshipit-source-id: f241cc40f3ac414a2960dec60d9ba4633e5f93c0
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47278
When we have multiple spans of text inside a <Text> element, React will emit these as separate RawText ShadowNodes. RawText shadow nodes cannot have any properties beyond the text they contain, yet our current AttributedText logic will generate a separate span for each and duplicate all the relevant properties.
This can be particularly inefficient when JSX is used to interpolate strings, e.g. `<Text styles={styles.text}>Example {i}/{count}</Text>` results in 4 raw text elements with duplicated properties.
Changelog: [General][Changed] Improved AttributedText generation for raw text nodes.
Reviewed By: NickGerleman
Differential Revision: D65134912
fbshipit-source-id: dba4296ebe9987e989760cdee66f1e076fbb7a98
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47512
As can be seen in `renderApplication`, `useConcurrentRoot` is no longer used to decide whether to run the application in concurrent mode, as we default all Fabric-users to concurrent root.
Changelog: [General][Removed] Removed type for useConcurrentRoot from AppRegistry, as it was already ignored
Reviewed By: sammy-SC, fabriziocucci
Differential Revision: D65660681
fbshipit-source-id: c99e5ae14d515015709908ed21a854c780f628e0
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47503
Enables the `scheduleAnimatedEndCallbackInMicrotask` feature flag that was introduced in https://github.com/facebook/react-native/pull/46714.
Changelog:
[General][Changed] - Callbacks passed to `animation.start(<callback>)` will be scheduled for execution in a microtask. Previously, there were certain scenarios in which the callback could be synchronously executed by `start`.
Reviewed By: javache
Differential Revision: D65645981
fbshipit-source-id: ac159208b7c1df60549baa52704bb0e704da0acf
Summary:
As titled. This API is legacy / Meta-only.
Changelog: [Internal]
Reviewed By: cortinico
Differential Revision: D65666574
fbshipit-source-id: f9700486aec0306b305910bff14ae7f3df3fab7f