Skip to content

Commit c02e3b1

Browse files
RSNarafacebook-github-bot
authored andcommitted
Only handle the first javascript fatal error (#47783)
Summary: Pull Request resolved: #47783 After the first javascript fatal, the runtime starts tearing down. And it becomes invalid. So, subsequent js fatals will most likely be just noise. Let's filter them out. This impacts bridgeless mode: both the javascript and c++ pipeline. Changelog: [Internal] Reviewed By: mdvacca Differential Revision: D66193194 fbshipit-source-id: 61a731850f7ac4f00bfac24e3260673bf94ba8ed
1 parent 451ff70 commit c02e3b1

File tree

3 files changed

+38
-9
lines changed

3 files changed

+38
-9
lines changed

packages/react-native/Libraries/Core/ExceptionsManager.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,12 @@ function reportException(
121121
const NativeExceptionsManager =
122122
require('./NativeExceptionsManager').default;
123123
if (NativeExceptionsManager) {
124+
if (isFatal) {
125+
if (global.RN$hasHandledFatalException?.()) {
126+
return;
127+
}
128+
global.RN$notifyOfFatalException?.();
129+
}
124130
NativeExceptionsManager.reportException(data);
125131
}
126132
}

packages/react-native/ReactCommon/jserrorhandler/JsErrorHandler.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -232,10 +232,6 @@ void JsErrorHandler::handleError(
232232

233233
if (!ReactNativeFeatureFlags::useAlwaysAvailableJSErrorHandling() &&
234234
_isRuntimeReady) {
235-
if (isFatal) {
236-
_hasHandledFatalError = true;
237-
}
238-
239235
try {
240236
handleJSError(runtime, error, isFatal);
241237
return;
@@ -382,7 +378,7 @@ void JsErrorHandler::handleErrorWithCppPipeline(
382378
}
383379
}
384380

385-
if (*shouldPreventDefault) {
381+
if (*shouldPreventDefault || _hasHandledFatalError) {
386382
return;
387383
}
388384

packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,37 @@ void ReactInstance::initializeRuntime(
436436
return jsErrorHandler->isRuntimeReady();
437437
}));
438438

439+
defineReadOnlyGlobal(
440+
runtime,
441+
"RN$hasHandledFatalException",
442+
jsi::Function::createFromHostFunction(
443+
runtime,
444+
jsi::PropNameID::forAscii(runtime, "hasHandledFatalException"),
445+
0,
446+
[jsErrorHandler = jsErrorHandler_](
447+
jsi::Runtime& /*runtime*/,
448+
const jsi::Value& /*unused*/,
449+
const jsi::Value* /*args*/,
450+
size_t /*count*/) {
451+
return jsErrorHandler->hasHandledFatalError();
452+
}));
453+
454+
defineReadOnlyGlobal(
455+
runtime,
456+
"RN$notifyOfFatalException",
457+
jsi::Function::createFromHostFunction(
458+
runtime,
459+
jsi::PropNameID::forAscii(runtime, "notifyOfFatalException"),
460+
0,
461+
[jsErrorHandler = jsErrorHandler_](
462+
jsi::Runtime& /*runtime*/,
463+
const jsi::Value& /*unused*/,
464+
const jsi::Value* /*args*/,
465+
size_t /*count*/) {
466+
jsErrorHandler->notifyOfFatalError();
467+
return jsi::Value::undefined();
468+
}));
469+
439470
defineReadOnlyGlobal(
440471
runtime,
441472
"RN$inExceptionHandler",
@@ -475,10 +506,6 @@ void ReactInstance::initializeRuntime(
475506
if (!ReactNativeFeatureFlags::
476507
useAlwaysAvailableJSErrorHandling()) {
477508
if (jsErrorHandler->isRuntimeReady()) {
478-
if (isFatal) {
479-
jsErrorHandler->notifyOfFatalError();
480-
}
481-
482509
return jsi::Value(false);
483510
}
484511
}

0 commit comments

Comments
 (0)