diff --git a/web-animations-2/Overview.bs b/web-animations-2/Overview.bs
index 88355c12dcc..58a1cca0aef 100644
--- a/web-animations-2/Overview.bs
+++ b/web-animations-2/Overview.bs
@@ -106,6 +106,7 @@ previous level of this specification:
* an animation effect-specific
playback rate,
* custom effects.
+* Support for non-monotonic (scroll) timelines.
Timing model
@@ -149,6 +150,82 @@ Along with the following updated description:
Setting the timeline of an animation
+The procedure to set the timeline of an animation,
+animation, to new timeline which may be null, is as
+follows:
+
+1. Let old timeline be the current timeline of
+ animation, if any.
+1. If new timeline is the same object as old timeline,
+ abort this procedure.
+1. Let |previous play state| be |animation|'s [=play state=].
+1. Let |previous current time| be the |animation|'s [=current time=].
+1. Let |from finite timeline| be true if |old timeline| is not null and
+ not [=monotonically increasing=].
+1. Let |to finite timeline| be true if |timeline| is not null and not
+ [=monotonically increasing=].
+1. Let the timeline of animation be new timeline.
+1. Set the flag |reset current time on resume| to false.
+1. Perform the steps corresponding to the first matching
+ condition from the following, if any:
+
+
+
+ : If |to finite timeline|,
+
+ :: 1. [=Apply any pending playback rate=] on |animation|
+ 1. Let |seek time| be zero if [=playback=] rate ≥ 0, and
+ |animation|'s
associated effect end otherwise.
+ 1. Update the animation based on the first matching condition if any:
+
+
+
+ : If
either of the following conditions are true:
+ * |previous play state| is 'running' or,
+ * |previous play state| is 'finished'
+
+ :: Set |animation|'s [=start time=] to |seek time|.
+
+ : If |previous play state| is 'paused':
+
+ :: If |previous current time| is resolved:
+
+ :: 1. Set the flag |reset current time on resume| to true.
+ 1. Set [=start time=] to unresolved.
+ 1. Set [=hold time=] to |previous current time|.
+
+
+ This step ensures that the [=current time=] is preserved
+ even in the case of a pause-pending animation with a resolved [=start time=].
+
+
+ :: Otherwise
+
+ :: 1. Set [=start time=] to |seek time|.
+
+
+
+ : If |from finite timeline| and |previous current time| is resolved,
+
+ :: Run the procedure to
set the current time to
+ |previous current time|.
+
+
+
+1. If the [=start time=] of animation is resolved, make animation's hold time
+ unresolved.
+
+
+ This step ensures that the finished play state of
+ animation is not “sticky” but is re-evaluated
+ based on its updated current time.
+
+
+1. Run the procedure to update an animation's finished state for
+ animation with the did seek flag set to false, and
+ the synchronously notify flag set to false.
+
Issue: If new timeline is null, we should ensure that custom
effects get called with an unresolved iteration progress
(unless a subsequent change in the same script execution context makes this
@@ -194,9 +271,345 @@ descendant effects and custom effects such that the first condition is:
> animation effect.
+
Setting the current time of an
+Animation
+
+The current time of an animation can be set to a new value to
+seek the animation.
+The procedure for setting the current time is defined in two parts.
+
+The procedure to silently set the current time of
+an animation, animation, to seek time is as follows:
+
+1. If seek time is an unresolved time value,
+ then perform the following steps.
+
+ 1. If the current time is resolved, then
+ throw a TypeError.
+
+ 1. Abort these steps.
+
+1. Update either animation's hold time or
+ [=start time=] as follows:
+
+
+
+ : 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.
+
+ : Otherwise,
+ :: Set
animation's [=start time=] to the result of evaluating
+
|timeline time| - (|seek time| / [=playback rate=])
+ where
timeline time is the current
time value
+ of
timeline associated with
animation.
+
+
+
+1. If animation has no associated timeline or the associated
+ timeline is inactive,
+ make animation's [=start time=] unresolved.
+
+
+ This preserves the invariant that when we don't have an active timeline it
+ is only possible to set either the [=start time=]
+ or the animation's current time.
+
+
+1. Make animation's previous current time unresolved.
+
+1. Set the |reset current time on resume| flag to false.
+
+
+The procedure to set the current time of an animation,
+animation, to seek time is as follows:
+
+1. Run the steps to silently set the current time of
+ animation to seek time.
+1. If animation has a pending pause task, synchronously
+ complete the pause operation by performing the following steps:
+ 1. Set animation's hold time to seek time.
+ 1. [=Apply any pending playback rate=] to |animation|.
+ 1. Make animation's [=start time=] unresolved.
+ 1. Cancel the pending pause task.
+ 1. Resolve animation's
+ current ready promise with animation.
+1. Run the procedure to update an animation's finished state for
+ animation with the did seek flag set to true, and
+ the synchronously notify flag set to false.
+
+Setting the start time of an
+Animation
+
+
+The procedure to set the start time
+of animation, animation, to new start time,
+is as follows:
+
+1. Let timeline time be the current time value of the
+ timeline that animation is associated with.
+ If there is no timeline associated with animation or the
+ associated timeline is inactive,
+ let the timeline time be unresolved.
+
+1. If timeline time is unresolved and new start
+ time is resolved, make animation's
+ hold time unresolved.
+
+
+ This preserves the invariant that when we don't have an active timeline it
+ is only possible to set either the [=start time=]
+ or the animation's current time.
+
+
+1. Let previous current time be animation's current
+ time.
+
+ Note: This is the current time after applying the changes from the
+ previous step which may cause the current time to become
+ unresolved.
+
+1. [=Apply any pending playback rate=] on |animation|.
+
+1. Set animation's [=start time=] to new start time.
+
+1. Set the |reset current time on resume| flag to false.
+
+1. Update animation's hold time based on the first matching
+ condition from the following,
+
+
+
+ : If
new start time is
resolved,
+ :: If
animation's [=playback rate=] is not zero,
+ make
animation's
hold time unresolved.
+
+ : Otherwise (
new start time is
unresolved),
+ :: Set
animation's
hold time to
previous current
+ time even if
previous current time is
+
unresolved.
+
+
+
+1. If animation has a pending play task or
+ a pending pause task, cancel that task and
+ resolve animation's
+ current ready promise with animation.
+
+1. Run the procedure to update an animation's finished state for
+ animation with the did seek flag set to true, and
+ the synchronously notify flag set to false.
+
Playing an animation
-The procedure to [=play an animation=] needs to include scheduling a task for
+The procedure to play an animation, animation, given
+a flag auto-rewind, is as follows:
+
+Note: The auto-rewind flag is provided for other specifications
+that build on this model but do not require the rewinding behavior, such
+as CSS Animations [[CSS-ANIMATIONS-1]].
+
+1. Let aborted pause be a boolean flag that is true if
+ animation has a pending pause task, and false otherwise.
+1. Let has pending ready promise be a boolean flag that is
+ initially false.
+1. Let seek time be a time value that is initially unresolved.
+1. Let has finite timeline be true if |animation| has an associated
+ timeline that is not [=monotonically increasing=].
+1. Let previous current time be the |animation|'s [=current time=]
+1. If |reset current time on resume| is set:
+
+ * Set previous current time to unresolved.
+ * Set the |reset curent time on resume| flag to false.
+
+1. Perform the steps corresponding to the first matching
+ condition from the following, if any:
+
+
+
+ : If |animation|'s [=effective playback rate=] > 0,
+ the
auto-rewind flag is true and
either
+
animation's:
+
+ *
previous current time is
unresolved, or
+ *
previous current time < zero, or
+ *
previous current time ≥
associated effect end,
+
+ :: Set
seek time to zero.
+
+ : If |animation|'s [=effective playback rate=] < 0,
+ the
auto-rewind flag is true and
either
+
animation's:
+
+ *
previous current time is
unresolved, or
+ *
previous current time ≤ zero, or
+ *
previous current time >
associated effect end,
+ ::
+
+
+ : If |animation|'s [=effective playback rate=] = 0 and |animation|'s
+ [=current time=] is [=unresolved=],
+
+ :: Set
seek time to zero.
+
+
+
+1. If |seek time| is resolved,
+
+
+
+ : If |has finite timeline| is true,
+ :: 1. Set
animation's
start time to
seek time.
+ 1. Let |animation|'s [=hold time=] be
unresolved.
+ 1. [=Apply any pending playback rate=] on |animation|.
+ : Otherwise,
+ :: Set
animation's
hold time to
seek time.
+
+
+
+1. If animation's hold time is resolved,
+ let its [=start time=] be unresolved.
+
+1. If animation has a pending play task or a
+ pending pause task,
+
+ 1. Cancel that task.
+ 1. Set has pending ready promise to true.
+
+1. If the following four conditions are all satisfied:
+
+ * |animation|'s [=hold time=] is [=unresolved=], and
+ * |seek time| is [=unresolved=], and
+ * |aborted pause| is false, and
+ * |animation| does not have a [=pending playback rate=],
+
+ abort this procedure.
+
+1. If has pending ready promise is false,
+ let animation's current ready promise be
+ a new promise in the relevant Realm of animation.
+
+1. Schedule a task to run as soon as animation is ready.
+ The task shall perform the following steps:
+
+ 1. Assert that at least one of |animation|'s [=start time=] or [=hold
+ time=] is resolved.
+
+ 1. Let ready time be the time value of
+ the timeline associated with animation at the moment
+ when animation became ready.
+
+ 1. Perform the steps corresponding to the first matching condition below,
+ if any:
+
+
+
+ : If |animation|'s [=hold time=] is
resolved,
+
+ :: 1. [=Apply any pending playback rate=] on |animation|.
+
+ 1. Let |new start time| be the result of evaluating
+
|ready time| - [=hold time=] / [=playback rate=]
+ for |animation|.
+ If the [=playback rate=] is zero, let
+ |new start time| be simply |ready time|.
+
+ 1. Set the [=start time=] of |animation| to |new start time|.
+
+ 1. If |animation|'s [=playback rate=] is not 0, make |animation|'s
+ [=hold time=] [=unresolved=].
+
+ : If |animation|'s [=start time=] is resolved and |animation| has
+ a [=pending playback rate=],
+
+ :: 1. Let |current time to match| be the result of evaluating
+
(|ready time| - [=start time=]) ×
+ [=playback rate=] for |animation|.
+
+ 1. [=Apply any pending playback rate=] on |animation|.
+
+ 1. If |animation|'s [=playback rate=] is zero, let |animation|'s
+ [=hold time=] be |current time to match|.
+
+ 1. Let |new start time| be the result of evaluating
+
|ready time| - |current time to match| /
+ [=playback rate=] for |animation|.
+ If the [=playback rate=] is zero, let |new start time| be simply
+ |ready time|.
+
+ 1. Set the [=start time=] of |animation| to |new start time|.
+
+
+
+ 1. Resolve animation's current
+ ready promise with animation.
+
+ 1. Run the procedure to update an animation's finished state for
+ animation with the did seek flag set to false,
+ and the synchronously notify flag set to false.
+
+
+
+ So long as the above task is scheduled but has yet to run,
+ animation is described as having a
+ pending play task.
+ While the task is running, however, |animation| does not have
+ a [=pending play task=].
+
+ If a user agent determines that |animation| is immediately ready, it
+ may schedule the above task as a microtask such that it runs at the next
+ microtask checkpoint, but it must
+ not perform the task synchronously.
+
+
+
+ The above requirement to run the
pending play task asynchronously
+ ensures that code such as the following behaves consistently between
+ implementations:
+
+
+ animation.play();
+ animation.ready.then(
+ () => { console.log('Playback commenced'); },
+ () => { console.log('Playback was canceled'); }
+ );
+ // Suppose some condition requires playback to be canceled...
+ animation.cancel();
+ // "Playback was canceled" will be printed to the console.
+
+
+ In the above code, were the [=pending play task=] run synchronously, the
+ [=current ready promise=] would not be rejected.
+
+
+
+1. Run the procedure to update an animation's finished state for
+ animation with the did seek flag set to false, and
+ the synchronously notify flag set to false.
+
+Issue: The procedure to [=play an animation=] needs to include scheduling a task for
updating [=custom effects=].