Skip to content
This repository was archived by the owner on Jun 16, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions packages/react-native/Libraries/Core/Timers/JSTimers.js
Original file line number Diff line number Diff line change
Expand Up @@ -484,4 +484,12 @@ BatchedBridge.setReactNativeMicrotasksCallback(
JSTimers.callReactNativeMicrotasks,
);

/**
* This is a hack to allow us to flush react native microtasks
* from the native side when bridgeless mode is disabled.
*/
global._flushReactNativeMicrotasks = () => {
return JSTimers.callReactNativeMicrotasks();
}

module.exports = ExportedJSTimers;
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@

#include "RuntimeScheduler_Legacy.h"
#include "SchedulerPriorityUtils.h"

#include <cxxreact/TraceSection.h>
#include <react/renderer/consistency/ScopedShadowTreeRevisionLock.h>
#include <utility>
#include <react/utils/OnScopeExit.h>

namespace facebook::react {

Expand All @@ -24,6 +24,40 @@ RuntimeScheduler_Legacy::RuntimeScheduler_Legacy(
now_(std::move(now)),
onTaskError_(std::move(onTaskError)) {}

void RuntimeScheduler_Legacy::performMicrotaskCheckpoint(jsi::Runtime& runtime) noexcept {
if (performingMicrotaskCheckpoint_) {
return;
}
performingMicrotaskCheckpoint_ = true;
OnScopeExit restoreFlag([&]() { performingMicrotaskCheckpoint_ = false; });
TraceSection s("RuntimeScheduler::performMicrotaskCheckpoint");

try {
// Get the global object
auto global = runtime.global();

// Check if _flushReactNativeMicrotasks exists on the global object
if (global.hasProperty(runtime, "_flushReactNativeMicrotasks")) {
auto flushFunction = global.getProperty(runtime, "_flushReactNativeMicrotasks");

// Check if it's actually a function
if (flushFunction.isObject() && flushFunction.getObject(runtime).isFunction(runtime)) {
auto function = flushFunction.getObject(runtime).getFunction(runtime);

// Call the function with no arguments
function.call(runtime);
}
}
} catch (jsi::JSError& error) {
// If there's an error calling the function, handle it gracefully
onTaskError_(runtime, error);
} catch (std::exception& ex) {
// Handle any other exceptions
jsi::JSError error(runtime, std::string("Non-js exception in performMicrotaskCheckpoint: ") + ex.what());
onTaskError_(runtime, error);
}
}

void RuntimeScheduler_Legacy::scheduleWork(RawCallback&& callback) noexcept {
TraceSection s("RuntimeScheduler::scheduleWork");

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

executeTask(runtime, topPriorityTask, didUserCallbackTimeout);
performMicrotaskCheckpoint(runtime);
}
} catch (jsi::JSError& error) {
onTaskError_(runtime, error);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,14 @@ class RuntimeScheduler_Legacy final : public RuntimeSchedulerBase {
nullptr};

RuntimeSchedulerTaskErrorHandler onTaskError_;

/*
* This allows the C++ code to trigger microtask flushing from JavaScript.
*/
void performMicrotaskCheckpoint(jsi::Runtime& runtime) noexcept;

private:
bool performingMicrotaskCheckpoint_{false};
};

} // namespace facebook::react
Loading