From ca7b9e950935e349cd6bdb730bed7ec7149c4d06 Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Mon, 11 Nov 2024 13:24:49 -0800 Subject: [PATCH] earlyjs: Extend C++ pipeline for non-js errors (#47529) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/47529 RuntimeExecutor, RuntimeScheduler, etc. can execute arbitrary c++ on the javascript thread. If that c++ throws a non-jsi::JSError, it will bypass the js error handler (and start tearing down the react instance 😱). Let's have the js error handler manage all exceptions raised while native is calling into js. This is more sane. Changelog: [Internal] Reviewed By: sammy-SC Differential Revision: D64626610 fbshipit-source-id: 40132f24b4e2737ae3f055fbd09153111404e5bf --- .../renderer/runtimescheduler/RuntimeScheduler_Legacy.cpp | 6 ++++++ .../renderer/runtimescheduler/RuntimeScheduler_Modern.cpp | 7 +++++++ .../ReactCommon/react/runtime/ReactInstance.cpp | 4 ++++ 3 files changed, 17 insertions(+) diff --git a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Legacy.cpp b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Legacy.cpp index 53929ef00ac..577eda29308 100644 --- a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Legacy.cpp +++ b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Legacy.cpp @@ -170,6 +170,9 @@ void RuntimeScheduler_Legacy::callExpiredTasks(jsi::Runtime& runtime) { } } catch (jsi::JSError& error) { onTaskError_(runtime, error); + } catch (std::exception& ex) { + jsi::JSError error(runtime, std::string("Non-js exception: ") + ex.what()); + onTaskError_(runtime, error); } currentPriority_ = previousPriority; @@ -233,6 +236,9 @@ void RuntimeScheduler_Legacy::startWorkLoop(jsi::Runtime& runtime) { } } catch (jsi::JSError& error) { onTaskError_(runtime, error); + } catch (std::exception& ex) { + jsi::JSError error(runtime, std::string("Non-js exception: ") + ex.what()); + onTaskError_(runtime, error); } currentPriority_ = previousPriority; diff --git a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Modern.cpp b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Modern.cpp index 0a05dd76b33..7a6eddf8506 100644 --- a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Modern.cpp +++ b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Modern.cpp @@ -386,6 +386,9 @@ void RuntimeScheduler_Modern::executeTask( } } catch (jsi::JSError& error) { onTaskError_(runtime, error); + } catch (std::exception& ex) { + jsi::JSError error(runtime, std::string("Non-js exception: ") + ex.what()); + onTaskError_(runtime, error); } } @@ -420,6 +423,10 @@ void RuntimeScheduler_Modern::performMicrotaskCheckpoint( } } catch (jsi::JSError& error) { onTaskError_(runtime, error); + } catch (std::exception& ex) { + jsi::JSError error( + runtime, std::string("Non-js exception: ") + ex.what()); + onTaskError_(runtime, error); } retries++; } diff --git a/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp b/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp index bb19ff78d8b..f6c07d7ff79 100644 --- a/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp +++ b/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp @@ -103,6 +103,10 @@ ReactInstance::ReactInstance( } } catch (jsi::JSError& originalError) { jsErrorHandler->handleError(jsiRuntime, originalError, true); + } catch (std::exception& ex) { + jsi::JSError error( + jsiRuntime, std::string("Non-js exception: ") + ex.what()); + jsErrorHandler->handleError(jsiRuntime, error, true); } }); }