Skip to content

Commit

Permalink
Route fatal js errors caught in js through JsErrorHandler
Browse files Browse the repository at this point in the history
Summary:
If a fatal error is caught in js, and the js pipeline isn't ready, route it through the c++ pipeline.

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D60138414

fbshipit-source-id: 333e38e2b904d6434a88469816e39bf1b9d0bc3f
  • Loading branch information
RSNara authored and facebook-github-bot committed Aug 15, 2024
1 parent dd7be8d commit 7fce717
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 1 deletion.
8 changes: 7 additions & 1 deletion packages/react-native/Libraries/Core/setUpErrorHandling.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,13 @@ ExceptionsManager.installConsoleErrorReporter();
if (!global.__fbDisableExceptionsManager) {
const handleError = (e: mixed, isFatal: boolean) => {
try {
ExceptionsManager.handleException(e, isFatal);
// TODO(T196834299): We should really use a c++ turbomodule for this
if (
!global.RN$handleException ||
!global.RN$handleException(e, isFatal)
) {
ExceptionsManager.handleException(e, isFatal);
}
} catch (ee) {
console.log('Failed to print error: ', ee.message);
throw e;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,4 +143,8 @@ bool JsErrorHandler::isRuntimeReady() {
return _isRuntimeReady;
}

void JsErrorHandler::notifyOfFatalError() {
_hasHandledFatalError = true;
}

} // namespace facebook::react
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class JsErrorHandler {
bool hasHandledFatalError();
void setRuntimeReady();
bool isRuntimeReady();
void notifyOfFatalError();

private:
/**
Expand Down
43 changes: 43 additions & 0 deletions packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,11 @@ void defineReactInstanceFlags(
}
}

bool isTruthy(jsi::Runtime& runtime, const jsi::Value& value) {
auto Boolean = runtime.global().getPropertyAsFunction(runtime, "Boolean");
return Boolean.call(runtime, value).getBool();
}

} // namespace

void ReactInstance::initializeRuntime(
Expand All @@ -375,6 +380,44 @@ void ReactInstance::initializeRuntime(

defineReactInstanceFlags(runtime, options);

// TODO(T196834299): We should really use a C++ turbomodule for this
defineReadOnlyGlobal(
runtime,
"RN$handleException",
jsi::Function::createFromHostFunction(
runtime,
jsi::PropNameID::forAscii(runtime, "handleException"),
2,
[jsErrorHandler = jsErrorHandler_](
jsi::Runtime& runtime,
const jsi::Value& /*unused*/,
const jsi::Value* args,
size_t count) {
if (count < 2) {
throw jsi::JSError(
runtime,
"handleException requires 2 arguments: error, isFatal");
}

auto isFatal = isTruthy(runtime, args[1]);
if (jsErrorHandler->isRuntimeReady()) {
if (isFatal) {
jsErrorHandler->notifyOfFatalError();
}

return jsi::Value(false);
}

if (isFatal) {
auto jsError =
jsi::JSError(runtime, jsi::Value(runtime, args[0]));
jsErrorHandler->handleFatalError(runtime, jsError);
return jsi::Value(true);
}

return jsi::Value(false);
}));

defineReadOnlyGlobal(
runtime,
"RN$registerCallableModule",
Expand Down

0 comments on commit 7fce717

Please sign in to comment.