Integrated Progress based animations with CSS Animations

Timeline duration can now be stored on an AnimationEffect.
This was needed since for CSS animations, InertEffects with
no owning animation are used until later in the pipeline.
Normally the owning animation of an effect is used to gain
access to the corresponding timeline which provides the timeline
duration needed for timing normalization math, but in some
cases the duration was needed before an effect had an owner
assigned. As such it is now possible to create an InertEffect
and pass in a timeline duration if needed.

Added logic for when CSS animations swap from progress based
timeline to a time based timeline. This new logic preserves
the current progress of the animation even when current times
do not match up.

I also removed time range from some CSS tests since they are
now supported by progress based animations.

Bug: 1216655, 1140602
Change-Id: I7dde1f117968c6465eb7c4c0f4b8b66d9371776f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3130703
Reviewed-by: Kevin Ellis <kevers@chromium.org>
Reviewed-by: Anders Hartvoll Ruud <andruud@chromium.org>
Commit-Queue: Jordan Taylor <jortaylo@microsoft.com>
Cr-Commit-Position: refs/heads/main@{#917801}
diff --git a/scroll-animations/css/at-scroll-timeline-cascade.html b/scroll-animations/css/at-scroll-timeline-cascade.html
index 7103491..fa72e0b 100644
--- a/scroll-animations/css/at-scroll-timeline-cascade.html
+++ b/scroll-animations/css/at-scroll-timeline-cascade.html
@@ -18,13 +18,11 @@
   }
   @scroll-timeline timeline {
     source: selector(#scroller);
-    time-range: 10s;
     start: 0px;
     end: 100px;
   }
   @scroll-timeline timeline {
     source: selector(#scroller);
-    time-range: 1s;
     start: 0px;
     end: 50px;
   }
@@ -45,6 +43,6 @@
   promise_test(async (t) => {
     scroller.scrollTop = 25;
     await waitForNextFrame();
-    assert_equals(getComputedStyle(element).width, '105px');
+    assert_equals(getComputedStyle(element).width, '150px');
   }, 'Latest @scroll-timeline rule wins');
 </script>
diff --git a/scroll-animations/css/at-scroll-timeline-dynamic.tentative.html b/scroll-animations/css/at-scroll-timeline-dynamic.tentative.html
index 361a95e..ac0f42e 100644
--- a/scroll-animations/css/at-scroll-timeline-dynamic.tentative.html
+++ b/scroll-animations/css/at-scroll-timeline-dynamic.tentative.html
@@ -60,8 +60,6 @@
       options.name = 'timeline';
     if (typeof(options.source) == 'undefined')
       options.source = 'selector(#scroller1)';
-    if (typeof(options.timeRange) == 'undefined')
-      options.timeRange = '1e10s';
     if (typeof(options.start) == 'undefined')
       options.start = '0px';
     if (typeof(options.end) == 'undefined')
@@ -69,7 +67,6 @@
     return insertSheet(`
       @scroll-timeline ${options.name} {
         source: ${options.source};
-        time-range: ${options.timeRange};
         start: ${options.start};
         end: ${options.end};
       }
@@ -107,7 +104,13 @@
       scroller1.scrollTop = scroller1.scrollTop - 1;
       scroller2.scrollTop = scroller2.scrollTop - 1;
       await waitForNextFrame();
-      assert_equals(getComputedStyle(element).width, expected);
+      assert_approx_equals(
+          parseFloat(getComputedStyle(element).width),
+          parseFloat(expected),
+          // converting between progress based scroll timelines and document
+          // timelines has some margin of rounding error, this check makes sure
+          // values are within 1/10th of a pixel.
+          0.1);
     }, description + ' [scroll]');
   }
 
diff --git a/scroll-animations/css/at-scroll-timeline-ignored.tentative.html b/scroll-animations/css/at-scroll-timeline-ignored.tentative.html
index 1a699ca..bb8b44f 100644
--- a/scroll-animations/css/at-scroll-timeline-ignored.tentative.html
+++ b/scroll-animations/css/at-scroll-timeline-ignored.tentative.html
@@ -23,21 +23,18 @@
   @scroll-timeline timeline1 {
     source: selector(#scroller1);
     orientation: auto;
-    time-range: 1e10s;
     start: 0px;
     end: 100px;
   }
   @scroll-timeline timeline2 {
     source: selector(#scroller2);
     orientation: auto;
-    time-range: 1e10s;
     start: 0px;
     end: 100px;
   }
   @scroll-timeline timeline3 {
     source: selector(#scroller3);
     orientation: auto;
-    time-range: 1e10s;
     start: 0px;
     end: 100px;
   }
diff --git a/scroll-animations/css/at-scroll-timeline-source-invalidation.tentative.html b/scroll-animations/css/at-scroll-timeline-source-invalidation.tentative.html
index 5f9561c..6f9ce7a 100644
--- a/scroll-animations/css/at-scroll-timeline-source-invalidation.tentative.html
+++ b/scroll-animations/css/at-scroll-timeline-source-invalidation.tentative.html
@@ -23,7 +23,6 @@
   }
   @scroll-timeline timeline {
     source: selector(#scroller);
-    time-range: 1e10s;
     start: 0px;
     end: 100px;
   }
diff --git a/scroll-animations/css/at-scroll-timeline-start-end.html b/scroll-animations/css/at-scroll-timeline-start-end.html
index e881d0d..0c4294e 100644
--- a/scroll-animations/css/at-scroll-timeline-start-end.html
+++ b/scroll-animations/css/at-scroll-timeline-start-end.html
@@ -19,47 +19,39 @@
   }
   @scroll-timeline timeline_0px_100px {
     source: selector(#scroller);
-    time-range: 10s;
     start: 0px;
     end: 100px;
   }
   @scroll-timeline timeline_50px_100px {
     source: selector(#scroller);
-    time-range: 10s;
     start: 50px;
     end: 100px;
   }
   @scroll-timeline timeline_auto_auto {
     source: selector(#scroller);
-    time-range: 10s;
     start: auto;
     end: auto;
   }
   @scroll-timeline timeline_auto_auto_implicit {
     source: selector(#scroller);
-    time-range: 10s;
   }
   @scroll-timeline timeline_50px_auto {
     source: selector(#scroller);
-    time-range: 10s;
     start: 50px;
     end: auto;
   }
   @scroll-timeline timeline_auto_100px {
     source: selector(#scroller);
-    time-range: 10s;
     start: auto;
     end: 100px;
   }
   @scroll-timeline timeline_25p_75p {
     source: selector(#scroller);
-    time-range: 10s;
     start: 25%;
     end: 75%;
   }
   @scroll-timeline timeline_calc_calc {
     source: selector(#scroller);
-    time-range: 10s;
     start: calc(25% + 10px);
     end: calc(75% + 10px);
   }
diff --git a/scroll-animations/css/at-scroll-timeline-time-range.html b/scroll-animations/css/at-scroll-timeline-time-range.html
deleted file mode 100644
index 2a57ed4..0000000
--- a/scroll-animations/css/at-scroll-timeline-time-range.html
+++ /dev/null
@@ -1,77 +0,0 @@
-<!DOCTYPE html>
-<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#scroll-timeline-at-rule">
-<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#descdef-scroll-timeline-time-range">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="/web-animations/testcommon.js"></script>
-<style>
-  #scroller {
-    overflow: scroll;
-    width: 100px;
-    height: 100px;
-  }
-  #contents {
-    height: 200px;
-  }
-  @keyframes expand {
-    from { width: 100px; }
-    to { width: 200px; }
-  }
-  @scroll-timeline timeline_10s {
-    source: selector(#scroller);
-    time-range: 10s;
-    start: 0px;
-    end: 100px;
-  }
-  @scroll-timeline timeline_1s {
-    source: selector(#scroller);
-    time-range: 1s;
-    start: 0px;
-    end: 100px;
-  }
-  @scroll-timeline timeline_1000ms {
-    source: selector(#scroller);
-    time-range: 1000ms;
-    start: 0px;
-    end: 100px;
-  }
-  #container > div {
-    width: 0px;
-    animation-name: expand;
-    animation-duration: 10s;
-    animation-timing-function: linear;
-  }
-  /* Ensure stable expectations if feature is not supported */
-  @supports not (animation-timeline:foo) {
-    #container > div { animation-play-state: paused; }
-  }
-  #element_10s { animation-timeline: timeline_10s; }
-  #element_1s { animation-timeline: timeline_1s; }
-  #element_1000ms { animation-timeline: timeline_1000ms; }
-</style>
-<div id=scroller>
-  <div id=contents></div>
-</div>
-<div id=container>
-  <div id=element_10s></div>
-  <div id=element_1s></div>
-  <div id=element_1000ms></div>
-</div>
-<script>
-  scroller.scrollTop = 50;
-
-  promise_test(async (t) => {
-    await waitForNextFrame();
-    assert_equals(getComputedStyle(element_10s).width, '150px');
-  }, 'Timerange mapped correctly (10s)');
-
-  promise_test(async (t) => {
-    await waitForNextFrame();
-    assert_equals(getComputedStyle(element_1s).width, '105px');
-  }, 'Timerange mapped correctly (1s)');
-
-  promise_test(async (t) => {
-    await waitForNextFrame();
-    assert_equals(getComputedStyle(element_1s).width, '105px');
-  }, 'Timerange mapped correctly (1000ms)');
-</script>
diff --git a/scroll-animations/css/scroll-timeline-cssom.tentative.html b/scroll-animations/css/scroll-timeline-cssom.tentative.html
index 1e6f581..afca950 100644
--- a/scroll-animations/css/scroll-timeline-cssom.tentative.html
+++ b/scroll-animations/css/scroll-timeline-cssom.tentative.html
@@ -157,17 +157,13 @@
   `@scroll-timeline timeline { start: selector(#bar) start 1; }`);
 
 test_csstext(
-  'time-range descriptor',
-  `@scroll-timeline timeline { time-range: 10s; }`);
-
-test_csstext(
   'defaults',
-  `@scroll-timeline timeline { source: none; orientation: auto; start: auto; end: auto; time-range: auto; }`);
+  `@scroll-timeline timeline { source: none; orientation: auto; start: auto; end: auto; }`);
 
 test_csstext(
   'order',
-  `@scroll-timeline timeline { orientation: auto; time-range: auto; source: none; end: auto; start: auto; }`,
-  `@scroll-timeline timeline { source: none; orientation: auto; start: auto; end: auto; time-range: auto; }`);
+  `@scroll-timeline timeline { orientation: auto; source: none; end: auto; start: auto; }`,
+  `@scroll-timeline timeline { source: none; orientation: auto; start: auto; end: auto; }`);
 
 // CSSScrollTimelineRule.source
 
@@ -246,21 +242,4 @@
 test_offsets('selector(#foo) end 3');
 test_offsets('selector(#foo) 3 end', 'selector(#foo) end 3');
 
-// CSSScrollTimelineRule.timeRange
-
-function test_scroll_time_range(specified, expected) {
-  test_descriptor('time-range', specified, expected);
-}
-
-test_scroll_time_range('auto');
-test_scroll_time_range(' auto ', 'auto');
-test_scroll_time_range('1s');
-test_scroll_time_range(' 1s ', '1s');
-test_scroll_time_range('1000ms');
-
-test_scroll_time_range('', 'auto');
-test_scroll_time_range('red', 'auto');
-test_scroll_time_range('#fff', 'auto');
-test_scroll_time_range('unset', 'auto');
-
 </script>