Summary:
In bridgeless mode, the CatalystInstance doesn't exist, but we still need to be able to access the sourceURL in SourceCodeModule (which is needed to render the images in LogBox warnings and errors). This diff adds a new API for getting the sourceURL directly from ReactContext, instead of having to call context.getCatalystInstance().getSourceURL(), and updates SourceCodeModule to use it.
Changelog: [Internal]
Reviewed By: RSNara
Differential Revision: D20848700
fbshipit-source-id: 3ecda81a17121178b76bbb3e9b0f27f103c1961a
Summary:
This is the first of three PRs related to enabling multi-bundle support in React Native. More details, motivation and reasoning behind it can be found in RFC [here](https://github.com/react-native-community/discussions-and-proposals/issues/152).
Logic responsible for installing globals was pulled out from `loadApplicationScript` to `initializeRuntime` since it should be ran only once, what was left was renamed to `loadBundle`.
It's based on dratwas work from [here](https://github.com/callstack/react-native/tree/feat/multibundle/split-load-application), but applied to current `master` to avoid rebasing 3-months old branch and issues that come with that.
## Changelog
[Internal] [Changed] - split `loadApplicationScript` into `initializeRuntime` and `loadBundle` to enable multi-bundle support in the future
Pull Request resolved: https://github.com/facebook/react-native/pull/27844
Test Plan: Initialized new RN app with CLI, set RN to build from source and verified the still app builds and runs OK using code from this branch.
Reviewed By: rickhanlonii
Differential Revision: D19888605
Pulled By: ejanzer
fbshipit-source-id: 24ace48ffe8978796591fe7c6cf53a61b127cce6
Summary:
Instead of just blindly retrying all ViewCommands if they fail - which could be dangerous, since it's arbitrary imperative commands we'd be executing twice, potentially with bad app state - we only retry if the ViewCommand throws a "RetryableMountingLayerException".
Changelog: [Internal] Optimization to ViewCommands
Reviewed By: mdvacca
Differential Revision: D20529985
fbshipit-source-id: 0217b43f4bf92442bcc7ca48c8ae2b9a9e543dc9
Summary:
Marketplace eagerly initializes a few NativeModules. These NativeModules are TurboModule compatible, and the device/user is in the TurboModule test. So these NativeModuels should be returned from the TurboModule system. However, for some reason, we end up doing a lookup on the `NativeModuleRegistry` for these NativeModules.
This means that either:
1. The TurboModuleManager isn't attached to the CatalystInstance
2. The TurboModuleManager returned null from getModule.
These logs will help us get to the bottom of what's going on.
Changelog: [Internal]
Reviewed By: JoshuaGross
Differential Revision: D20260150
fbshipit-source-id: bb554ead412ad3b0fa7502b77f575365608ebc98
Summary:
Currently the error messages lead users to assume that all problems are because we're trying to use the ReactContext too early; it could be because we're using it too late, after it's been destroyed. Because of D17944723, it could be because we're accessing too late, after teardown.
Changelog: [Internal] making some error messages more specific and helpful
Reviewed By: mdvacca
Differential Revision: D20251909
fbshipit-source-id: e236d57e4d7d9c778d41de95160c242bcd69b3c9
Summary:
Turns out that dispatchMountItems was reentrant, meaning that something (in particular, updateState) could cause mount items to be queued up which would then be executed synchronously, out-of-order, in the middle of the previous dispatchMountItems call.
We will continue to monitor this and see how often we're reentering: T63181639 and via any soft exceptions that are logged.
For context, there are currently three ways dispatchMountItems gets called: 1) On every UI Tick in the UI thread, in a loop; 2) via animations, via synchronouslyUpdateViewOnUIThread, which happens to fail a *lot* currently; 3) when there is a commit on the UI thread, like with a Java->C++ state update. We must account for reentrance and failure in all three cases and make sure the `mInDispatch` flag is reset after success or failure in all of those situations.
Changelog: [Internal]
Reviewed By: mdvacca
Differential Revision: D20170160
fbshipit-source-id: 834f1d9b65000caa7f2eea4849e5e7951d2b6be6
Summary:
This Pull Request implements the PlatformColor proposal discussed at https://github.com/react-native-community/discussions-and-proposals/issues/126. The changes include implementations for iOS and Android as well as a PlatformColorExample page in RNTester.
Every native platform has the concept of system defined colors. Instead of specifying a concrete color value the app developer can choose a system color that varies in appearance depending on a system theme settings such Light or Dark mode, accessibility settings such as a High Contrast mode, and even its context within the app such as the traits of a containing view or window.
The proposal is to add true platform color support to react-native by extending the Flow type `ColorValue` with platform specific color type information for each platform and to provide a convenience function, `PlatformColor()`, for instantiating platform specific ColorValue objects.
`PlatformColor(name [, name ...])` where `name` is a system color name on a given platform. If `name` does not resolve to a color for any reason, the next `name` in the argument list will be resolved and so on. If none of the names resolve, a RedBox error occurs. This allows a latest platform color to be used, but if running on an older platform it will fallback to a previous version.
The function returns a `ColorValue`.
On iOS the values of `name` is one of the iOS [UI Element](https://developer.apple.com/documentation/uikit/uicolor/ui_element_colors) or [Standard Color](https://developer.apple.com/documentation/uikit/uicolor/standard_colors) names such as `labelColor` or `systemFillColor`.
On Android the `name` values are the same [app resource](https://developer.android.com/guide/topics/resources/providing-resources) path strings that can be expressed in XML:
XML Resource:
`@ [<package_name>:]<resource_type>/<resource_name>`
Style reference from current theme:
`?[<package_name>:][<resource_type>/]<resource_name>`
For example:
- `?android:colorError`
- `?android:attr/colorError`
- `?attr/colorPrimary`
- `?colorPrimaryDark`
- `android:color/holo_purple`
- `color/catalyst_redbox_background`
On iOS another type of system dynamic color can be created using the `IOSDynamicColor({dark: <color>, light:<color>})` method. The arguments are a tuple containing custom colors for light and dark themes. Such dynamic colors are useful for branding colors or other app specific colors that still respond automatically to system setting changes.
Example: `<View style={{ backgroundColor: IOSDynamicColor({light: 'black', dark: 'white'}) }}/>`
Other platforms could create platform specific functions similar to `IOSDynamicColor` per the needs of those platforms. For example, macOS has a similar dynamic color type that could be implemented via a `MacDynamicColor`. On Windows custom brushes that tint or otherwise modify a system brush could be created using a platform specific method.
## Changelog
[General] [Added] - Added PlatformColor implementations for iOS and Android
Pull Request resolved: https://github.com/facebook/react-native/pull/27908
Test Plan:
The changes have been tested using the RNTester test app for iOS and Android. On iOS a set of XCTestCase's were added to the Unit Tests.
<img width="924" alt="PlatformColor-ios-android" src="https://user-images.githubusercontent.com/30053638/73472497-ff183a80-433f-11ea-90d8-2b04338bbe79.png">
In addition `PlatformColor` support has been added to other out-of-tree platforms such as macOS and Windows has been implemented using these changes:
react-native for macOS branch: https://github.com/microsoft/react-native/compare/master...tom-un:tomun/platformcolors
react-native for Windows branch: https://github.com/microsoft/react-native-windows/compare/master...tom-un:tomun/platformcolors
iOS
|Light|Dark|
|{F229354502}|{F229354515}|
Android
|Light|Dark|
|{F230114392}|{F230114490}|
{F230122700}
Reviewed By: hramos
Differential Revision: D19837753
Pulled By: TheSavior
fbshipit-source-id: 82ca70d40802f3b24591bfd4b94b61f3c38ba829
Summary:
We must use FLog instead of android.util.log, this diff moves the current callsites of android.util.log to FLog
changeLog:[internal]
Reviewed By: JoshuaGross
Differential Revision: D19884741
fbshipit-source-id: 300f7d691961aa51f0b525c37da7ae3d64fe5131
Summary:
It turns out that in release builds, proguard is doing something weird with inner classes, so that getSimpleName() is actually returning "OuterClass$InnerClass" in some cases. We have logic to handle this case already in JavaScriptModuleRegistry, so I'm moving that out to a static method that I can access in bridgeless mode.
Also adding tests for it.
Changelog: [Internal]
Reviewed By: mdvacca
Differential Revision: D19701703
fbshipit-source-id: 625737bfb50ca8ba2bd26034e2a74c682783ba8a
Summary:
This is an incomplete effort to migrate from libfb to libfbjni. This is needed to restore the compatibility with Flipper and other FB Android projects that make use of FBJNI. Effectively, the outcome is that `fbjni` no longer has a checked-in copy here, but instead relies on the public artifacts published at github.com/facebookincubator/fbjni that can be deduplicated at build-time.
**A non-exhaustive list of tasks:**
* [X] Gradle builds the SDK and RNTester for Android.
* [X] Buck build for rntester works in OSS.
* [ ] Move from `java-only` release to full `fbjni` release. This requires finding a solution for stripping out `.so` files that the old `Android.mk` insists on including in the final artifacts and will clash with the full distribution.
* [ ] Import this and fix potential internal build issues.
* [ ] Verify that the changes made to the Hermes integration don't have any unintended consequences.
## Changelog
[Android] [Changed] - Migrated from libfb to libfbjni for JNI calls
Pull Request resolved: https://github.com/facebook/react-native/pull/27729
Test Plan:
- CI is already passing again for Gradle and Buck in OSS.
- After applying the following patch, RNTester builds and works with the latest Flipper SDK:
```
diff --git a/RNTester/android/app/build.gradle b/RNTester/android/app/build.gradle
index b8a6437d7..eac942104 100644
--- a/RNTester/android/app/build.gradle
+++ b/RNTester/android/app/build.gradle
@@ -170,10 +170,19 @@ dependencies {
debugImplementation files(hermesPath + "hermes-debug.aar")
releaseImplementation files(hermesPath + "hermes-release.aar")
- debugImplementation("com.facebook.flipper:flipper:0.23.4") {
+ debugImplementation("com.facebook.flipper🐬+") {
exclude group:'com.facebook.yoga'
- exclude group:'com.facebook.flipper', module: 'fbjni'
- exclude group:'com.facebook.litho', module: 'litho-annotations'
+ exclude group:'com.facebook.fbjni'
+ }
+
+ debugImplementation("com.facebook.flipper:flipper-network-plugin:+") {
+ exclude group:'com.facebook.yoga'
+ exclude group:'com.facebook.fbjni'
+ }
+
+ debugImplementation("com.facebook.flipper:flipper-fresco-plugin:+") {
+ exclude group:'com.facebook.yoga'
+ exclude group:'com.facebook.fbjni'
}
if (useIntlJsc) {
```
Reviewed By: mdvacca
Differential Revision: D19345270
Pulled By: passy
fbshipit-source-id: 33811e7f97f44f2ec5999e1c35339909dc4fd3b1
Summary:
## Problem
For efficiency reasons, we'd only check whether the current class or its superclass implemented the `TurboModule` interface. However, it's possible for NativeModules to exist that use inheritance, and have their base class extend a code-generated spec. In this case, the superclass of the superclass of the NativeModule will implement `TurboModule`.
## Solution
To fix this problem, I'm relying on the `Types.isAssignable` API and checking whether the NativeModule can be assigned to the `TurboModule` interface. This is a more reliable way of knowing whether a NativeModule is a TurboModule or not.
**Note:** Had to adjust the buck dependencies of FrescoModule to make the `mTypes.isAssignable` check work.
Changelog:
[Android][Fixed] - Correct TurboModule detection logic in ReactModuleSpecProcessor
Reviewed By: fkgozali
Differential Revision: D19183671
fbshipit-source-id: ad21881453fe7027d9432048108f6ba344fd7e63
Summary:
We currently have a method in ReactContextBaseJavaModule that logs a warning if the native module is trying to access a ReactContext without an active Catalyst instance (because if you try to access it directly, it throws).
For bridgeless mode, we never have a CatalystInstance, but it's safe to call certain methods on the context that would normally require one. For this case, let's just return the context when the context is in bridgeless mode.
Changelog: [Internal]
Reviewed By: RSNara
Differential Revision: D19133988
fbshipit-source-id: cae0bd397aa24d9ad416491cbc32676870cc70b0
Summary:
The class was deprecated in 2016 and is blocking an upgrade to fbjni
which no longer supports the `Countable` class this extends.
Changelog:
[Android] [Removed] - NativeRunnableDeprecated
Pull Request resolved: https://github.com/facebook/react-native/pull/27529
Test Plan: No references to it in this codebase.
Reviewed By: mdvacca
Differential Revision: D19087074
Pulled By: passy
fbshipit-source-id: a4ee73be7c13cedf1d86d2643f8e788ad4a2e31f
Summary:
This diff refactors ReactContext to use IllegalStateException instead of RuntimeException when applicable.
Changelog: [internal]
Reviewed By: JoshuaGross
Differential Revision: D18901845
fbshipit-source-id: 51ec36824c8402fa2c17e76c55578be44ec8aa15
Summary:
ExceptionManagers are created before the `ReactApplicationContext`. Once we make them all TurboModule-compatible, they'll also subclasses `ReactContextBaseJavaModule`. This means that they'll need to be created with `ReactApplicationContext`. Since one isn't available, we'll have to call `super(null)` in their constructor.
Changelog:
[Android][Changed] - Make ReactApplicationContext nullable as the constructor argument of ReactContextBaseJavaModule
Reviewed By: PeteTheHeat
Differential Revision: D18935950
fbshipit-source-id: a643a10a42cf36a2a2d6fde87795965f16295d43
Summary:
This diff exposes the getJSIModule on the ReactContext class.
This class already has methods to obtain NativeModules and JSModules, it make sense to expose the getJSIModule method too.
Changelog: [internal]
Reviewed By: JoshuaGross
Differential Revision: D18862858
fbshipit-source-id: 95fe48c065266060c96fc40a002041ba398b3134
Summary:
This method exposes a method to ReactContext to determine if we are running in Bridgeless mode or not
Changelog: [internal]
Reviewed By: JoshuaGross
Differential Revision: D18901149
fbshipit-source-id: bdd5ba747381f3bde5f592276b42244ca01ccbb9
Summary:
This diff promotes the UIManagerModule.getEventDispatcher() to the interface UIManager and it implements this method in FabricUIManager class.
Changelog: [internal]
Reviewed By: JoshuaGross
Differential Revision: D18862862
fbshipit-source-id: 424f0e601ed1807dbd5d33048daf7dc3bb200dcd
Summary: Removing the methods I recently added for storing/retrieving an instance key on a ReactContext.
Reviewed By: PeteTheHeat, mdvacca
Differential Revision: D18710637
fbshipit-source-id: d34683ec660bd999db8112865e15392606fc9237
Summary:
This diff adds extra logging in the method that handles exceptions for RN Android
Changelog: internal
Reviewed By: JoshuaGross
Differential Revision: D18694123
fbshipit-source-id: e275445b65473ed55eec9d4b823938e32fa805e5
Summary:
We need to make our ExceptionsManagers into TurboModules. To do so, we need to first make them type-safe. This requires extending the base class code-generated from the NativeModule JavaScript spec. That base class extends `ReactContextBaseJavaModule`, which requires `ReactApplicationContext` to instantiate. Unfortunatley, our ExceptionsManagers need to be created before the `ReactInstanceManager`. This means that the `ReactApplicationContext` isn't available by the time they're created.
In this diff, I make the `ReactContextBaseJavaModule` have a 0 argument constructor that simply sets its ReactApplicationContext to null. This will allow us to eventually migrate our ExceptionsManagers to the TurboModule system.
Changelog:
[Android][Added] - Give ReactContextBaseJavaModule a 0 arg ctor
Reviewed By: mdvacca
Differential Revision: D18717908
fbshipit-source-id: 203ffc49f2ec0b32a809402801795879d3b3a64b
Summary:
We read from / write to `CatalystInstanceImpl.mTurboModuleRegistry` from multiple threads. To ensure that we directly read/write from memory, and not a stale cache, we should make this variable `volatile`.
Changelog:
[Android][Fixed] Make TurboModuleRegistry in CatalystInstanceImpl.java volatile
Reviewed By: fkgozali
Differential Revision: D18542954
fbshipit-source-id: 0a47f05e0653b4f7f58503c678bdf31c68eab9bf
Summary:
Document which methods can be called on UI thread or ANY thread.
In the future we should see if we can use only `ThreadConfined` or the AndroidX annotations instead of using both / choosing between them at each site.
Changelog: [Internal]
Reviewed By: mdvacca
Differential Revision: D18532542
fbshipit-source-id: 3b5406ea5035615a0ebf83484bf8ec0747a6b6f7
Summary:
Fixes T54997838 by preventing any view mutations during `onMeasure` calls.
There might still be places where this is possible, but this is where I'm seeing all the crashes currently.
See comments in ReactRootView for why views were mutated during onMeasure.
Changelog: [Internal]
Reviewed By: mdvacca
Differential Revision: D18518591
fbshipit-source-id: 1406af8a6b0bfcc86f4cc5b451b3967f312dfd85
Summary:
Adding a new String field for `instanceKey` to ReactContext, which is set via a new constructor on ReactApplicationContext. Also adding getters to ReactContext and ThemedReactContext so that it's accessible from any instance/subclass of ReactContext.
This will only be used in bridgeless mode.
Reviewed By: mdvacca
Differential Revision: D18316556
fbshipit-source-id: 9757da72fde4ba36034c1e129326461fed496229
Summary:
Turns out that `SoftAssertions.java` has always been a lie - it actually always throws exceptions. Migrate it to using `ReactSoftException`.
This file hasn't been touched at all since it was originally open-sourced, besides codemods!
Changelog: [Internal]
Reviewed By: mdvacca
Differential Revision: D18336020
fbshipit-source-id: cba3db25a9f9d61325dd3f7843e92e984ae56281
Summary:
Looking at the crash reports from T46487253:
1. This crash happens only with TurboModule-compatible NativeModules.
2. Users who experience this crash are in the TurboModules test group.
Therefore, the crash happens while trying to load TurboModules.
The stack trace of the crash includes [this lookup via the NativeModule system](https://fburl.com/diffusion/vxj9goz5). When TurboModules are enabled, we can only start executing this line if one of two things are true:
1. The TurboModuleRegistry is null in CatalystInstanceImpl.
2. The TurboModuleRegistry isn't null but the NativeModule returned by the TurboModuleRegistry is null.
We can protect against 1 by asserting that when `ReactFeatureFlags.useTurboModules` is `true`, `mTurboModuleRegistry` is not null. Once this check lands, unless there's a race with setting `ReactFeatureFlags.useTurboModules`, we should be able to rule out 1.
Changelog:
[Added][Android] - Assert TurboModuleRegistry isn't null before using it in CatalystInstanceImpl
Reviewed By: PeteTheHeat
Differential Revision: D18211935
fbshipit-source-id: de88c033425c474ef80b73386b7182b1d3bb382f
Summary:
Mostly for easing open-source migration and not making a backwards-incompatible change (yet), we'll set this to false by default. Every app can opt-in to this if wanted but it's not necessary. This change is part of experiments surrounding more-aggressive teardown for Fabric and Bridgeless mode.
Changelog: [Internal] - This has the effect of (by default) disabling the previous diff which caused ReactContext teardown to always set mCatalystInstance to null. Now that is opt-in behavior and off by default, so it's not longer a breaking change.
Reviewed By: mdvacca
Differential Revision: D18207302
fbshipit-source-id: 7acfc894415e966f652c7049849eef79c440a135
Summary:
Simplify the API of `getReactApplicationContextIfActiveOrWarn`. We don't need to pass so much information into this method to collect good SoftExceptions.
Changelog: [Internal]
Reviewed By: mdvacca
Differential Revision: D18134400
fbshipit-source-id: 0a250ab0252a44121f3339a31506a0a6c4c7cd35
Summary:
In D18032458 we introduce getReactApplicationContextIfActiveOrWarn. In this diff, modules that access a JS or Native module through ReactApplicationContext need to check if the CatalystInstance is still alive before continuing.
Modules that don't derive from `ReactContextBaseJavaModule` manually check for the catalyst impl and log their own SoftExceptions.
In this diff we also introduce SoftExceptions that by contract never cause crashes, even in debug mode.
Changelog: [Internal]
Reviewed By: mdvacca
Differential Revision: D18112989
fbshipit-source-id: 868f01f388aa2db3518db9f873f2afc2a62eed45
Summary:
In three previous diffs (D18020359 D17998627 D17969056), I implemented this logic in three different modules. There are potentially hundreds of modules where we should be implementing this check, so I'm moving the important logic into ReactContextBaseJavaModule.
Additionally, `WebSocketModule` was retaining its own copy of ReactApplicationContext instead of using the built-in `getReactApplicationContext`, so I removed that ivar from `WebSocketModule`.
Changelog:
[Internal]
Reviewed By: mdvacca
Differential Revision: D18032458
fbshipit-source-id: 9114120d3b80334df8d2e0813e36d21c667fc1bd
Summary:
CatalystInstanceImpl.destroy does a bunch of stuff in each of the relevant threads (Native Module thread, JS thread, UI thread).
This change creates a V1 destroy method (unchanged) and a V2 destroy method. The goal is to resolve (and catch!) race conditions in native modules and JSI modules that could occur during teardown; and mitigate race conditions that occur in RN teardown, like deallocation of C++ objects (scheduler, JS VM, and UIManager for Fabric).
Changelog:
[Internal] Experiment to fix deallocation race conditions
Reviewed By: mdvacca
Differential Revision: D18001677
fbshipit-source-id: 5955da0a7b726491c7d749642475f0fba74cce5a
Summary:
We want ReactContext to blow up if it tries to use `mCatalystInstance` after `destroy` is called.
Changelog:
[[Internal]]
Reviewed By: mdvacca
Differential Revision: D17944723
fbshipit-source-id: cfe8a8b98473f53dd68bbcd91a71f58bd7a0c503
Summary:
This already has an assert that `destroy` should only be called on the UI thread. Add an annotation.
Changelog: [Internal]
Reviewed By: mdvacca
Differential Revision: D17989113
fbshipit-source-id: fd44f321cbcb7f0a18383ca6226cce72e5991eea
Summary: Oleksandr made the point that making `sDidInit` volatile isn't quite enough because the flag is set at the beginning of the function; it's possible that it will return true while it's still in the process of initializing the bridge. Moving where we set the flag to the end of the function should address the issue.
Reviewed By: JoshuaGross
Differential Revision: D17770128
fbshipit-source-id: 695d3edc582d9dce1884d8698d400dd147ca5cae
Summary: In D17747958 I added a function to check the value of a static variable, but forgot to make sure it was accessed in a thread-safe manner. Adding `volatile` to the flag
Reviewed By: makovkastar
Differential Revision: D17763888
fbshipit-source-id: f227b69de1a0df6493424da3b276529555999f70
Summary: Adding a hook to check if ReactBridge is initialized so we can avoid loading the .so on the main thread.
Reviewed By: fkgozali
Differential Revision: D17747958
fbshipit-source-id: 5969afa57dc1b446c03bc68eaa9e1385fe17c461
Summary:
`ReactRootView.startReactApplication` takes a `Bundle` argument called `initialProperties`. This is translated to a `ReadableMap` via `Arguments.fromBundle`. If the bundle contains an array of bundles, this gets translated by `Arguments.fromArray`.
If the bundle was passed from one activity to another via intent extras, however, there is a problem. After the bundle has been marshaled and unmarshaled, the array of `Bundle`s come out the other end as an arrap of `Parcelable`s, although each array element remains a `Bundle`. This results in an "Unknown array type" exception.
This PR fixes this by adding support for `Parcelable` arrays – provided they contain only members of type `Bundle`.
## Changelog
[Android] [Fixed] - Don't throw "Unknown array type" exception when passing serialized bundle arrays in ReactRootView.startReactApplication's initialProperties parameter
Pull Request resolved: https://github.com/facebook/react-native/pull/26379
Test Plan: Added test class `ArgumentsTest`. The test method `testFromMarshaledBundle` fails when used on the old version of `Arguments`.
Differential Revision: D17661203
Pulled By: cpojer
fbshipit-source-id: 63612d78f49bdf9cc53f6f21ae883dba6cebce84
Summary:
In `CatalystInstanceImpl.destroy()`, we require the TurboModuleManager using the [following lines](https://fburl.com/diffusion/a4y6wbft):
```
final JSIModule turboModuleManager =
ReactFeatureFlags.useTurboModules
? mJSIModuleRegistry.getModule(JSIModuleType.TurboModuleManager)
: null;
```
For some strange reason, even though `ReactFeatureFlags.useTurboModules` is true, the TurboModuleManager isn't registered with mJSIModuleRegistry. I spent some time looking through the code, but I couldn't figure out why. These lines actually aren't necessary, so it's possible to fix the issue by simply working around it, which is what this diff does. We shouldn't have been double requiring the TurboModuleManager anyways, since `CatalystInstance.java` has a method to set the TurboModuleManager, which we call in `ReactInstanceManager.createReactContext`.
## Alternative approach
I could push this diff to the next cut, and instead land a diff that adds debug information to the native crash. At the cost of a week, it may help us figure out why we're seeing the crash. Thoughts? cc fkgozali
Reviewed By: fkgozali
Differential Revision: D17636604
fbshipit-source-id: ecfff593dc6eb4ec4d5e331348b308bc7ab37966
Summary: CatalystInstanceImpl is responsible for creating the NativeModules thread. We therefore expose a method `getNativeCallInvokerHolder()` on this hybrid class to create and give us access to the `CallInvokerHolder` for the NativeModules thread.
Reviewed By: PeteTheHeat
Differential Revision: D17422164
fbshipit-source-id: 316423847518124115643549fa73a8533d493cd0
Summary:
## Motivation
The concept behind JSCallInvoker doesn't necessarily have to apply only to the JS thread. On Android, we need to re-use this abstraction to allow execution of async method calls on the NativeModules thread.
Reviewed By: PeteTheHeat
Differential Revision: D17377313
fbshipit-source-id: 3d9075cbfce0b908d800a366947cfd16a3013d1c
Summary:
We probably don't always need to crash in these cases.
This should replace all prod/dev crashes with logged SoftExceptions.
Note that this is currently only used for Fabric.
Changelog:
[Internal]
Reviewed By: mdvacca
Differential Revision: D17170459
fbshipit-source-id: 70757ae88deb8c893b36971d879174e25a194fb9
Summary:
## Summary
When an exception is raised by Java in a synchronous call from JS to Java, the Java portion of the stack trace is simply ignored when the exception is forwarded to JS. This problem doesn't exist for async calls. I did some digging to figure out why this works with async calls, but not sync calls, to get to the bottom of T52585087.
In T52585087, `TurboModuleRegistry.get<Spec>('I18nAssets')` fails because of a `NullPointerException` in Java. However, since there's no stack trace associated with the `NullPointerException`, it's hard to diagnose the problem.
## Asynchronous calls
ReactNative's NativeModules thread is a background thread on which we schedule asynchronous NativeModule method invocations. We spawn our background threads in Java using the [`MessageQueueThreadImpl`](https://fburl.com/diffusion/u0vdm5k3). Each thread is associated with a queue on which you can schedule some work. These `MessageQueueThread`s have a [C++ API](https://fburl.com/diffusion/596740d8) that we can use to schedule some work from C++.
NativeModule method invocations in JS produce a C++/Java boundry, because our JS executes C++, which executes the Java NativeModule method. But since the method is asynchronous, instead of invoking it immediately, we wrap it in a C++ lambda and use the C++ API of `MessageQueueThread` to schedule it to be invoked later. Therefore, when it actually invokes, we'll get Java invoking C++, which invokes Java.
When the NativeModule method (implemented in Java) throws an exception, fbjni will convert that exception into a `jni::JniException` and start unwinding the C++ stack. Eventually, this exception will reach the outermost Java/C++ boundry. Typically, at this point, the program would crash, but because we used fbjni to register all our native functions, our `jni::JniException` will automatically be converted into a regular Java exception. This exception will be caught by MessageQueueThreadHandler [here](https://fburl.com/diffusion/c4thoca7), and handled using our ExceptionHandler NativeModule.
## Synchronous calls
In synchronous execution, JS uses a `JSI::HostObject` to call the Java method directly. If the Java method throws an error, because we're using fbjni, that Java exception will be converted to a `jni::JniException` object, which will contain the stack tract of the Java object. However, from what I could gather, Hermes doesn't know about `jni::JniException`. So, simply ignore the stack trace associated with the Java exception, understanding only the exception message. Hence, all synchronous calls into Java only display the JS stack trace. What we really want is to build an platform-agnostic abstraction that understands `jni::JniException` (and whatever its analogue is in iOS, if any) and use that to bridge between Native and JS.
## Temporary Solution
We know that when NativeModules are created, we do a synchronous call from JS to C++ to Java. This synchronous call happens when you do a property access on the `NativeModules` object. Therefore, at the very least, to get to the bottom of T52585087, we could log all exceptions that are thrown whenever a NativeModule is created. This should help us get to the bottom of T52585087.
Reviewed By: mdvacca
Differential Revision: D17126667
fbshipit-source-id: a6fb27aaea094b9559939ddcc260d3a2c6e71492