Re: [csswg-drafts] [web-animations-1] Setting the target effect to null on a play-pending animation should probably not make it paused

Discussed this yesterday with @graouts, @stephenmcgruer, and @flackr and decided this was probably ok (i.e. dropping the cancelation step), provided that the promises resolve as expected.

Given the following test:

```js
const anim = div.animate({ marginLeft: [ '0px', '100px' ] }, 1000);

console.group('Initial state');
console.log(`playState: ${anim.playState}`);
console.log(`pending: ${anim.pending}`);
console.groupEnd();

anim.ready.then(() => {
  console.log('Ready promise resolved');
}).catch(() => {
  console.log('Ready promise rejected');
});
anim.finished.then(() => {
  console.log('Finished promise resolved');
}).catch(() => {
  console.log('Finished promise rejected');
});

console.group('After setting effect to null');
anim.effect = null;
console.log(`playState: ${anim.playState}`);
console.log(`pending: ${anim.pending}`);
console.groupEnd();

requestAnimationFrame(() => {
  console.log('Next frame');
});
```
([Codepen](https://codepen.io/birtles/pen/WKOEKj?editors=0010))

Current Firefox gives:

```
+ Initial state
  playState: running
  pending: true
+ After setting effect to null
  playState: paused
  pending: false
Ready promise rejected
Next frame
```

With these changes we get:

```
+ Initial state
  playState: running
  pending: true
+ After setting effect to null
  playState: finished
  pending: true
Finished promise resolved
Ready promise resolved
Next frame
```

The reason for the finished promise being resolved first is that when we update the effect, the spec says to:

> 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.

which will bring us to:

> if synchronously notify is false, queue a microtask to run finish notification steps for animation

So we'll end up with a microtask on the queue to resolve the finish promise that will be processed before the next frame where we resolve the ready promise.

That's a little unexpected perhaps, but I think it kind of makes sense too (and trying to fix it would probably only complicate the model further).


The other question we had was whether this arrangement would allow you to recover from the finished-pending state and go back to play-pending.

For example, if you do:

```js
const anim = div.animate({ marginLeft: [ '0px', '100px' ] }, 1000);
anim.effect = null;
anim.effect = new KeyframeEffect(...);
```

Are you play-pending at the end?

The answer is yes. Adding the following to the above test:

```js
console.group('After setting effect to something else');
anim.effect = new KeyframeEffect(div, { marginLeft: [ '0px', '100px' ] }, 1000);
console.log(`playState: ${anim.playState}`);
console.log(`pending: ${anim.pending}`);
console.groupEnd();
```

I get:

```
+ Initial state
  playState: running
  pending: true
+ After setting effect to null
  playState: finished
  pending: true
+ After setting effect to something else
  playState: running
  pending: true
Ready promise resolved
Next frame
(1s later)
Finished promise resolved
```

Which seems like the behavior we want.

Unless anyone has any objections, I'm going to go ahead and make this change.

-- 
GitHub Notification of comment by birtles
Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/2077#issuecomment-407647460 using your GitHub account

Received on Wednesday, 25 July 2018 06:28:32 UTC