loop.js
 1  import { raf } from './environment.js';
 2  
 3  const tasks = new Set();
 4  
 5  /**
 6   * @param {number} now
 7   * @returns {void}
 8   */
 9  function run_tasks(now) {
10  	tasks.forEach((task) => {
11  		if (!task.c(now)) {
12  			tasks.delete(task);
13  			task.f();
14  		}
15  	});
16  	if (tasks.size !== 0) raf(run_tasks);
17  }
18  
19  /**
20   * For testing purposes only!
21   * @returns {void}
22   */
23  export function clear_loops() {
24  	tasks.clear();
25  }
26  
27  /**
28   * Creates a new task that runs on each raf frame
29   * until it returns a falsy value or is aborted
30   * @param {import('./private.js').TaskCallback} callback
31   * @returns {import('./private.js').Task}
32   */
33  export function loop(callback) {
34  	/** @type {import('./private.js').TaskEntry} */
35  	let task;
36  	if (tasks.size === 0) raf(run_tasks);
37  	return {
38  		promise: new Promise((fulfill) => {
39  			tasks.add((task = { c: callback, f: fulfill }));
40  		}),
41  		abort() {
42  			tasks.delete(task);
43  		}
44  	};
45  }