Skip to content
This repository was archived by the owner on Jun 16, 2026. It is now read-only.

Commit 64fcffb

Browse files
authored
Merge pull request #85 from SudoPlz/sudoplz/fix-runtime-scheduler-flush-microtasks
fix(RuntimeScheduler): flush JS microtasks after work-loop to prevent…
2 parents dee1f2c + f79dd30 commit 64fcffb

3 files changed

Lines changed: 52 additions & 1 deletion

File tree

packages/react-native/Libraries/Core/Timers/JSTimers.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,4 +484,12 @@ BatchedBridge.setReactNativeMicrotasksCallback(
484484
JSTimers.callReactNativeMicrotasks,
485485
);
486486

487+
/**
488+
* This is a hack to allow us to flush react native microtasks
489+
* from the native side when bridgeless mode is disabled.
490+
*/
491+
global._flushReactNativeMicrotasks = () => {
492+
return JSTimers.callReactNativeMicrotasks();
493+
}
494+
487495
module.exports = ExportedJSTimers;

packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Legacy.cpp

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77

88
#include "RuntimeScheduler_Legacy.h"
99
#include "SchedulerPriorityUtils.h"
10-
1110
#include <cxxreact/TraceSection.h>
1211
#include <react/renderer/consistency/ScopedShadowTreeRevisionLock.h>
1312
#include <utility>
13+
#include <react/utils/OnScopeExit.h>
1414

1515
namespace facebook::react {
1616

@@ -24,6 +24,40 @@ RuntimeScheduler_Legacy::RuntimeScheduler_Legacy(
2424
now_(std::move(now)),
2525
onTaskError_(std::move(onTaskError)) {}
2626

27+
void RuntimeScheduler_Legacy::performMicrotaskCheckpoint(jsi::Runtime& runtime) noexcept {
28+
if (performingMicrotaskCheckpoint_) {
29+
return;
30+
}
31+
performingMicrotaskCheckpoint_ = true;
32+
OnScopeExit restoreFlag([&]() { performingMicrotaskCheckpoint_ = false; });
33+
TraceSection s("RuntimeScheduler::performMicrotaskCheckpoint");
34+
35+
try {
36+
// Get the global object
37+
auto global = runtime.global();
38+
39+
// Check if _flushReactNativeMicrotasks exists on the global object
40+
if (global.hasProperty(runtime, "_flushReactNativeMicrotasks")) {
41+
auto flushFunction = global.getProperty(runtime, "_flushReactNativeMicrotasks");
42+
43+
// Check if it's actually a function
44+
if (flushFunction.isObject() && flushFunction.getObject(runtime).isFunction(runtime)) {
45+
auto function = flushFunction.getObject(runtime).getFunction(runtime);
46+
47+
// Call the function with no arguments
48+
function.call(runtime);
49+
}
50+
}
51+
} catch (jsi::JSError& error) {
52+
// If there's an error calling the function, handle it gracefully
53+
onTaskError_(runtime, error);
54+
} catch (std::exception& ex) {
55+
// Handle any other exceptions
56+
jsi::JSError error(runtime, std::string("Non-js exception in performMicrotaskCheckpoint: ") + ex.what());
57+
onTaskError_(runtime, error);
58+
}
59+
}
60+
2761
void RuntimeScheduler_Legacy::scheduleWork(RawCallback&& callback) noexcept {
2862
TraceSection s("RuntimeScheduler::scheduleWork");
2963

@@ -233,6 +267,7 @@ void RuntimeScheduler_Legacy::startWorkLoop(jsi::Runtime& runtime) {
233267
}
234268

235269
executeTask(runtime, topPriorityTask, didUserCallbackTimeout);
270+
performMicrotaskCheckpoint(runtime);
236271
}
237272
} catch (jsi::JSError& error) {
238273
onTaskError_(runtime, error);

packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Legacy.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,14 @@ class RuntimeScheduler_Legacy final : public RuntimeSchedulerBase {
186186
nullptr};
187187

188188
RuntimeSchedulerTaskErrorHandler onTaskError_;
189+
190+
/*
191+
* This allows the C++ code to trigger microtask flushing from JavaScript.
192+
*/
193+
void performMicrotaskCheckpoint(jsi::Runtime& runtime) noexcept;
194+
195+
private:
196+
bool performingMicrotaskCheckpoint_{false};
189197
};
190198

191199
} // namespace facebook::react

0 commit comments

Comments
 (0)