This repository was archived by the owner on Jun 16, 2026. It is now read-only.
fix(RuntimeScheduler): flush JS microtasks after work-loop to prevent…#85
Merged
SudoPlz merged 1 commit intoJul 23, 2025
Conversation
… Reanimated stalls React-Freeze’s infiniteThenable causes Fabric’s RuntimeScheduler_Legacy to spin indefinitely within the while loop within startWorkLoop, which prevents the JS thread from ever flushing its microtask queue (handled by JSTimers/MessageQueue). When the queue starves, Reanimated worklets never run and animations freeze. This patch adds an explicit call to performMicrotaskCheckpoint(runtime) immediately after each task execution inside startWorkLoop. The helper invokes the global _flushReactNativeMicrotasks JS function (registered from JSTimers) so the queued microtasks are processed even while the native work-loop is busy. ✓ Restores Reanimated animations under Fabric bridgeless ticket: https://app.asana.com/1/236888843494340/project/1199705967702853/task/1210188774106277?focus=true
Flewp
approved these changes
Jul 22, 2025
Flewp
left a comment
There was a problem hiding this comment.
Nice! 🎉
Is this upstream-able? Should it be?
Any expected impact on CPU usage?
Author
|
@Flewp yes it's upstreamable, I didn't notice any impact on CPU usage, essentially it's flushing the microtask queue after every task completion, which is the same thing the modern RuntimeScheduler does as well. This PR is bringing that change to the Legacy runtime scheduler (the one we're using now). After we turn bridgeless mode on, we will be using the modern RuntimeScheduler and this change will be useless, but for the time being we need to flush the micro task queue manually because of |
pmick
approved these changes
Jul 23, 2025
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🐛 Fabric + Reanimated microtasks never flush (animations freeze)
TL;DR
React-Freeze’s
infiniteThenableleaves Fabric’sRuntimeScheduler_Legacystuck in an endless work-loop.JS microtasks never flush → Reanimated worklets never run → all animations stall.
This issue proposes calling
performMicrotaskCheckpoint(runtime)inside the loop so the JS queue is processed each iteration.Symptoms
global.queueMicrotasklogs enqueue eventsglobal.__callMicrotasksnever logs execution.console.log“fixes” the bugInvestigation summary
infiniteThenable.commitRootImpl→ schedules tasks viaScheduler.unstable_scheduleCallback.RuntimeScheduler_Legacy::startWorkLoopand spins forever:MessageQueue.__callReactNativeMicrotasks).Proposed fix (implemented in PR)
RuntimeScheduler_Legacy.cppexecuteTask(...)call we now runperformMicrotaskCheckpointcalls the global_flushReactNativeMicrotasksJS helper (already registered byJSTimers) which empties the queue viaJSTimers.callReactNativeMicrotasks().Why this is safe
Ticket
https://app.asana.com/1/236888843494340/project/1199705967702853/task/1210188774106277?focus=true
Credits
Big shout-out to Szymon for spotting the infinite loop and mapping the bridge call-chain! 🎉