- From: Antoine Quint via GitHub <sysbot+gh@w3.org>
- Date: Fri, 21 Feb 2025 12:26:06 +0000
- To: public-css-archive@w3.org
graouts has just created a new issue for https://github.com/w3c/csswg-drafts: == [web-animations-2] moving from a progress-based timeline to a monotonic timeline can yield incompatible timeline time and animation current time == I'm working on a failure in the WPT subtest "Playback rate affects whether active phase boundary is inclusive" in `scroll-animations/scroll-timelines/scroll-animation-effect-phases.tentative.html` and encountered what appears to be a spec issue. I've simplified the test in this particular reduction: ```html <style> .scroller { overflow: scroll; height: 200px; width: 200px; } .contents { height: 1200px; width: 100%; background-color: green; } </style> <div class="scroller"> <div class="contents"></div> </div> <script> (async function () { // create an animation associated with a progress-based timeline const timeline = new ScrollTimeline({ source: document.querySelector(".scroller") }); const animation = document.querySelector(".contents").animate({ opacity: [0.1, 1] }, { timeline }); await Promise.all([animation.ready, new Promise(requestAnimationFrame)]); // set the animation to the "after" phase const scroller = animation.timeline.source; const maxScroll = scroller.scrollHeight - scroller.clientHeight; scroller.scrollTop = 1.5 * maxScroll; // wait a frame and set the timeline to a monotonic timeline await new Promise(requestAnimationFrame); animation.timeline = document.timeline; })(); </script> ``` In WebKit – at the time of writing ([290776@main](https://commits.webkit.org/290776@main)) – this particular test yields a debug assertion because we end up attempting an operation with a time value that is expressed in seconds and one expressed as a percentage. Here's how we get there, and I believe in accordance with the current specifications: ### Step 1 Under the call to `Element.animate()`, the procedure to [set the timeline of an animation](https://drafts.csswg.org/web-animations-2/#setting-the-timeline) takes us inside the "if to finite timeline" branch and we set both the _start time_ and the _hold time_ to be _unresolved_. ### Step 2 As the _update animations and send events_ procedure is triggered and the animation becomes _ready_, we [calculate an auto-aligned start time](https://drafts.csswg.org/web-animations-2/#animation-calculating-an-auto-aligned-start-time) and set the _start time_ to `0%` as the _hold time_ remains _unresolved_. ### Step 3 After the animation timeline's source changes scroll position, and during the next occurence of the _update animations and send events_ procedure, we [update the animation's finished state](https://drafts.csswg.org/web-animations-1/#update-an-animations-finished-state) and match this condition: > If all three of the following conditions are true, > > - the unconstrained current time is resolved, and > - animation’s start time is resolved, and > - animation does not have a pending play task or a pending pause task, > > then update animation’s hold time based on the first matching condition for animation from below, if any: … and then match this condition: > If playback rate > 0 and unconstrained current time is greater than or equal to associated effect end … and finally this sub-condition: > If did seek is false, let the hold time be the maximum value of previous current time and associated effect end. As a result, the _hold time_ is set to `100%` and the _start time_ remains set to `0%`. ### Step 4 As we [set the timeline](https://drafts.csswg.org/web-animations-2/#animation-set-the-timeline-of-an-animation) to the document timeline, and as such move from a progress-based timeline to a monotonic timeline, we enter this condition: > If from finite timeline and previous progress is resolved, > Run the procedure to set the current time to previous progress * end time. As such we immediately run the procedure to [silently set the current time](https://drafts.csswg.org/web-animations-2/#silently-set-the-current-time) and enter this condition: > If any of the following conditions are true: > > - animation’s hold time is resolved, or > - animation’s start time is unresolved, or > - animation has no associated timeline or the associated timeline is inactive, or > - animation’s playback rate is 0, > > Set animation’s hold time to seek time. As a result, the _hold time_ becomes `0s` and the _start time_ remains `0%`. Note that these two times are now using different time units. As the [setting the timeline](https://drafts.csswg.org/web-animations-2/#animation-set-the-timeline-of-an-animation) procedure continues, we additionally run this step: > If the start time of animation is resolved, make animation’s hold time unresolved. As a result, the _hold time_ becomes unresolved and the _start time_ remains `0%`. To finish [setting the timeline](https://drafts.csswg.org/web-animations-2/#animation-set-the-timeline-of-an-animation) we [update the animation's finished state](https://drafts.csswg.org/web-animations-1/#update-an-animations-finished-state) and attempt to compute the unconstrained current time at which point we attempt to compute: ``` current time = (timeline time - start time) * playback rate ``` The _timeline time_ is a resolved time expressed in seconds since the timeline is monotonic while the start time has remained `0%`. This is when WebKit hits a debug assertion. The WPT in question test immediately sets the current time to `0` but I don't think we should be in the situation described above as we set the timeline. Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/11761 using your GitHub account -- Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config
Received on Friday, 21 February 2025 12:26:07 UTC