Report early js exceptions on the js thread (#46116)

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

If your app raises an early js exception, and you cold start it, often you'll see this error:

```
SurfaceRegistryBinding::startSurface failed. Global was not installed.
```

{F1807125099}

The reason why is because two different threads race to redbox:
* The nativemodule thread: the early js error (reported [here](https://fburl.com/code/vcrqzsdp))
* The javascript thread: the SurfaceRegistryBinding error (a subsequent native -> js call)

After this diff, the early js error will **not jump onto the nativemodule thread** to report this error.

This ensures that we "always" (to the best of my knowledge) see the early js error first.

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D61339213

fbshipit-source-id: f1b9ab30150b87377817c2fd93ca349c406db48b
This commit is contained in:
Ramanpreet Nara
2024-08-20 17:50:55 -07:00
committed by Facebook GitHub Bot
parent ee597bfe2b
commit a949e0d751
@@ -156,7 +156,7 @@ final class ReactInstance {
nativeModulesMessageQueueThread,
mJavaTimerManager,
jsTimerExecutor,
new ReactJsExceptionHandlerImpl(nativeModulesMessageQueueThread),
new ReactJsExceptionHandlerImpl(exceptionHandler),
bindingsInstaller,
isProfiling,
reactHostInspectorTarget);
@@ -318,25 +318,28 @@ final class ReactInstance {
}
private class ReactJsExceptionHandlerImpl implements ReactJsExceptionHandler {
private final MessageQueueThread mMessageQueueThread;
private final QueueThreadExceptionHandler mQueueThreadExceptionHandler;
ReactJsExceptionHandlerImpl(MessageQueueThread nativeModulesMessageQueueThread) {
mMessageQueueThread = nativeModulesMessageQueueThread;
ReactJsExceptionHandlerImpl(QueueThreadExceptionHandler queueThreadExceptionHandler) {
mQueueThreadExceptionHandler = queueThreadExceptionHandler;
}
@Override
public void reportJsException(ParsedError error) {
JavaOnlyMap data = StackTraceHelper.convertParsedError(error);
// Simulate async native module method call
mMessageQueueThread.runOnQueue(
() -> {
NativeExceptionsManagerSpec exceptionsManager =
(NativeExceptionsManagerSpec)
Assertions.assertNotNull(
mTurboModuleManager.getModule(NativeExceptionsManagerSpec.NAME));
exceptionsManager.reportException(data);
});
try {
NativeExceptionsManagerSpec exceptionsManager =
(NativeExceptionsManagerSpec)
Assertions.assertNotNull(
mTurboModuleManager.getModule(NativeExceptionsManagerSpec.NAME));
exceptionsManager.reportException(data);
} catch (Exception e) {
// Sometimes (e.g: always with the default exception manager) the native module exceptions
// manager can throw. In those cases, call into the lower-level queue thread exceptions
// handler.
mQueueThreadExceptionHandler.handleException(e);
}
}
}