// The event loop's JS side. The host owns the loop (see lib/rt/jsrt.h). A // macrotask is an IO op or a timer, which the host runs: it calls // `__complete(h)` when op `h` is done. A microtask is a promise job, in // `__microtasks`. After the program's top level, end.js runs all microtasks, // and after each macrotask, `__complete` does // What to do when IO op `h` completes: `__pending[h]`, a fn that gets `h`. // Handles are small ints, and a handle is used again after its op completes const __pending = []; // Promise jobs, in order. `head` is the next one, so that taking a job does // not move the others. A job is a closure, which keeps its own data: the // handler and the value that it is called with. So each handler gets only the // values of its own promise (see `docs/model.md`, section 3.3) const __microtasks = { jobs: [], head: 0 }; function __queue_job(job) { __microtasks.jobs.push(job); } function __drain_microtasks() { const q = __microtasks; while (q.head < q.jobs.length) { const job = q.jobs[q.head]; q.jobs[q.head] = undefined; q.head++; job(); } q.jobs.length = 0; q.head = 0; } // What the host calls when op `h` is done: its callback, then the microtasks function __complete(h) { const done = __pending[h]; __pending[h] = undefined; if (done !== undefined) done(h); __drain_microtasks(); } __link_host_complete(__complete);