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