Refactor: RuntimeScheduler: Make error hander configurable

Summary:
## History
1. Originally landed in D60138415
2. Reverted in D60232011 (it broke ios oss builds)

## Motivation
In bridgeless, we want to configure the error handling of runtime scheduler. So that we can route those errors to the C++ error handling pipeline, when necessary.

Changelog: [Internal]

Reviewed By: rubennorte

Differential Revision: D60477342

fbshipit-source-id: f14e20d7aff39e0fee42918567ccc6e685674134
This commit is contained in:
Ramanpreet Nara
2024-08-14 20:43:11 -07:00
committed by Facebook GitHub Bot
parent 68c0720e34
commit bc930441cf
6 changed files with 47 additions and 18 deletions
@@ -10,6 +10,7 @@
#include "RuntimeScheduler_Modern.h"
#include "SchedulerPriorityUtils.h"
#include <cxxreact/ErrorUtils.h>
#include <cxxreact/SystraceSection.h>
#include <react/featureflags/ReactNativeFeatureFlags.h>
#include <utility>
@@ -19,23 +20,33 @@ namespace facebook::react {
namespace {
std::unique_ptr<RuntimeSchedulerBase> getRuntimeSchedulerImplementation(
RuntimeExecutor runtimeExecutor,
std::function<RuntimeSchedulerTimePoint()> now) {
std::function<RuntimeSchedulerTimePoint()> now,
RuntimeSchedulerTaskErrorHandler onTaskError) {
if (ReactNativeFeatureFlags::useModernRuntimeScheduler()) {
return std::make_unique<RuntimeScheduler_Modern>(
std::move(runtimeExecutor), std::move(now));
std::move(runtimeExecutor), std::move(now), std::move(onTaskError));
} else {
return std::make_unique<RuntimeScheduler_Legacy>(
std::move(runtimeExecutor), std::move(now));
std::move(runtimeExecutor), std::move(now), std::move(onTaskError));
}
}
} // namespace
RuntimeScheduler::RuntimeScheduler(
RuntimeExecutor runtimeExecutor,
std::function<RuntimeSchedulerTimePoint()> now)
std::function<RuntimeSchedulerTimePoint()> now,
RuntimeSchedulerTaskErrorHandler onTaskError)
: runtimeSchedulerImpl_(getRuntimeSchedulerImplementation(
std::move(runtimeExecutor),
std::move(now))) {}
std::move(now),
std::move(onTaskError))) {}
/* static */ void RuntimeScheduler::handleTaskErrorDefault(
jsi::Runtime& runtime,
jsi::JSError& error) {
handleJSError(runtime, error, true);
}
void RuntimeScheduler::scheduleWork(RawCallback&& callback) noexcept {
return runtimeSchedulerImpl_->scheduleWork(std::move(callback));
@@ -19,6 +19,9 @@ namespace facebook::react {
using RuntimeSchedulerRenderingUpdate = std::function<void()>;
using RuntimeSchedulerTimeout = std::chrono::milliseconds;
using RuntimeSchedulerTaskErrorHandler =
std::function<void(jsi::Runtime& runtime, jsi::JSError& error)>;
// This is a temporary abstract class for RuntimeScheduler forks to implement
// (and use them interchangeably).
class RuntimeSchedulerBase {
@@ -60,7 +63,8 @@ class RuntimeScheduler final : RuntimeSchedulerBase {
explicit RuntimeScheduler(
RuntimeExecutor runtimeExecutor,
std::function<RuntimeSchedulerTimePoint()> now =
RuntimeSchedulerClock::now);
RuntimeSchedulerClock::now,
RuntimeSchedulerTaskErrorHandler onTaskError = handleTaskErrorDefault);
/*
* Not copyable.
@@ -163,6 +167,10 @@ class RuntimeScheduler final : RuntimeSchedulerBase {
// Actual implementation, stored as a unique pointer to simplify memory
// management.
std::unique_ptr<RuntimeSchedulerBase> runtimeSchedulerImpl_;
static void handleTaskErrorDefault(
jsi::Runtime& runtime,
jsi::JSError& error);
};
} // namespace facebook::react
@@ -8,7 +8,6 @@
#include "RuntimeScheduler_Legacy.h"
#include "SchedulerPriorityUtils.h"
#include <cxxreact/ErrorUtils.h>
#include <cxxreact/SystraceSection.h>
#include <react/renderer/consistency/ScopedShadowTreeRevisionLock.h>
#include <utility>
@@ -19,8 +18,11 @@ namespace facebook::react {
RuntimeScheduler_Legacy::RuntimeScheduler_Legacy(
RuntimeExecutor runtimeExecutor,
std::function<RuntimeSchedulerTimePoint()> now)
: runtimeExecutor_(std::move(runtimeExecutor)), now_(std::move(now)) {}
std::function<RuntimeSchedulerTimePoint()> now,
RuntimeSchedulerTaskErrorHandler onTaskError)
: runtimeExecutor_(std::move(runtimeExecutor)),
now_(std::move(now)),
onTaskError_(std::move(onTaskError)) {}
void RuntimeScheduler_Legacy::scheduleWork(RawCallback&& callback) noexcept {
SystraceSection s("RuntimeScheduler::scheduleWork");
@@ -167,7 +169,7 @@ void RuntimeScheduler_Legacy::callExpiredTasks(jsi::Runtime& runtime) {
executeTask(runtime, topPriorityTask, didUserCallbackTimeout);
}
} catch (jsi::JSError& error) {
handleJSError(runtime, error, true);
onTaskError_(runtime, error);
}
currentPriority_ = previousPriority;
@@ -224,7 +226,7 @@ void RuntimeScheduler_Legacy::startWorkLoop(jsi::Runtime& runtime) {
executeTask(runtime, topPriorityTask, didUserCallbackTimeout);
}
} catch (jsi::JSError& error) {
handleJSError(runtime, error, true);
onTaskError_(runtime, error);
}
currentPriority_ = previousPriority;
@@ -22,7 +22,8 @@ class RuntimeScheduler_Legacy final : public RuntimeSchedulerBase {
public:
explicit RuntimeScheduler_Legacy(
RuntimeExecutor runtimeExecutor,
std::function<RuntimeSchedulerTimePoint()> now);
std::function<RuntimeSchedulerTimePoint()> now,
RuntimeSchedulerTaskErrorHandler onTaskError);
/*
* Not copyable.
@@ -179,6 +180,8 @@ class RuntimeScheduler_Legacy final : public RuntimeSchedulerBase {
ShadowTreeRevisionConsistencyManager* shadowTreeRevisionConsistencyManager_{
nullptr};
RuntimeSchedulerTaskErrorHandler onTaskError_;
};
} // namespace facebook::react
@@ -8,7 +8,6 @@
#include "RuntimeScheduler_Modern.h"
#include "SchedulerPriorityUtils.h"
#include <cxxreact/ErrorUtils.h>
#include <cxxreact/SystraceSection.h>
#include <react/featureflags/ReactNativeFeatureFlags.h>
#include <react/renderer/consistency/ScopedShadowTreeRevisionLock.h>
@@ -33,8 +32,11 @@ std::chrono::milliseconds getResolvedTimeoutForIdleTask(
RuntimeScheduler_Modern::RuntimeScheduler_Modern(
RuntimeExecutor runtimeExecutor,
std::function<RuntimeSchedulerTimePoint()> now)
: runtimeExecutor_(std::move(runtimeExecutor)), now_(std::move(now)) {}
std::function<RuntimeSchedulerTimePoint()> now,
RuntimeSchedulerTaskErrorHandler onTaskError)
: runtimeExecutor_(std::move(runtimeExecutor)),
now_(std::move(now)),
onTaskError_(std::move(onTaskError)) {}
void RuntimeScheduler_Modern::scheduleWork(RawCallback&& callback) noexcept {
SystraceSection s("RuntimeScheduler::scheduleWork");
@@ -384,7 +386,7 @@ void RuntimeScheduler_Modern::executeTask(
task.callback = result.getObject(runtime).getFunction(runtime);
}
} catch (jsi::JSError& error) {
handleJSError(runtime, error, true);
onTaskError_(runtime, error);
}
}
@@ -418,7 +420,7 @@ void RuntimeScheduler_Modern::performMicrotaskCheckpoint(
break;
}
} catch (jsi::JSError& error) {
handleJSError(runtime, error, true);
onTaskError_(runtime, error);
}
retries++;
}
@@ -23,7 +23,8 @@ class RuntimeScheduler_Modern final : public RuntimeSchedulerBase {
public:
explicit RuntimeScheduler_Modern(
RuntimeExecutor runtimeExecutor,
std::function<RuntimeSchedulerTimePoint()> now);
std::function<RuntimeSchedulerTimePoint()> now,
RuntimeSchedulerTaskErrorHandler onTaskError);
/*
* Not copyable.
@@ -222,6 +223,8 @@ class RuntimeScheduler_Modern final : public RuntimeSchedulerBase {
nullptr};
PerformanceEntryReporter* performanceEntryReporter_{nullptr};
RuntimeSchedulerTaskErrorHandler onTaskError_;
};
} // namespace facebook::react