animationFrameScheduler with delay causes incorrect behavior (and exception)
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 31.7k
- Forks
- 3k
- PR merge metrics
- No merged PRs in 30d
Description
Describe the bug
If AnimationFrameScheduler#schedule is used with a delay > 0, the action is scheduled as AsyncAction. Executing the action takes the same code path as AnimationFrameAction.
So if the AsyncAction executes while AnimationFrameActions are scheduled, it executes those too, which is too early as the browser is not yet preparing the next frame.
With the fix in #6889 it will throw an error, when rAF tries to execute the actual AnimationFrameActions, but the queue is already empty:
Uncaught TypeError: Cannot read properties of undefined (reading 'execute')
at AnimationFrameScheduler.flush (src\internal\scheduler\AnimationFrameScheduler.ts:24:27)
at C:\code\rxjs\src\internal\scheduler\AnimationFrameAction.ts:21:121
Expected behavior
AsyncAction to be handled separately. Ideally we could use asyncScheduler.schedule(...) instead of super.request/recycleAsyncId.
Reproduction code
animationFrameScheduler.schedule(() => console.log('async'), 1);
animationFrameScheduler.schedule(() => console.log('animation frame'));
Reproduction URL
No response
Version
7.5.5
Environment
No response
Additional context
I could try to fix this, but I'm not sure how to test this properly. The code above flaky, because the timeout of 1ms is not guaranteed to be executed before the next animation frame. I guess I could mock the relevant animationFrameProvider
asapScheduler uses similar code, but seems not to be affected, because timeouts will never be executed before microtasks.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with src/internal/scheduler/AnimationFrameScheduler.ts and src/internal/scheduler/AnimationFrameAction.ts, then inspect the animationFrameProvider used by the scheduler. Reproduce the delayed and immediate scheduling sequence with a controlled frame provider, and add a regression test showing that the delayed action does not execute queued animation-frame actions early or trigger an exception.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- frontend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100