From 6e282b741b657e4deab13de4b90a71cbdb6d21de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Mon, 16 Dec 2024 03:17:08 -0800 Subject: [PATCH] Add scheduleTask and runWorkLoop to public API (#48284) Summary: Changelog: [internal] We recently prevented tasks that run via `runTask` to synchronously call `runTask` because the execution is synchronous and we can't nest tasks in the event loop (D67107664 / https://github.com/facebook/react-native/pull/48235). This adds `scheduleTask` to schedule tasks (also within tasks) with the right expectations (the task will not run synchronously on that call but at the right time). It also adds `runWorkLoop` so we can run scheduled tasks if they're not scheduled from an already running task. Differential Revision: D67275518 --- packages/react-native-fantom/src/index.js | 30 +++++++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/packages/react-native-fantom/src/index.js b/packages/react-native-fantom/src/index.js index 0c3b79f7dbcd3b..179e0d7755fcb5 100644 --- a/packages/react-native-fantom/src/index.js +++ b/packages/react-native-fantom/src/index.js @@ -60,6 +60,17 @@ class Root { // TODO: add an API to check if all surfaces were deallocated when tests are finished. } +const DEFAULT_TASK_PRIORITY = schedulerPriorityImmediate; + +/** + * Schedules a task to run on the event loop. + * If the work loop is running, it will be executed according to its priority. + * Otherwise, it will wait in the queue until the work loop runs. + */ +export function scheduleTask(task: () => void | Promise) { + nativeRuntimeScheduler.unstable_scheduleCallback(DEFAULT_TASK_PRIORITY, task); +} + let flushingQueue = false; /* @@ -70,14 +81,23 @@ let flushingQueue = false; export function runTask(task: () => void | Promise) { if (flushingQueue) { throw new Error( - 'Nested runTask calls are not allowed. If you want to schedule a task from inside another task, use scheduleTask instead.', + 'Nested `runTask` calls are not allowed. If you want to schedule a task from inside another task, use `scheduleTask` instead.', ); } - nativeRuntimeScheduler.unstable_scheduleCallback( - schedulerPriorityImmediate, - task, - ); + scheduleTask(task); + runWorkLoop(); +} + +/** + * Runs the event loop until all tasks are executed. + */ +export function runWorkLoop(): void { + if (flushingQueue) { + throw new Error( + 'Cannot start the work loop because it is already running. If you want to schedule a task from inside another task, use `scheduleTask` instead.', + ); + } try { flushingQueue = true;