Skip to content

Commit

Permalink
Add flashImmediateRunning flag to setupSetImmediate (software-mansion…
Browse files Browse the repository at this point in the history
…#4280)

<!-- Thanks for submitting a pull request! We appreciate you spending
the time to work on these changes. Please follow the template so that
the reviewers can easily understand what the code changes affect. -->

## Summary

- fixes software-mansion#4168 

The problem is caused by recursive `callMicrotasks` calls. 
Recursive calls appear when we have an event that trigger another event
that calls `callMicrotasks` synchronously.
In result, we call the same microtasks array multiple times. 
In some cases we get the wrong order of instructions and we end up with
`runRequested` set on `true` without callbacks in the queue, so we never
call `queueMicrotask` again.

The idea of fix is to set flag that inform us, that we are inside
`callMicrotasks` call, so we don't execute the same callbacks again

## Test plan

- Created minimal repro using to `Animated.ScrollView` components. (one
trigger another)
- Tested on example from issue
  • Loading branch information
mstach60161 authored and fluiddot committed Jun 5, 2023
1 parent 5e04258 commit de1ed98
Showing 1 changed file with 13 additions and 4 deletions.
17 changes: 13 additions & 4 deletions src/reanimated2/threads.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export function setupMicrotasks() {
'worklet';

let microtasksQueue: Array<() => void> = [];
let isExecutingMicrotasksQueue = false;

// @ts-ignore – typescript expects this to conform to NodeJS definition and expects the return value to be NodeJS.Immediate which is an object and not a number
global.queueMicrotask = (callback: () => void): number => {
Expand All @@ -23,11 +24,19 @@ export function setupMicrotasks() {
};

global.__callMicrotasks = () => {
for (let index = 0; index < microtasksQueue.length; index += 1) {
// we use classic 'for' loop because the size of the currentTasks array may change while executing some of the callbacks due to queueMicrotask calls
microtasksQueue[index]();
if (isExecutingMicrotasksQueue) {
return;
}
try {
isExecutingMicrotasksQueue = true;
for (let index = 0; index < microtasksQueue.length; index += 1) {
// we use classic 'for' loop because the size of the currentTasks array may change while executing some of the callbacks due to queueMicrotask calls
microtasksQueue[index]();
}
microtasksQueue = [];
} finally {
isExecutingMicrotasksQueue = false;
}
microtasksQueue = [];
};
}

Expand Down

0 comments on commit de1ed98

Please sign in to comment.