From 6cf1d53539355b161644543d3f384c8811bc760a Mon Sep 17 00:00:00 2001 From: Johannes Odland Date: Sun, 12 Nov 2023 22:45:35 +0100 Subject: [PATCH] Handle CSSUnitValue inset and update range measurements on source and subject resize --- src/proxy-cssom.js | 120 +++++++++++++++++++++++++++++ src/scroll-timeline-base.js | 145 ++++++++++++++++++++++++------------ src/simplify-calculation.js | 6 +- test/expected.txt | 82 ++++++++++---------- 4 files changed, 264 insertions(+), 89 deletions(-) diff --git a/src/proxy-cssom.js b/src/proxy-cssom.js index 656d4553..04c39d49 100644 --- a/src/proxy-cssom.js +++ b/src/proxy-cssom.js @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. import { createAType, invertType, multiplyTypes, to, toSum } from "./numeric-values"; +import { simplifyCalculation } from "./simplify-calculation"; export function installCSSOM() { // Object for storing details associated with an object which are to be kept @@ -68,7 +69,126 @@ export function installCSSOM() { } } + /** + * Parse a CSSUnitValue from the passed string + * @param {string} str + * @return {CSSUnitValue} + */ + function parseCSSUnitValue(str) { + const UNIT_VALUE_REGEXP = /^(-?\d*[.]?\d+)(r?em|r?ex|r?cap|r?ch|r?ic|r?lh|[sld]?v(w|h|i|b|min|max)|cm|mm|Q|in|pt|pc|px|%)?$/; + const match = str.match(UNIT_VALUE_REGEXP); + if (match) { + let [_, v, unit] = match; + if (typeof unit === 'undefined') { + unit = 'number'; + } else if (unit === '%') { + unit = 'percent'; + } + return new CSSUnitValue(parseFloat(v), unit); + } else { + throw new SyntaxError(`Unsupported syntax ${str}`); + } + } + + /** + * Parse the string as a CSSMathProduct + * @param {string} str + * @return {CSSMathProduct} + */ + function parseCSSMultiplication(str) { + let values = []; + const tokens = str.split(/(? { // Sample and store scroll pos @@ -304,6 +310,7 @@ function updateSource(timeline, source) { scrollEventSource(source).addEventListener("scroll", scrollListener); details.disconnect = () => { resizeObserver.disconnect(); + mutationObserver.disconnect(); scrollEventSource(source).removeEventListener("scroll", scrollListener); }; } @@ -368,7 +375,7 @@ export class ScrollTimeline { // View timeline subject: null, - inset: (options ? options.inset : null), + inset: null, // Internal members animations: [], @@ -599,23 +606,29 @@ export function calculateRange(phase, sourceMeasurements, subjectMeasurements, a const rtl = sourceMeasurements.direction == 'rtl' || sourceMeasurements.writingMode == 'vertical-rl'; let viewSize = undefined; let viewPos = undefined; - let containerSize = undefined; + let sizes = { + fontSize: subjectMeasurements.fontSize + }; if (axis == 'x' || (axis == 'inline' && horizontalWritingMode) || (axis == 'block' && !horizontalWritingMode)) { viewSize = subjectMeasurements.offsetWidth; viewPos = subjectMeasurements.left; - if (rtl) + sizes.scrollPadding = [sourceMeasurements.scrollPaddingLeft, sourceMeasurements.scrollPaddingRight]; + if (rtl) { viewPos += sourceMeasurements.scrollWidth - sourceMeasurements.clientWidth; - containerSize = sourceMeasurements.clientWidth; + sizes.scrollPadding = [sourceMeasurements.scrollPaddingRight, sourceMeasurements.scrollPaddingLeft]; + } + sizes.containerSize = sourceMeasurements.clientWidth; } else { // TODO: support sideways-lr viewSize = subjectMeasurements.offsetHeight; viewPos = subjectMeasurements.top; - containerSize = sourceMeasurements.clientHeight; + sizes.scrollPadding = [sourceMeasurements.scrollPaddingTop, sourceMeasurements.scrollPaddingBottom]; + sizes.containerSize = sourceMeasurements.clientHeight; } - const inset = parseInset(optionsInset, containerSize); + const inset = calculateInset(optionsInset, sizes); // Cover: // 0% progress represents the position at which the start border edge of the @@ -624,7 +637,7 @@ export function calculateRange(phase, sourceMeasurements, subjectMeasurements, a // 100% progress represents the position at which the end border edge of the // element’s principal box coincides with the start edge of its view progress // visibility range. - const coverStartOffset = viewPos - containerSize + inset.end; + const coverStartOffset = viewPos - sizes.containerSize + inset.end; const coverEndOffset = viewPos + viewSize - inset.start; // Contain: @@ -647,7 +660,7 @@ export function calculateRange(phase, sourceMeasurements, subjectMeasurements, a let startOffset = undefined; let endOffset = undefined; - const targetIsTallerThanContainer = viewSize > containerSize ? true : false; + const targetIsTallerThanContainer = viewSize > sizes.containerSize ? true : false; switch(phase) { case 'cover': @@ -683,47 +696,74 @@ export function calculateRange(phase, sourceMeasurements, subjectMeasurements, a return { start: startOffset, end: endOffset }; } -function validateInset(value) { - // Validating insets when constructing ViewTimeline by running the parse function. - // TODO: parse insets to CSSNumericValue when constructing ViewTimeline - parseInset(value, 0) +function parseInset(value) { + const inset = { start: 0, end: 0 }; + + if (!value) return inset; + + let parts = value; + // Parse string parts to + if (typeof value === 'string') { + // Split value into separate parts + const stringParts = value.split(/(? { + if (str.trim() === 'auto') { + return 'auto'; + } else { + try { + return CSSNumericValue.parse(str); + } catch (e) { + throw TypeError('Invalid inset'); + } + } + }); + } + if (parts.length === 0 || parts.length > 2) { + throw TypeError('Invalid inset'); + } + + // Validate that the parts are 'auto' or + for (const part of parts) { + if (part === 'auto') { + continue; + } + const type = part.type(); + if (!(type.length === 1 || type.percent === 1)) { + throw TypeError('Invalid inset'); + } + } + + return { + start: parts[0], + end: parts[1] ?? parts[0] + }; } -function parseInset(value, containerSize) { +function calculateInset(value, sizes) { const inset = { start: 0, end: 0 }; - if(!value) - return inset; - - const parts = value.split(' '); - const insetParts = []; - parts.forEach(part => { - // TODO: Add support for relative lengths (e.g. em) - if(part.endsWith("%")) - insetParts.push(containerSize / 100 * parseFloat(part)); - else if(part.endsWith("px")) - insetParts.push(parseFloat(part)); - else if(part === "auto") - insetParts.push(0); - else - throw TypeError("Unsupported inset. Only % and px values are supported (for now)."); - }); + if (!value) return inset; - if (insetParts.length > 2) { - throw TypeError("Invalid inset"); - } + const [start, end] = [value.start, value.end].map((part, i) => { + if (part === 'auto') { + return sizes.scrollPadding[i] === 'auto' ? 0 : parseFloat(sizes.scrollPadding[i]); + } - if(insetParts.length == 1) { - inset.start = insetParts[0]; - inset.end = insetParts[0]; - } else if(insetParts.length == 2) { - inset.start = insetParts[0]; - inset.end = insetParts[1]; - } + const simplifiedUnit = simplifyCalculation(part, { + percentageReference: CSS.px(sizes.containerSize), + fontSize: CSS.px(parseFloat(sizes.fontSize)) + }); + if (simplifiedUnit instanceof CSSUnitValue && simplifiedUnit.unit === 'px') { + return simplifiedUnit.value; + } else { + throw TypeError('Unsupported inset.'); + } + }); - return inset; + return { start, end }; } + // Calculate the fractional offset of a (phase, percent) pair relative to the // full cover range. export function relativePosition(timeline, phase, offset) { @@ -763,11 +803,16 @@ export class ViewTimeline extends ScrollTimeline { details.subject = options && options.subject ? options.subject : undefined; // TODO: Handle insets. if (options && options.inset) { - validateInset(options.inset) + details.inset = parseInset(options.inset); + } + if (details.subject) { + const mutationObserver = new MutationObserver(() => { + updateMeasurements(details.source); + }); + mutationObserver.observe(details.subject, {attributes: true, attributeFilter: ['class', 'style']}); } - validateSource(this); - details.subjectMeasurements = measureSubject(details.source, details.subject) + details.subjectMeasurements = measureSubject(details.source, details.subject); updateInternal(this); } @@ -805,4 +850,12 @@ export class ViewTimeline extends ScrollTimeline { return CSS.percent(100 * progress); } + get startOffset() { + return CSS.px(range(this,'cover').start); + } + + get endOffset() { + return CSS.px(range(this,'cover').end); + } + } diff --git a/src/simplify-calculation.js b/src/simplify-calculation.js index da76e7fb..e6144fe3 100644 --- a/src/simplify-calculation.js +++ b/src/simplify-calculation.js @@ -1,7 +1,7 @@ import {isCanonical} from "./utils"; /** - * @typedef {{percentageReference: CSSUnitValue}} Info + * @typedef {{percentageReference: CSSUnitValue, fontSize?: CSSUnitValue}} Info */ /** @@ -81,7 +81,9 @@ export function simplifyCalculation(root, info) { root = sum.values[0]; } // TODO: handle relative lengths - + if (root instanceof CSSUnitValue && root.unit === 'em' && info.fontSize) { + root = new CSSUnitValue(root.value * info.fontSize.value, info.fontSize.unit); + } // 3. If root is a , return its numeric value. // 4. Otherwise, return root. return root; diff --git a/test/expected.txt b/test/expected.txt index 1aaa8fb5..3302b607 100644 --- a/test/expected.txt +++ b/test/expected.txt @@ -643,9 +643,9 @@ PASS /scroll-animations/scroll-timelines/effect-updateTiming.html Updates the sp FAIL /scroll-animations/scroll-timelines/effect-updateTiming.html Allows setting the easing of an animation in progress PASS /scroll-animations/scroll-timelines/finish-animation.html Finishing an animation with a zero playback rate throws PASS /scroll-animations/scroll-timelines/finish-animation.html Finishing an animation seeks to the end time -FAIL /scroll-animations/scroll-timelines/finish-animation.html Finishing an animation with a current time past the effect end jumps back to the end +PASS /scroll-animations/scroll-timelines/finish-animation.html Finishing an animation with a current time past the effect end jumps back to the end PASS /scroll-animations/scroll-timelines/finish-animation.html Finishing a reversed animation jumps to zero time -FAIL /scroll-animations/scroll-timelines/finish-animation.html Finishing a reversed animation with a current time less than zero makes it jump back to zero +PASS /scroll-animations/scroll-timelines/finish-animation.html Finishing a reversed animation with a current time less than zero makes it jump back to zero PASS /scroll-animations/scroll-timelines/finish-animation.html Finishing an animation while play-pending resolves the pending task immediately PASS /scroll-animations/scroll-timelines/finish-animation.html Finishing an animation attached to inactive timeline while play-pending doesn't resolves the pending task PASS /scroll-animations/scroll-timelines/finish-animation.html Finishing an animation resolves the finished promise synchronously @@ -699,18 +699,18 @@ FAIL /scroll-animations/scroll-timelines/intrinsic-iteration-duration.tentative. PASS /scroll-animations/scroll-timelines/intrinsic-iteration-duration.tentative.html Intrinsic iteration duration accounts for number of iterations PASS /scroll-animations/scroll-timelines/pause-animation.html Pausing clears the start time PASS /scroll-animations/scroll-timelines/pause-animation.html A pending ready promise should be resolved and not replaced when the animation is paused -FAIL /scroll-animations/scroll-timelines/pause-animation.html A pause-pending animation maintains the current time when applying a pending playback rate +PASS /scroll-animations/scroll-timelines/pause-animation.html A pause-pending animation maintains the current time when applying a pending playback rate PASS /scroll-animations/scroll-timelines/pause-animation.html The animation's current time remains fixed after pausing PASS /scroll-animations/scroll-timelines/pause-animation.html Pausing a canceled animation sets the current time PASS /scroll-animations/scroll-timelines/pause-animation.html Pause pending task doesn't run when the timeline is inactive. PASS /scroll-animations/scroll-timelines/pause-animation.html Animation start and current times are correct if scroll timeline is activated after animation.pause call. FAIL /scroll-animations/scroll-timelines/play-animation.html Playing an animations aligns the start time with the start of the active range PASS /scroll-animations/scroll-timelines/play-animation.html Playing an animations with a negative playback rate aligns the start time with the end of the active range -FAIL /scroll-animations/scroll-timelines/play-animation.html Start time set while play pending is preserved. -FAIL /scroll-animations/scroll-timelines/play-animation.html Current time set while play pending is preserved. +PASS /scroll-animations/scroll-timelines/play-animation.html Start time set while play pending is preserved. +PASS /scroll-animations/scroll-timelines/play-animation.html Current time set while play pending is preserved. FAIL /scroll-animations/scroll-timelines/play-animation.html Playing a running animation resets a sticky start time PASS /scroll-animations/scroll-timelines/play-animation.html Playing a finished animation restarts the animation aligned at the start -FAIL /scroll-animations/scroll-timelines/play-animation.html Playing a finished and reversed animation restarts the animation aligned at the end +PASS /scroll-animations/scroll-timelines/play-animation.html Playing a finished and reversed animation restarts the animation aligned at the end PASS /scroll-animations/scroll-timelines/play-animation.html Playing a pause-pending but previously finished animation realigns with the scroll position PASS /scroll-animations/scroll-timelines/play-animation.html Playing a finished animation clears the start time PASS /scroll-animations/scroll-timelines/play-animation.html The ready promise should be replaced if the animation is not already pending @@ -720,8 +720,8 @@ PASS /scroll-animations/scroll-timelines/play-animation.html If a pause operatio FAIL /scroll-animations/scroll-timelines/play-animation.html A pending playback rate is used when determining timeline range alignment PASS /scroll-animations/scroll-timelines/play-animation.html Playing a canceled animation sets the start time PASS /scroll-animations/scroll-timelines/play-animation.html Playing a canceled animation backwards sets the start time -FAIL /scroll-animations/scroll-timelines/reverse-animation.html Setting current time while reverse-pending preserves currentTime -FAIL /scroll-animations/scroll-timelines/reverse-animation.html Reversing an animation inverts the playback rate +PASS /scroll-animations/scroll-timelines/reverse-animation.html Setting current time while reverse-pending preserves currentTime +PASS /scroll-animations/scroll-timelines/reverse-animation.html Reversing an animation inverts the playback rate FAIL /scroll-animations/scroll-timelines/reverse-animation.html Reversing an animation resets a sticky start time. PASS /scroll-animations/scroll-timelines/reverse-animation.html Reversing an animation does not cause it to leave the pending state PASS /scroll-animations/scroll-timelines/reverse-animation.html Reversing an animation does not cause it to resolve the ready promise @@ -729,7 +729,7 @@ PASS /scroll-animations/scroll-timelines/reverse-animation.html Reversing an ani FAIL /scroll-animations/scroll-timelines/reverse-animation.html Reversing when when playbackRate == 0 should preserve the playback rate PASS /scroll-animations/scroll-timelines/reverse-animation.html Reversing an idle animation aligns startTime with the rangeEnd boundary PASS /scroll-animations/scroll-timelines/reverse-animation.html Reversing an animation without an active timeline throws an InvalidStateError -FAIL /scroll-animations/scroll-timelines/reverse-animation.html Reversing an animation plays a pausing animation +PASS /scroll-animations/scroll-timelines/reverse-animation.html Reversing an animation plays a pausing animation PASS /scroll-animations/scroll-timelines/reverse-animation.html Reversing should use the negative pending playback rate PASS /scroll-animations/scroll-timelines/scroll-animation-effect-fill-modes.tentative.html Scroll based animation effect fill mode should return 'auto' for getTiming() and should return 'none' for getComputedTiming(). PASS /scroll-animations/scroll-timelines/scroll-animation-effect-fill-modes.tentative.html Applied effect value before start delay with fill: none @@ -789,7 +789,7 @@ PASS /scroll-animations/scroll-timelines/scroll-animation-effect-phases.tentativ PASS /scroll-animations/scroll-timelines/scroll-animation-effect-phases.tentative.html Make timeline inactive, force style update then pause the animation. No crashing indicates test success. PASS /scroll-animations/scroll-timelines/scroll-animation-inactive-timeline.html Play pending task doesn't run when the timeline is inactive. PASS /scroll-animations/scroll-timelines/scroll-animation-inactive-timeline.html Animation start and current times are correct if scroll timeline is activated after animation.play call. -FAIL /scroll-animations/scroll-timelines/scroll-animation-inactive-timeline.html Animation start and current times are correct if scroll timeline is activated after setting start time. +PASS /scroll-animations/scroll-timelines/scroll-animation-inactive-timeline.html Animation start and current times are correct if scroll timeline is activated after setting start time. FAIL /scroll-animations/scroll-timelines/scroll-animation-inactive-timeline.html Animation current time is correct when the timeline becomes newly inactive and then active again. FAIL /scroll-animations/scroll-timelines/scroll-animation.html Animation start and current times are correct for each animation state. FAIL /scroll-animations/scroll-timelines/scroll-animation.html Animation start and current times are correct for each animation state when the animation starts playing with advanced scroller. @@ -809,22 +809,22 @@ FAIL /scroll-animations/scroll-timelines/scroll-timeline-range.html Scroll timel PASS /scroll-animations/scroll-timelines/scroll-timeline-snapshotting.html ScrollTimeline current time is updated after programmatic animated scroll. PASS /scroll-animations/scroll-timelines/setting-current-time.html Setting animation current time to null throws TypeError. FAIL /scroll-animations/scroll-timelines/setting-current-time.html Setting the current time to an absolute time value throws exception -FAIL /scroll-animations/scroll-timelines/setting-current-time.html Set animation current time to a valid value without playing. -FAIL /scroll-animations/scroll-timelines/setting-current-time.html Set animation current time to a valid value while playing. -FAIL /scroll-animations/scroll-timelines/setting-current-time.html Set animation current time to a value beyond effect end. -FAIL /scroll-animations/scroll-timelines/setting-current-time.html Set animation current time to a negative value. -FAIL /scroll-animations/scroll-timelines/setting-current-time.html Setting current time while play pending overrides the current time -FAIL /scroll-animations/scroll-timelines/setting-current-time.html Setting animation.currentTime then restarting the animation should reset the current time. -FAIL /scroll-animations/scroll-timelines/setting-current-time.html Set Animation current time then scroll. -FAIL /scroll-animations/scroll-timelines/setting-current-time.html Animation current time and play state are correct when current time is set while the timeline is inactive. -FAIL /scroll-animations/scroll-timelines/setting-current-time.html Animation current time set while the timeline is inactive holds when the timeline becomes active again. +PASS /scroll-animations/scroll-timelines/setting-current-time.html Set animation current time to a valid value without playing. +PASS /scroll-animations/scroll-timelines/setting-current-time.html Set animation current time to a valid value while playing. +PASS /scroll-animations/scroll-timelines/setting-current-time.html Set animation current time to a value beyond effect end. +PASS /scroll-animations/scroll-timelines/setting-current-time.html Set animation current time to a negative value. +PASS /scroll-animations/scroll-timelines/setting-current-time.html Setting current time while play pending overrides the current time +PASS /scroll-animations/scroll-timelines/setting-current-time.html Setting animation.currentTime then restarting the animation should reset the current time. +PASS /scroll-animations/scroll-timelines/setting-current-time.html Set Animation current time then scroll. +PASS /scroll-animations/scroll-timelines/setting-current-time.html Animation current time and play state are correct when current time is set while the timeline is inactive. +PASS /scroll-animations/scroll-timelines/setting-current-time.html Animation current time set while the timeline is inactive holds when the timeline becomes active again. PASS /scroll-animations/scroll-timelines/setting-playback-rate.html Zero current time is not affected by playbackRate set while the animation is in idle state. PASS /scroll-animations/scroll-timelines/setting-playback-rate.html Zero current time is not affected by playbackRate set while the animation is in play-pending state. PASS /scroll-animations/scroll-timelines/setting-playback-rate.html Initial current time is scaled by playbackRate set while scroll-linked animation is in running state. FAIL /scroll-animations/scroll-timelines/setting-playback-rate.html The current time is scaled by playbackRate set while the scroll-linked animation is in play state. PASS /scroll-animations/scroll-timelines/setting-playback-rate.html The playback rate set before scroll-linked animation started playing affects the rate of progress of the current time PASS /scroll-animations/scroll-timelines/setting-playback-rate.html The playback rate affects the rate of progress of the current time when scrolling -FAIL /scroll-animations/scroll-timelines/setting-playback-rate.html Setting the playback rate while play-pending does not scale current time. +PASS /scroll-animations/scroll-timelines/setting-playback-rate.html Setting the playback rate while play-pending does not scale current time. FAIL /scroll-animations/scroll-timelines/setting-playback-rate.html Setting the playback rate while playing scales current time. FAIL /scroll-animations/scroll-timelines/setting-playback-rate.html Setting the playback rate while playing scales the set current time. PASS /scroll-animations/scroll-timelines/setting-playback-rate.html Negative initial playback rate should correctly modify initial current time. @@ -833,19 +833,19 @@ PASS /scroll-animations/scroll-timelines/setting-playback-rate.html Zero initial FAIL /scroll-animations/scroll-timelines/setting-playback-rate.html Setting a zero playback rate while running preserves the start time FAIL /scroll-animations/scroll-timelines/setting-playback-rate.html Reversing an animation with non-boundary aligned start time symmetrically adjusts the start time FAIL /scroll-animations/scroll-timelines/setting-start-time.html Setting the start time to an absolute time value throws exception -FAIL /scroll-animations/scroll-timelines/setting-start-time.html Setting the start time clears the hold time -FAIL /scroll-animations/scroll-timelines/setting-start-time.html Setting the start time clears the hold time when the timeline is inactive -FAIL /scroll-animations/scroll-timelines/setting-start-time.html Setting an unresolved start time sets the hold time -FAIL /scroll-animations/scroll-timelines/setting-start-time.html Setting an unresolved start time sets the hold time to unresolved when the timeline is inactive -FAIL /scroll-animations/scroll-timelines/setting-start-time.html Setting the start time resolves a pending ready promise -FAIL /scroll-animations/scroll-timelines/setting-start-time.html Setting the start time resolves a pending ready promise when the timelineis inactive +PASS /scroll-animations/scroll-timelines/setting-start-time.html Setting the start time clears the hold time +PASS /scroll-animations/scroll-timelines/setting-start-time.html Setting the start time clears the hold time when the timeline is inactive +PASS /scroll-animations/scroll-timelines/setting-start-time.html Setting an unresolved start time sets the hold time +PASS /scroll-animations/scroll-timelines/setting-start-time.html Setting an unresolved start time sets the hold time to unresolved when the timeline is inactive +PASS /scroll-animations/scroll-timelines/setting-start-time.html Setting the start time resolves a pending ready promise +PASS /scroll-animations/scroll-timelines/setting-start-time.html Setting the start time resolves a pending ready promise when the timelineis inactive FAIL /scroll-animations/scroll-timelines/setting-start-time.html Setting an unresolved start time on a play-pending animation makes it idle -FAIL /scroll-animations/scroll-timelines/setting-start-time.html Setting the start time updates the finished state -FAIL /scroll-animations/scroll-timelines/setting-start-time.html Setting the start time on a running animation updates the play state -FAIL /scroll-animations/scroll-timelines/setting-start-time.html Setting the start time on a reverse running animation updates the play state +PASS /scroll-animations/scroll-timelines/setting-start-time.html Setting the start time updates the finished state +PASS /scroll-animations/scroll-timelines/setting-start-time.html Setting the start time on a running animation updates the play state +PASS /scroll-animations/scroll-timelines/setting-start-time.html Setting the start time on a reverse running animation updates the play state PASS /scroll-animations/scroll-timelines/setting-start-time.html Setting the start time resolves a pending pause task -FAIL /scroll-animations/scroll-timelines/setting-start-time.html Setting the start time of a play-pending animation applies a pending playback rate -FAIL /scroll-animations/scroll-timelines/setting-start-time.html Setting the start time of a playing animation applies a pending playback rate +PASS /scroll-animations/scroll-timelines/setting-start-time.html Setting the start time of a play-pending animation applies a pending playback rate +PASS /scroll-animations/scroll-timelines/setting-start-time.html Setting the start time of a playing animation applies a pending playback rate PASS /scroll-animations/scroll-timelines/setting-timeline.tentative.html Setting a scroll timeline on a play-pending animation synchronizes currentTime of the animation with the scroll position. PASS /scroll-animations/scroll-timelines/setting-timeline.tentative.html Setting a scroll timeline on a pause-pending animation fixes the currentTime of the animation based on the scroll position once resumed PASS /scroll-animations/scroll-timelines/setting-timeline.tentative.html Setting a scroll timeline on a reversed play-pending animation synchronizes the currentTime of the animation with the scroll position. @@ -863,10 +863,10 @@ PASS /scroll-animations/scroll-timelines/setting-timeline.tentative.html Switchi FAIL /scroll-animations/scroll-timelines/setting-timeline.tentative.html Switching from a document timeline to a scroll timeline on an infinite duration animation. FAIL /scroll-animations/scroll-timelines/setting-timeline.tentative.html Changing from a scroll-timeline to a view-timeline updates start time. PASS /scroll-animations/scroll-timelines/source-quirks-mode.html Style of is reflected in source attribute in quirks mode -FAIL /scroll-animations/scroll-timelines/update-playback-rate.html Updating the playback rate maintains the current time +PASS /scroll-animations/scroll-timelines/update-playback-rate.html Updating the playback rate maintains the current time PASS /scroll-animations/scroll-timelines/update-playback-rate.html Updating the playback rate while running makes the animation pending -FAIL /scroll-animations/scroll-timelines/update-playback-rate.html Updating the playback rate on a play-pending animation maintains the current time -FAIL /scroll-animations/scroll-timelines/update-playback-rate.html Updating the playback rate on a pause-pending animation maintains the current time +PASS /scroll-animations/scroll-timelines/update-playback-rate.html Updating the playback rate on a play-pending animation maintains the current time +PASS /scroll-animations/scroll-timelines/update-playback-rate.html Updating the playback rate on a pause-pending animation maintains the current time PASS /scroll-animations/scroll-timelines/update-playback-rate.html If a pending playback rate is set multiple times, the latest wins PASS /scroll-animations/scroll-timelines/update-playback-rate.html In the idle state, the playback rate is applied immediately PASS /scroll-animations/scroll-timelines/update-playback-rate.html In the paused state, the playback rate is applied immediately @@ -933,17 +933,17 @@ FAIL /scroll-animations/view-timelines/timeline-offset-in-keyframe.html Timeline FAIL /scroll-animations/view-timelines/unattached-subject-inset.html Creating a view timeline with a subject that is not attached to the document works as expected FAIL /scroll-animations/view-timelines/view-timeline-get-current-time-range-name.html View timeline current time for named range FAIL /scroll-animations/view-timelines/view-timeline-get-set-range.html Getting and setting the animation range -FAIL /scroll-animations/view-timelines/view-timeline-inset.html View timeline with px based inset. -FAIL /scroll-animations/view-timelines/view-timeline-inset.html View timeline with percent based inset. -FAIL /scroll-animations/view-timelines/view-timeline-inset.html view timeline with inset auto. -FAIL /scroll-animations/view-timelines/view-timeline-inset.html view timeline with font relative inset. +PASS /scroll-animations/view-timelines/view-timeline-inset.html View timeline with px based inset. +PASS /scroll-animations/view-timelines/view-timeline-inset.html View timeline with percent based inset. +PASS /scroll-animations/view-timelines/view-timeline-inset.html view timeline with inset auto. +PASS /scroll-animations/view-timelines/view-timeline-inset.html view timeline with font relative inset. FAIL /scroll-animations/view-timelines/view-timeline-inset.html view timeline with viewport relative insets. -FAIL /scroll-animations/view-timelines/view-timeline-inset.html view timeline inset as string +PASS /scroll-animations/view-timelines/view-timeline-inset.html view timeline inset as string PASS /scroll-animations/view-timelines/view-timeline-inset.html view timeline with invalid inset PASS /scroll-animations/view-timelines/view-timeline-missing-subject.html ViewTimeline with missing subject PASS /scroll-animations/view-timelines/view-timeline-on-display-none-element.html element with display: none should have inactive viewtimeline PASS /scroll-animations/view-timelines/view-timeline-range-large-subject.html View timeline with range set via delays. -FAIL /scroll-animations/view-timelines/view-timeline-range.html View timeline with range as pair. +PASS /scroll-animations/view-timelines/view-timeline-range.html View timeline with range as pair. PASS /scroll-animations/view-timelines/view-timeline-range.html View timeline with range and inferred name or offset. PASS /scroll-animations/view-timelines/view-timeline-range.html View timeline with range as pair. PASS /scroll-animations/view-timelines/view-timeline-range.html View timeline with range as pair. @@ -957,4 +957,4 @@ FAIL /scroll-animations/view-timelines/view-timeline-sticky-block.html View time FAIL /scroll-animations/view-timelines/view-timeline-sticky-inline.html View timeline with sticky target, block axis. FAIL /scroll-animations/view-timelines/view-timeline-subject-size-changes.html View timeline with subject size change after the creation of the animation FAIL /scroll-animations/view-timelines/zero-intrinsic-iteration-duration.tentative.html Intrinsic iteration duration is non-negative -Passed 392 of 959 tests. +Passed 432 of 959 tests.