Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: e9521780a83da546fd1cea021caf29306de8af8d
      
https://github.com/WebKit/WebKit/commit/e9521780a83da546fd1cea021caf29306de8af8d
  Author: Ahmad Saleem <[email protected]>
  Date:   2026-08-19 (Wed, 19 Aug 2026)

  Changed paths:
    A 
LayoutTests/imported/w3c/web-platform-tests/scroll-animations/css/timeline-offset-keyframes-zero-length-attachment-range-expected.txt
    A 
LayoutTests/imported/w3c/web-platform-tests/scroll-animations/css/timeline-offset-keyframes-zero-length-attachment-range.html
    M Source/WebCore/animation/BlendingKeyframes.cpp
    M Source/WebCore/animation/KeyframeEffect.cpp

  Log Message:
  -----------
  A zero-length animation attachment range produces infinite computed keyframe 
offsets
https://bugs.webkit.org/show_bug.cgi?id=322009
rdar://185204758

Reviewed by Antoine Quint.

computedOffset() maps a keyframe's timeline range offset into the progress 
space of the
animation's attachment range by dividing by that range's length. It skipped the 
division
only when the attachment range isDefault(), which tests start.isNormal() && 
end.isNormal()
and so does not catch a range that is non-default but degenerate. With a range 
such as
"contain 50% contain 50%" both edges resolve to the same timeline offset, the 
length is
zero, and the division yielded +/-Infinity (or NaN when the numerator happened 
to be zero
as well).

The guard in updateComputedKeyframeOffsetsIfNeeded() does not help here: it 
bails out when
the timeline's currentTime is unresolved, but in this case the timeline range 
is perfectly
ordinary and only the attachment range is degenerate.

A zero-length attachment range gives the animation no interval to progress 
over, so there
is no offset to map onto. Return quiet_NaN() instead, which is how this code 
already
represents an unresolved computed offset -- see the 
named-range-without-a-timeline case
above it, and hasKeyframeWithUnresolvedComputedOffset(), which disables 
acceleration.
Computed offsets legitimately fall outside [0,1], so clamping would be wrong.

This matches Chrome, which already reports an unresolved computed offset here. 
Firefox
reports +/-Infinity, as WebKit did before this change.

While here, make BlendingKeyframes::updatedComputedOffsets() sort with an 
explicit
comparator. It sorted on BlendingKeyframe::offset() using std::less, which is 
not a strict
weak ordering over NaN: every NaN compares equivalent to every other offset, 
while those
offsets are not equivalent to each other. That is undefined behavior and trips 
hardened
libc++ comparator checks. It is reachable independently of the above, via 
range-offset
keyframes on an element with no scroll timeline at all. Order unresolved 
offsets last.

Test: 
imported/w3c/web-platform-tests/scroll-animations/css/timeline-offset-keyframes-zero-length-attachment-range.html

* 
LayoutTests/imported/w3c/web-platform-tests/scroll-animations/css/timeline-offset-keyframes-zero-length-attachment-range-expected.txt:
 Added.
* 
LayoutTests/imported/w3c/web-platform-tests/scroll-animations/css/timeline-offset-keyframes-zero-length-attachment-range.html:
 Added.
* Source/WebCore/animation/BlendingKeyframes.cpp:
(WebCore::BlendingKeyframes::updatedComputedOffsets):
* Source/WebCore/animation/KeyframeEffect.cpp:
(WebCore::computedOffset):

Canonical link: https://commits.webkit.org/319443@main



To unsubscribe from these emails, change your notification settings at 
https://github.com/WebKit/WebKit/settings/notifications

Reply via email to