diff --git a/packages/react-native/Libraries/Core/ExceptionsManager.js b/packages/react-native/Libraries/Core/ExceptionsManager.js index a0b22359ea0..ecb2171961e 100644 --- a/packages/react-native/Libraries/Core/ExceptionsManager.js +++ b/packages/react-native/Libraries/Core/ExceptionsManager.js @@ -121,6 +121,12 @@ function reportException( const NativeExceptionsManager = require('./NativeExceptionsManager').default; if (NativeExceptionsManager) { + if (isFatal) { + if (global.RN$hasHandledFatalException?.()) { + return; + } + global.RN$notifyOfFatalException?.(); + } NativeExceptionsManager.reportException(data); } } diff --git a/packages/react-native/ReactCommon/jserrorhandler/JsErrorHandler.cpp b/packages/react-native/ReactCommon/jserrorhandler/JsErrorHandler.cpp index 6742322af13..fda5c18920e 100644 --- a/packages/react-native/ReactCommon/jserrorhandler/JsErrorHandler.cpp +++ b/packages/react-native/ReactCommon/jserrorhandler/JsErrorHandler.cpp @@ -232,10 +232,6 @@ void JsErrorHandler::handleError( if (!ReactNativeFeatureFlags::useAlwaysAvailableJSErrorHandling() && _isRuntimeReady) { - if (isFatal) { - _hasHandledFatalError = true; - } - try { handleJSError(runtime, error, isFatal); return; @@ -382,7 +378,7 @@ void JsErrorHandler::handleErrorWithCppPipeline( } } - if (*shouldPreventDefault) { + if (*shouldPreventDefault || _hasHandledFatalError) { return; } diff --git a/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp b/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp index f24a006e697..2a695fc28b2 100644 --- a/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp +++ b/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp @@ -436,6 +436,37 @@ void ReactInstance::initializeRuntime( return jsErrorHandler->isRuntimeReady(); })); + defineReadOnlyGlobal( + runtime, + "RN$hasHandledFatalException", + jsi::Function::createFromHostFunction( + runtime, + jsi::PropNameID::forAscii(runtime, "hasHandledFatalException"), + 0, + [jsErrorHandler = jsErrorHandler_]( + jsi::Runtime& /*runtime*/, + const jsi::Value& /*unused*/, + const jsi::Value* /*args*/, + size_t /*count*/) { + return jsErrorHandler->hasHandledFatalError(); + })); + + defineReadOnlyGlobal( + runtime, + "RN$notifyOfFatalException", + jsi::Function::createFromHostFunction( + runtime, + jsi::PropNameID::forAscii(runtime, "notifyOfFatalException"), + 0, + [jsErrorHandler = jsErrorHandler_]( + jsi::Runtime& /*runtime*/, + const jsi::Value& /*unused*/, + const jsi::Value* /*args*/, + size_t /*count*/) { + jsErrorHandler->notifyOfFatalError(); + return jsi::Value::undefined(); + })); + defineReadOnlyGlobal( runtime, "RN$inExceptionHandler", @@ -475,10 +506,6 @@ void ReactInstance::initializeRuntime( if (!ReactNativeFeatureFlags:: useAlwaysAvailableJSErrorHandling()) { if (jsErrorHandler->isRuntimeReady()) { - if (isFatal) { - jsErrorHandler->notifyOfFatalError(); - } - return jsi::Value(false); } }