diff --git a/src/runtime/internal/loop.ts b/src/runtime/internal/loop.ts index c1a42aa724..33e519732f 100644 --- a/src/runtime/internal/loop.ts +++ b/src/runtime/internal/loop.ts @@ -1,39 +1,42 @@ -import { now, raf } from './environment'; +import { raf } from './environment'; export interface Task { abort(): void; promise: Promise } -const tasks = new Set(); -let running = false; +type TaskCallback = (now: number) => boolean | void; +type TaskEntry = { c: TaskCallback; f: () => void }; -function run_tasks() { +const tasks = new Set(); + +function run_tasks(now: number) { tasks.forEach(task => { - if (!task[0](now())) { + if (!task.c(now)) { tasks.delete(task); - task[1](); + task.f(); } }); - running = tasks.size > 0; - if (running) raf(run_tasks); + if (tasks.size !== 0) raf(run_tasks); } +/** + * For testing purposes only! + */ export function clear_loops() { - // for testing... - tasks.forEach(task => tasks.delete(task)); - running = false; + tasks.clear(); } -export function loop(fn: (number) => void): Task { - let task; +/** + * Creates a new task that runs on each raf frame + * until it returns a falsy value or is aborted + */ +export function loop(callback: TaskCallback): Task { + let task: TaskEntry; - if (!running) { - running = true; - raf(run_tasks); - } + if (tasks.size === 0) raf(run_tasks); return { - promise: new Promise(fulfil => { - tasks.add(task = [fn, fulfil]); + promise: new Promise(fulfill => { + tasks.add(task = { c: callback, f: fulfill }); }), abort() { tasks.delete(task); diff --git a/test/runtime/index.js b/test/runtime/index.js index fc989d352f..60bd70a5d9 100644 --- a/test/runtime/index.js +++ b/test/runtime/index.js @@ -107,7 +107,7 @@ describe("runtime", () => { set_raf(cb => { raf.callback = () => { raf.callback = null; - cb(); + cb(raf.time); flush(); }; });