Microtask update introduced event dropping
See original GitHub issueCopied from the excellent writeup @ef4 did in https://github.com/emberjs/ember.js/issues/16296:
Hello fans of timing bugs, today I have a fun one for you.
The new microtask-based autorun architecture can drop scheduled events. To see it in action, you can run the following against 3.1 beta:
import Controller from '@ember/controller';
import { schedule } from '@ember/runloop';
export default Controller.extend({
actions: {
testIt() {
// Here I am deliberately escaping the run loop to use autoruns instead.
Promise.resolve().then(() => {
// This schedules an autorun
schedule('render', () => {
console.log(1);
// Here we schedule a microtask. It will be ahead of the runloop's own next flush.
Promise.resolve().then(() => {
console.log(2);
return Promise.resolve().then(() => {
// This runs fine
console.log(3);
// But this scheduled event never fires.
schedule('actions', () => console.log('THIS NEVER RUNS!!!!') )
});
})
// when we return out of here, the runloop goes back to the
// first queue to start flushing again. But our promise stack is
// interleaving with the runloop's one-microtask-per-queue.
});
});
}
}
});
If you fire the testIt
event, the console logs
1
2
3
The number of layers of promises required to experience the bug depends on which queue you’re trying to schedule. The runloop spends one microtask per queue, so our stack of promise resolutions is interleaved with each queue’s flush. In the above example, we schedule on the actions
queue immediately after that queue has just flushed, and the runloop never notices.
You can make it drop events on any other queue just by varying the number of promises you resolve in between the time you first trigger an autorun and the time you schedule your doomed event.
I published a working example of the bug here: https://github.com/ef4/bug-repro/tree/bad-timing
Issue Analytics
- State:
- Created 6 years ago
- Comments:5
This was fixed by https://github.com/BackburnerJS/backburner.js/pull/336, and the version of backburner using microtasks is included by Ember since 3.2.0-beta.1.
@rwjblue excellent, thanks for confirming. I’ll open an issue against Ember then, although I’m at a bit of a loss as to how best to get a useful reproduction other than the tests used to work and now they don’t 🌵