sableland / sable

JavaScript runtime Deno was meant to be.
MIT License
34 stars 5 forks source link

Timers are not always fired when registered in a microtask #53

Closed andreubotella closed 7 months ago

andreubotella commented 7 months ago
setTimeout(() => {
  queueMicrotask(() => {
    setTimeout(() => {
      console.log("should be called but isn't");
    }, 0);
  });
}, 0);

If there are no registered timers after a timer callback is finished running, but microtasks are enqueued that will register timers, those timers will not run. Or at least not until the next time a timer is registered.

This is caused by the fact that op_timers_sleep is called immediately after the timer callback runs, and it sees there are no timers in the queue, so it returns null immediately. However, since it's an async op, the code after the await will run after the currently scheduled microtasks, which can register new timers. And this isn't being taken into account.