svelte
Version:
Cybernetically enhanced web apps
43 lines (37 loc) • 1.42 kB
JavaScript
import { run_all } from '../../shared/utils.js';
import { is_flushing_sync } from '../reactivity/batch.js';
/** @type {Array<() => void>} */
let micro_tasks = [];
function run_micro_tasks() {
var tasks = micro_tasks;
micro_tasks = [];
run_all(tasks);
}
/**
* @param {() => void} fn
*/
export function queue_micro_task(fn) {
if (micro_tasks.length === 0 && !is_flushing_sync) {
var tasks = micro_tasks;
queueMicrotask(() => {
// If this is false, a flushSync happened in the meantime. Do _not_ run new scheduled microtasks in that case
// as the ordering of microtasks would be broken at that point - consider this case:
// - queue_micro_task schedules microtask A to flush task X
// - synchronously after, flushSync runs, processing task X
// - synchronously after, some other microtask B is scheduled, but not through queue_micro_task but for example a Promise.resolve() in user code
// - synchronously after, queue_micro_task schedules microtask C to flush task Y
// - one tick later, microtask A now resolves, flushing task Y before microtask B, which is incorrect
// This if check prevents that race condition (that realistically will only happen in tests)
if (tasks === micro_tasks) run_micro_tasks();
});
}
micro_tasks.push(fn);
}
/**
* Synchronously run any queued tasks.
*/
export function flush_tasks() {
while (micro_tasks.length > 0) {
run_micro_tasks();
}
}