This repository has been archived by the owner on Oct 18, 2024. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fully update internal state before invoking periodic-timer callback
Fixes #88. Currently when a periodic timer's callback gets invoked, its `_nextCall` is still the time of the current call, not the next one. If the timer callback itself calls `flushTimers` or `elapse`, this causes the same timer to immediately get called again. Fortunately the fix is easy: update `_nextCall` just before invoking `_callback`, instead of just after. --- To work through why this is a complete fix (and doesn't leave further bugs of this kind still to be fixed): After this fix, the call to the timer's callback is a tail call from `FakeTimer._fire`. Because the call site of `FakeTimer._fire` is immediately followed by `flushMicrotasks()`, this means calling other `FakeAsync` methods from the timer callback is no different from doing so in a subsequent microtask. Moreover, when running timers from `flushTimers`, if after the `flushMicrotasks` call this turns out to be the last timer to run, then `flushTimers` will return with no further updates to the state. So when the timer callback is invoked (in that case), the whole `FakeAsync` state must already be in a state that `flushTimers` would have been happy to leave it in. (And there's no special cleanup that it does only after a non-last timer.) Similarly, when running timers from `elapse` (the only other possibility), the only difference from a state that `elapse` would be happy to leave things in is that `_elapsingTo` is still set. That field affects only `elapse` and `elapseBlocking`; and those are both designed to handle being called from within `elapse`.
- Loading branch information