runAllAsync and runToLastAsync do not run code in the microtask queue
fatso83 opened this issue · 5 comments
- FakeTimers version : 11.1.0
- Environment : Node
- Example URL : jestjs/jest#14549
What did you expect to happen?
I expected that fake timers
1) should advance past queued microtasks using runAllAsync
2) should advance past queued microtasks using runToLastAsync
What actually happens
They do not.
How to reproduce
git clone https://github.com/fatso83/lolex ;
cd lolex;
git checkout async-issues-run-all;
npm i; npx mocha test/issue-async.test.js
See https://github.com/fatso83/lolex/blob/async-issues-run-all/test/issue-async.test.js
Jest can do it because it transpiles (probably)
We can't do it because queueMicrotask isn't hookable from JS like nextTick, we can use an internal Node API but without connecting a debugger it'd be hard to write it in a stable way
We can't do it because queueMicrotask isn't hookable from JS like nextTick, we can use an internal Node API but without connecting a debugger it'd be hard to write it in a stable way
@benjamingr Could you elaborate on this a bit? I am not sure I understand at all. We do take control over queueMicrotask
, delegating to clock.nextTick()
, so after looking a bit at the code and throwing in some debugging I thought this was just about some bug in our implementation.
I see the clock.jobs
array is not cleared. Rather it is doubled up before exiting:
after [
{ func: [Function (anonymous)], args: [], error: null },
{ func: [Function: afterWriteTick], args: [ [Object] ], error: null }
]
I am not quite sure why that second job is there, but you say there is something about the async versions we cannot control?
I made a go and I think I found the bug, unless I am missing something substantial. This little diff should be sufficient to get the runAllAsync
test working (at least when I tried):
@@ -1578,6 +1578,8 @@ function withGlobal(_global) {
function doRun() {
originalSetTimeout(function () {
try {
+ runJobs(clock);
+
let numTimers;
if (i < clock.loopLimit) {
if (!clock.timers) {
I cannot claim that I understand all the minute details of fake-timers, but I did see that runJobs
, which runs the micro tasks, were missing from the runAllAsync
method.
I still see that the clock.jobs
array is non-empty (containing that { func: [Function: afterWriteTick] ..}
job after the test has completed), but functionally everything seems to be working. Could you explain what this is, @benjamingr ?
Closed by ^