ReactiveX / ReactiveX/rxjs

animationFrameScheduler with delay causes incorrect behavior (and exception)

Open
#6,891 0 comments 1 reaction 0 assignees View on GitHub

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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.