Skip to content
This repository was archived by the owner on Jul 14, 2026. It is now read-only.

Skip spring integration on non-finite or non-positive frame durations - #2

Open
thebrowsercompany-bot2 wants to merge 35 commits into
mainfrom
diamond/spring-animation-dt-guard
Open

Skip spring integration on non-finite or non-positive frame durations#2
thebrowsercompany-bot2 wants to merge 35 commits into
mainfrom
diamond/spring-animation-dt-guard

Conversation

@thebrowsercompany-bot2

Copy link
Copy Markdown

Root Cause

On macOS, CoreVideoDriver feeds frame.duration (targetTimestamp - timestamp, derived from CVTimeStamp.videoTime / videoTimeScale) straight into SpringAnimation.tick. When the display link is torn down and restarted (e.g. after the screen sleeps and wakes), the first frame after wake can carry a non-finite or non-positive duration (a stale/zero videoTimeScale yields inf/NaN). Feeding that into the analytic spring solver produces non-finite state, which then traps when the value is read back.

Fix

Guard SpringAnimation.tick against non-finite and non-positive frame durations by skipping the frame. Finite durations — including large but valid ones — are unchanged, so normal playback is unaffected.

Tests

Added testSpringToleratesDegenerateFrameDuration, which ticks with zero, negative, inf, and NaN durations and asserts the value/velocity stay finite. It fails on the pre-fix code and passes with the guard. Full MotionTests suite passes (34 tests).

This branch is b3ll/Motion@c9a57f9 (the commit currently pinned by the arc repo) plus this single fix.

b3ll and others added 30 commits January 31, 2023 19:29
I was erroneously assuming that ignoring velocity was sufficient to stop upon reaching the `toValue`, however with enough velocity, the check for whether `toValue` has been reached or not is incorrect.

Now, it checks to see if the delta between the current value and the value after executing the spring to see if there’s a sign change (i.e. crossing zero), meaning the `toValue` has been reached and the spring should resolve.
This adds the ability to get the destination for a `DecayAnimation`. It also allows the ability to set the destination for a `DecayAnimation` (similar to how one can with `UIScrollView`). Setting the `toValue` on a `DecayAnimation` will result in the `velocity` being adjusted so that the `DecayAnimation` will stop at the supplied `toValue`.

This also adds the ability to adjust how the decay will end with regards to rounded values. Setting a value of 1.0 will result in the `DecayAnimation` always stopping on whole point values (whereas setting something like `1 / screenScale` will allow it to stop on pixel values).

Implements b3ll#28
Support toValue on DecayAnimation; Add roundingFactor
…bserve

Pause animation driver if necessary when unobserving animations
Introduce AnimationEnvironment to address b3ll#18
Fixed a crash on tvOS if the device’s refresh rate was set below 60fps.
b3ll and others added 5 commits April 9, 2024 23:00
A display link that restarts after screen sleep/wake can deliver a
non-finite or non-positive frame duration. Feeding that into the spring
solver produces non-finite state, which traps when the value is read
back on the next tick. Guard against it by skipping degenerate frames.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants