[web-animations] Update timing interfaces (#10047)
This updates the tests to reflect the specification changes made in https://github.com/w3c/csswg-drafts/commit/953041faa37d86d77eca651822eebc7dc7477e01
diff --git a/web-animations/animation-model/keyframe-effects/effect-value-iteration-composite-operation.html b/web-animations/animation-model/keyframe-effects/effect-value-iteration-composite-operation.html
index c2e9702..142d49d 100644
--- a/web-animations/animation-model/keyframe-effects/effect-value-iteration-composite-operation.html
+++ b/web-animations/animation-model/keyframe-effects/effect-value-iteration-composite-operation.html
@@ -20,13 +20,13 @@
iterations: 10,
iterationComposite: 'accumulate' });
- anim.currentTime = anim.effect.timing.duration / 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).alignContent, 'flex-end',
'Animated align-content style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration * 2;
assert_equals(getComputedStyle(div).alignContent, 'flex-start',
'Animated align-content style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
+ anim.currentTime += anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).alignContent, 'flex-end',
'Animated align-content style at 50s of the third iteration');
}, 'iteration composition of discrete type animation (align-content)');
@@ -41,13 +41,13 @@
iterationComposite: 'accumulate' });
anim.pause();
- anim.currentTime = anim.effect.timing.duration / 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).marginLeft, '5px',
'Animated margin-left style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration * 2;
assert_equals(getComputedStyle(div).marginLeft, '20px',
'Animated margin-left style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
+ anim.currentTime += anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).marginLeft, '25px',
'Animated margin-left style at 50s of the third iteration');
}, 'iteration composition of <length> type animation');
@@ -66,13 +66,13 @@
iterationComposite: 'accumulate' });
anim.pause();
- anim.currentTime = anim.effect.timing.duration / 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).width, '25px',
'Animated width style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration * 2;
assert_equals(getComputedStyle(div).width, '100px',
'Animated width style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
+ anim.currentTime += anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).width, '125px',
'Animated width style at 50s of the third iteration');
}, 'iteration composition of <percentage> type animation');
@@ -87,13 +87,13 @@
iterationComposite: 'accumulate' });
anim.pause();
- anim.currentTime = anim.effect.timing.duration / 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).color, 'rgb(60, 60, 60)',
'Animated color style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration * 2;
assert_equals(getComputedStyle(div).color, 'rgb(240, 240, 240)',
'Animated color style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
+ anim.currentTime += anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).color, 'rgb(255, 255, 255)',
'Animated color style at 50s of the third iteration');
}, 'iteration composition of <color> type animation');
@@ -108,13 +108,13 @@
iterationComposite: 'accumulate' });
anim.pause();
- anim.currentTime = anim.effect.timing.duration / 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).color, 'rgb(30, 90, 30)',
'Animated color style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration * 2;
assert_equals(getComputedStyle(div).color, 'rgb(120, 240, 120)',
'Animated color style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
+ anim.currentTime += anim.effect.getComputedTiming().duration / 2;
// The green color is (240 + 180) / 2 = 210
assert_equals(getComputedStyle(div).color, 'rgb(150, 210, 150)',
'Animated color style at 50s of the third iteration');
@@ -131,13 +131,13 @@
iterationComposite: 'accumulate' });
anim.pause();
- anim.currentTime = anim.effect.timing.duration / 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).flexGrow, '5',
'Animated flex-grow style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration * 2;
assert_equals(getComputedStyle(div).flexGrow, '20',
'Animated flex-grow style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
+ anim.currentTime += anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).flexGrow, '25',
'Animated flex-grow style at 50s of the third iteration');
}, 'iteration composition of <number> type animation');
@@ -154,13 +154,13 @@
iterationComposite: 'accumulate' });
anim.pause();
- anim.currentTime = anim.effect.timing.duration / 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).clip, 'rect(5px, 5px, 5px, 5px)',
'Animated clip style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration * 2;
assert_equals(getComputedStyle(div).clip, 'rect(20px, 20px, 20px, 20px)',
'Animated clip style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
+ anim.currentTime += anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).clip, 'rect(25px, 25px, 25px, 25px)',
'Animated clip style at 50s of the third iteration');
}, 'iteration composition of <shape> type animation');
@@ -175,13 +175,13 @@
iterationComposite: 'accumulate' });
anim.pause();
- anim.currentTime = anim.effect.timing.duration / 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).width, '5px',
'Animated calc width style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration * 2;
assert_equals(getComputedStyle(div).width, '20px',
'Animated calc width style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
+ anim.currentTime += anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).width, '25px',
'Animated calc width style at 50s of the third iteration');
}, 'iteration composition of <calc()> value animation');
@@ -200,15 +200,15 @@
iterationComposite: 'accumulate' });
anim.pause();
- anim.currentTime = anim.effect.timing.duration / 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).width, '10px',
// 100px * 5% + 5px
'Animated calc width style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration * 2;
assert_equals(getComputedStyle(div).width,
'40px', // 100px * (10% + 10%) + (10px + 10px)
'Animated calc width style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
+ anim.currentTime += anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).width,
'50px', // (40px + 60px) / 2
'Animated calc width style at 50s of the third iteration');
@@ -225,13 +225,13 @@
iterationComposite: 'accumulate' });
anim.pause();
- anim.currentTime = anim.effect.timing.duration / 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).opacity, '0.2',
'Animated opacity style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration * 2;
assert_equals(getComputedStyle(div).opacity, '0.8',
'Animated opacity style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
+ anim.currentTime += anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).opacity, '1', // (0.8 + 1.2) * 0.5
'Animated opacity style at 50s of the third iteration');
}, 'iteration composition of opacity animation');
@@ -247,15 +247,15 @@
iterationComposite: 'accumulate' });
anim.pause();
- anim.currentTime = anim.effect.timing.duration / 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).boxShadow,
'rgb(60, 60, 60) 5px 5px 5px 0px',
'Animated box-shadow style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration * 2;
assert_equals(getComputedStyle(div).boxShadow,
'rgb(240, 240, 240) 20px 20px 20px 0px',
'Animated box-shadow style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
+ anim.currentTime += anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).boxShadow,
'rgb(255, 255, 255) 25px 25px 25px 0px',
'Animated box-shadow style at 50s of the third iteration');
@@ -271,13 +271,13 @@
iterationComposite: 'accumulate' });
anim.pause();
- anim.currentTime = anim.effect.timing.duration / 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).filter, 'blur(5px)',
'Animated filter blur style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration * 2;
assert_equals(getComputedStyle(div).filter, 'blur(20px)',
'Animated filter blur style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
+ anim.currentTime += anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).filter, 'blur(25px)',
'Animated filter blur style at 50s of the third iteration');
}, 'iteration composition of filter blur animation');
@@ -293,15 +293,15 @@
iterationComposite: 'accumulate' });
anim.pause();
- anim.currentTime = anim.effect.timing.duration / 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).filter,
'brightness(1.4)',
'Animated filter brightness style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration * 2;
assert_equals(getComputedStyle(div).filter,
'brightness(2.6)', // brightness(1) + brightness(0.8) + brightness(0.8)
'Animated filter brightness style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
+ anim.currentTime += anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).filter,
'brightness(3)', // (brightness(2.6) + brightness(3.4)) * 0.5
'Animated filter brightness style at 50s of the third iteration');
@@ -318,15 +318,15 @@
iterationComposite: 'accumulate' });
anim.pause();
- anim.currentTime = anim.effect.timing.duration / 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).filter,
'brightness(0.5)',
'Animated filter brightness style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration * 2;
assert_equals(getComputedStyle(div).filter,
'brightness(0)', // brightness(1) is an identity element, not accumulated.
'Animated filter brightness style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
+ anim.currentTime += anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).filter,
'brightness(0.5)', // brightness(1) is an identity element, not accumulated.
'Animated filter brightness style at 50s of the third iteration');
@@ -343,15 +343,15 @@
iterationComposite: 'accumulate' });
anim.pause();
- anim.currentTime = anim.effect.timing.duration / 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).filter,
'drop-shadow(rgb(60, 60, 60) 5px 5px 5px)',
'Animated filter drop-shadow style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration * 2;
assert_equals(getComputedStyle(div).filter,
'drop-shadow(rgb(240, 240, 240) 20px 20px 20px)',
'Animated filter drop-shadow style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
+ anim.currentTime += anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).filter,
'drop-shadow(rgb(255, 255, 255) 25px 25px 25px)',
'Animated filter drop-shadow style at 50s of the third iteration');
@@ -368,15 +368,15 @@
iterationComposite: 'accumulate' });
anim.pause();
- anim.currentTime = anim.effect.timing.duration / 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).filter,
'brightness(1.5) contrast(1.5)',
'Animated filter list at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration * 2;
assert_equals(getComputedStyle(div).filter,
'brightness(3) contrast(3)',
'Animated filter list at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
+ anim.currentTime += anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).filter,
'brightness(3.5) contrast(3.5)',
'Animated filter list at 50s of the third iteration');
@@ -393,18 +393,18 @@
iterationComposite: 'accumulate' });
anim.pause();
- anim.currentTime = anim.effect.timing.duration / 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).filter,
'contrast(2) brightness(2)', // discrete
'Animated filter list at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration * 2;
assert_equals(getComputedStyle(div).filter,
// We can't accumulate 'contrast(2) brightness(2)' onto
// the first list 'brightness(1) contrast(1)' because of
// mismatch of the order.
'brightness(1) contrast(1)',
'Animated filter list at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
+ anim.currentTime += anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).filter,
// We *can* accumulate 'contrast(2) brightness(2)' onto
// the same list 'contrast(2) brightness(2)' here.
@@ -424,15 +424,15 @@
iterationComposite: 'accumulate' });
anim.pause();
- anim.currentTime = anim.effect.timing.duration / 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).filter,
'sepia(0.5) contrast(1.5)',
'Animated filter list at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration * 2;
assert_equals(getComputedStyle(div).filter,
'sepia(2) contrast(3)',
'Animated filter list at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
+ anim.currentTime += anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).filter,
'sepia(2.5) contrast(3.5)',
'Animated filter list at 50s of the third iteration');
@@ -448,15 +448,15 @@
iterationComposite: 'accumulate' });
anim.pause();
- anim.currentTime = anim.effect.timing.duration / 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration / 2;
assert_matrix_equals(getComputedStyle(div).transform,
'matrix(0, 1, -1, 0, 0, 0)', // rotate(90deg)
'Animated transform(rotate) style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration * 2;
assert_matrix_equals(getComputedStyle(div).transform,
'matrix(1, 0, 0, 1, 0, 0)', // rotate(360deg)
'Animated transform(rotate) style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
+ anim.currentTime += anim.effect.getComputedTiming().duration / 2;
assert_matrix_equals(getComputedStyle(div).transform,
'matrix(0, 1, -1, 0, 0, 0)', // rotate(450deg)
'Animated transform(rotate) style at 50s of the third iteration');
@@ -472,16 +472,16 @@
iterationComposite: 'accumulate' });
anim.pause();
- anim.currentTime = anim.effect.timing.duration / 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration / 2;
assert_matrix_equals(getComputedStyle(div).transform,
'matrix(0.5, 0, 0, 0.5, 0, 0)', // scale(0.5)
'Animated transform(scale) style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration * 2;
assert_matrix_equals(getComputedStyle(div).transform,
'matrix(0, 0, 0, 0, 0, 0)', // scale(0); scale(1) is an identity element,
// not accumulated.
'Animated transform(scale) style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
+ anim.currentTime += anim.effect.getComputedTiming().duration / 2;
assert_matrix_equals(getComputedStyle(div).transform,
'matrix(0.5, 0, 0, 0.5, 0, 0)', // scale(0.5); scale(1) an identity
// element, not accumulated.
@@ -498,15 +498,15 @@
iterationComposite: 'accumulate' });
anim.pause();
- anim.currentTime = anim.effect.timing.duration / 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration / 2;
assert_matrix_equals(getComputedStyle(div).transform,
'matrix(1.5, 0, 0, 1.5, 0, 0)', // scale(1.5)
'Animated transform(scale) style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration * 2;
assert_matrix_equals(getComputedStyle(div).transform,
'matrix(3, 0, 0, 3, 0, 0)', // scale(1 + (2 -1) + (2 -1))
'Animated transform(scale) style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
+ anim.currentTime += anim.effect.getComputedTiming().duration / 2;
assert_matrix_equals(getComputedStyle(div).transform,
'matrix(3.5, 0, 0, 3.5, 0, 0)', // (scale(3) + scale(4)) * 0.5
'Animated transform(scale) style at 50s of the third iteration');
@@ -522,15 +522,15 @@
iterationComposite: 'accumulate' });
anim.pause();
- anim.currentTime = anim.effect.timing.duration / 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration / 2;
assert_matrix_equals(getComputedStyle(div).transform,
'matrix(1, 0, 0, 1, 0, 0)', // scale(1)
'Animated transform(scale) style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration * 2;
assert_matrix_equals(getComputedStyle(div).transform,
'matrix(2, 0, 0, 2, 0, 0)', // (scale(0) + scale(2-1)*2)
'Animated transform(scale) style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
+ anim.currentTime += anim.effect.getComputedTiming().duration / 2;
assert_matrix_equals(getComputedStyle(div).transform,
'matrix(3, 0, 0, 3, 0, 0)', // (scale(2) + scale(4)) * 0.5
'Animated transform(scale) style at 50s of the third iteration');
@@ -547,15 +547,15 @@
iterationComposite: 'accumulate' });
anim.pause();
- anim.currentTime = anim.effect.timing.duration / 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration / 2;
assert_matrix_equals(getComputedStyle(div).transform,
'matrix(0, 1, -1, 0, 0, 5)', // rotate(90deg) translateX(5px)
'Animated transform list at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration * 2;
assert_matrix_equals(getComputedStyle(div).transform,
'matrix(1, 0, 0, 1, 20, 0)', // rotate(360deg) translateX(20px)
'Animated transform list at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
+ anim.currentTime += anim.effect.getComputedTiming().duration / 2;
assert_matrix_equals(getComputedStyle(div).transform,
'matrix(0, 1, -1, 0, 0, 25)', // rotate(450deg) translateX(25px)
'Animated transform list at 50s of the third iteration');
@@ -572,16 +572,16 @@
iterationComposite: 'accumulate' });
anim.pause();
- anim.currentTime = anim.effect.timing.duration / 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration / 2;
assert_matrix_equals(getComputedStyle(div).transform,
'matrix(2.5, 0, 0, 2.5, 15, 0)',
'Animated transform of matrix function at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration * 2;
assert_matrix_equals(getComputedStyle(div).transform,
// scale(2) + (scale(3-1)*2) + translateX(30px)*2
'matrix(6, 0, 0, 6, 60, 0)',
'Animated transform of matrix function at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
+ anim.currentTime += anim.effect.getComputedTiming().duration / 2;
assert_matrix_equals(getComputedStyle(div).transform,
// from: matrix(6, 0, 0, 6, 60, 0)
// to: matrix(7, 0, 0, 7, 90, 0)
@@ -601,20 +601,20 @@
iterationComposite: 'accumulate' });
anim.pause();
- anim.currentTime = anim.effect.timing.duration / 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration / 2;
assert_matrix_equals(getComputedStyle(div).transform,
// Interpolate between matrix(2, 0, 0, 2, 0, 0) = translateX(0px) scale(2)
// and matrix(3, 0, 0, 3, 30, 0) = scale(3) translateX(10px)
'matrix(2.5, 0, 0, 2.5, 15, 0)',
'Animated transform list at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration * 2;
assert_matrix_equals(getComputedStyle(div).transform,
// 'from' and 'to' value are mismatched, so accumulate
// matrix(2, 0, 0, 2, 0, 0) onto matrix(3, 0, 0, 3, 30, 0) * 2
// = scale(2) + (scale(3-1)*2) + translateX(30px)*2
'matrix(6, 0, 0, 6, 60, 0)',
'Animated transform list at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
+ anim.currentTime += anim.effect.getComputedTiming().duration / 2;
assert_matrix_equals(getComputedStyle(div).transform,
// Interpolate between matrix(6, 0, 0, 6, 60, 0)
// and matrix(7, 0, 0, 7, 210, 0) = scale(7) translate(30px)
@@ -636,20 +636,20 @@
iterationComposite: 'accumulate' });
anim.pause();
- anim.currentTime = anim.effect.timing.duration / 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration / 2;
assert_matrix_equals(getComputedStyle(div).transform,
// Interpolate between matrix(1, 0, 0, 1, 0, 0) = translateX(0px)
// and matrix(2, 0, 0, 2, 20, 0) = scale(2) translateX(10px)
'matrix(1.5, 0, 0, 1.5, 10, 0)',
'Animated transform list at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration * 2;
assert_matrix_equals(getComputedStyle(div).transform,
// 'from' and 'to' value are mismatched, so accumulate
// matrix(1, 0, 0, 1, 0, 0) onto matrix(2, 0, 0, 2, 20, 0) * 2
// = scale(1) + (scale(2-1)*2) + translateX(20px)*2
'matrix(3, 0, 0, 3, 40, 0)',
'Animated transform list at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
+ anim.currentTime += anim.effect.getComputedTiming().duration / 2;
assert_matrix_equals(getComputedStyle(div).transform,
// Interpolate between matrix(3, 0, 0, 3, 40, 0)
// and matrix(4, 0, 0, 4, 120, 0) =
@@ -670,17 +670,17 @@
iterationComposite: 'accumulate' });
anim.pause();
- anim.currentTime = anim.effect.timing.duration / 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration / 2;
assert_matrix_equals(getComputedStyle(div).transform,
// translateX(none) -> translateX(10px) @ 50%
'matrix(1, 0, 0, 1, 5, 0)',
'Animated transform list at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration * 2;
assert_matrix_equals(getComputedStyle(div).transform,
// translateX(10px * 2 + none) -> translateX(10px * 2 + 10px) @ 0%
'matrix(1, 0, 0, 1, 20, 0)',
'Animated transform list at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
+ anim.currentTime += anim.effect.getComputedTiming().duration / 2;
assert_matrix_equals(getComputedStyle(div).transform,
// translateX(10px * 2 + none) -> translateX(10px * 2 + 10px) @ 50%
'matrix(1, 0, 0, 1, 25, 0)',
@@ -704,16 +704,16 @@
iterationComposite: 'accumulate' });
anim.pause();
- anim.currentTime = anim.effect.timing.duration / 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration / 2;
assert_matrix_equals(getComputedStyle(div).transform,
'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 40, 1)',
'Animated transform of matrix3d function at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration * 2;
assert_matrix_equals(getComputedStyle(div).transform,
// translateZ(30px) + (translateZ(50px)*2)
'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 130, 1)',
'Animated transform of matrix3d function at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
+ anim.currentTime += anim.effect.getComputedTiming().duration / 2;
assert_matrix_equals(getComputedStyle(div).transform,
// from: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 130, 1)
// to: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 150, 1)
@@ -736,11 +736,11 @@
assert_matrix_equals(getComputedStyle(div).transform,
'matrix(1, 0, 0, 1, 0, 0)', // Actually not rotated at all.
'Animated transform of rotate3d function at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration * 2;
assert_matrix_equals(getComputedStyle(div).transform,
rotate3dToMatrix3d(1, 1, 0, Math.PI), // 180deg
'Animated transform of rotate3d function at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
+ anim.currentTime += anim.effect.getComputedTiming().duration / 2;
assert_matrix_equals(getComputedStyle(div).transform,
rotate3dToMatrix3d(1, 1, 0, 225 * Math.PI / 180), //((270 + 180) * 0.5)deg
'Animated transform of rotate3d function at 50s of the third iteration');
@@ -756,13 +756,13 @@
iterationComposite: 'accumulate' });
anim.pause();
- anim.currentTime = anim.effect.timing.duration / 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).marginLeft, '15px',
'Animated margin-left style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration * 2;
assert_equals(getComputedStyle(div).marginLeft, '50px', // 10px + 20px + 20px
'Animated margin-left style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
+ anim.currentTime += anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).marginLeft, '55px', // (50px + 60px) * 0.5
'Animated margin-left style at 50s of the third iteration');
}, 'iteration composition starts with non-zero value animation');
@@ -777,15 +777,15 @@
iterationComposite: 'accumulate' });
anim.pause();
- anim.currentTime = anim.effect.timing.duration / 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).marginLeft,
'0px',
'Animated margin-left style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
+ anim.currentTime = anim.effect.getComputedTiming().duration * 2;
assert_equals(getComputedStyle(div).marginLeft,
'-10px', // 10px + -10px + -10px
'Animated margin-left style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
+ anim.currentTime += anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).marginLeft,
'-20px', // (-10px + -30px) * 0.5
'Animated margin-left style at 50s of the third iteration');
@@ -801,17 +801,22 @@
anim.pause();
anim.currentTime =
- anim.effect.timing.duration * 2 + anim.effect.timing.duration / 2;
+ anim.effect.getComputedTiming().duration * 2 +
+ anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).marginLeft, '25px',
'Animated style at 50s of the third iteration');
// double its duration.
- anim.effect.timing.duration = anim.effect.timing.duration * 2;
+ anim.effect.updateTiming({
+ duration: anim.effect.getComputedTiming().duration * 2
+ });
assert_equals(getComputedStyle(div).marginLeft, '12.5px',
'Animated style at 25s of the first iteration');
// half of original.
- anim.effect.timing.duration = anim.effect.timing.duration / 4;
+ anim.effect.updateTiming({
+ duration: anim.effect.getComputedTiming().duration / 4
+ });
assert_equals(getComputedStyle(div).marginLeft, '50px',
'Animated style at 50s of the fourth iteration');
}, 'duration changes with an iteration composition operation of accumulate');
diff --git a/web-animations/interfaces/Animatable/animate.html b/web-animations/interfaces/Animatable/animate.html
index 36c4ee1..c7b7b25 100644
--- a/web-animations/interfaces/Animatable/animate.html
+++ b/web-animations/interfaces/Animatable/animate.html
@@ -8,6 +8,8 @@
<script src="../../resources/easing-tests.js"></script>
<script src="../../resources/keyframe-utils.js"></script>
<script src="../../resources/keyframe-tests.js"></script>
+<script src="../../resources/timing-utils.js"></script>
+<script src="../../resources/timing-tests.js"></script>
<body>
<div id="log"></div>
<iframe width="10" height="10" id="iframe"></iframe>
@@ -17,8 +19,7 @@
// Tests on Element
test(t => {
- const div = createDiv(t);
- const anim = div.animate(null);
+ const anim = createDiv(t).animate(null);
assert_class_string(anim, 'Animation', 'Returned object is an Animation');
}, 'Element.animate() creates an Animation object');
@@ -57,26 +58,9 @@
}, 'Element.animate() creates an Animation object with a KeyframeEffect'
+ ' that is created in the relevant realm of the target element');
-test(t => {
- const iframe = window.frames[0];
- const div = createDiv(t, iframe.document);
- const anim = div.animate(null);
- assert_equals(Object.getPrototypeOf(anim.effect.timing),
- iframe.AnimationEffectTiming.prototype,
- 'The prototype of the created AnimationEffectTiming is that'
- + ' defined on the relevant global for the target element');
- assert_not_equals(Object.getPrototypeOf(anim.effect.timing),
- AnimationEffectTiming.prototype,
- 'The prototype of the created AnimationEffectTiming is NOT'
- + ' that of the current global');
-}, 'Element.animate() creates an Animation object with a KeyframeEffect'
- + ' whose AnimationEffectTiming object is created in the relevant realm'
- + ' of the target element');
-
for (const subtest of gEmptyKeyframeListTests) {
test(t => {
- const div = createDiv(t);
- const anim = div.animate(subtest, 2000);
+ const anim = createDiv(t).animate(subtest, 2000);
assert_not_equals(anim, null);
}, 'Element.animate() accepts empty keyframe lists ' +
`(input: ${JSON.stringify(subtest)})`);
@@ -84,8 +68,7 @@
for (const subtest of gKeyframesTests) {
test(t => {
- const div = createDiv(t);
- const anim = div.animate(subtest.input, 2000);
+ const anim = createDiv(t).animate(subtest.input, 2000);
assert_frame_lists_equal(anim.effect.getKeyframes(), subtest.output);
}, `Element.animate() accepts ${subtest.desc}`);
}
@@ -99,54 +82,101 @@
}, `Element.animate() does not accept ${subtest.desc}`);
}
+test(t => {
+ const anim = createDiv(t).animate(null, 2000);
+ assert_equals(anim.effect.getTiming().duration, 2000);
+ assert_default_timing_except(anim.effect, ['duration']);
+}, 'Element.animate() accepts a double as an options argument');
+
+test(t => {
+ const anim = createDiv(t).animate(null,
+ { duration: Infinity, fill: 'forwards' });
+ assert_equals(anim.effect.getTiming().duration, Infinity);
+ assert_equals(anim.effect.getTiming().fill, 'forwards');
+ assert_default_timing_except(anim.effect, ['duration', 'fill']);
+}, 'Element.animate() accepts a KeyframeAnimationOptions argument');
+
+test(t => {
+ const anim = createDiv(t).animate(null);
+ assert_default_timing_except(anim.effect, []);
+}, 'Element.animate() accepts an absent options argument');
+
+for (const invalid of gBadDelayValues) {
+ test(t => {
+ assert_throws(new TypeError, () => {
+ createDiv(t).animate(null, { delay: invalid });
+ });
+ }, `Element.animate() does not accept invalid delay value: ${invalid}`);
+}
+
+test(t => {
+ const anim = createDiv(t).animate(null, { duration: 'auto' });
+ assert_equals(anim.effect.getTiming().duration, 'auto', 'set duration \'auto\'');
+ assert_equals(anim.effect.getComputedTiming().duration, 0,
+ 'getComputedTiming() after set duration \'auto\'');
+}, 'Element.animate() accepts a duration of \'auto\' using a dictionary'
+ + ' object');
+
+for (const invalid of gBadDurationValues) {
+ if (typeof invalid === 'string' && !isNaN(parseFloat(invalid))) {
+ continue;
+ }
+ test(t => {
+ assert_throws(new TypeError, () => {
+ createDiv(t).animate(null, invalid);
+ });
+ }, 'Element.animate() does not accept invalid duration value: '
+ + (typeof invalid === 'string' ? `"${invalid}"` : invalid));
+}
+
+for (const invalid of gBadDurationValues) {
+ test(t => {
+ assert_throws(new TypeError, () => {
+ createDiv(t).animate(null, { duration: invalid });
+ });
+ }, 'Element.animate() does not accept invalid duration value: '
+ + (typeof invalid === 'string' ? `"${invalid}"` : invalid)
+ + ' using a dictionary object');
+}
+
for (const invalidEasing of gInvalidEasings) {
test(t => {
- const div = createDiv(t);
assert_throws(new TypeError, () => {
- div.animate({ easing: invalidEasing }, 2000);
+ createDiv(t).animate({ easing: invalidEasing }, 2000);
});
}, `Element.animate() does not accept invalid easing: '${invalidEasing}'`);
}
-test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
- assert_equals(anim.effect.timing.duration, 2000);
- // Also check that unspecified parameters receive their default values
- assert_equals(anim.effect.timing.fill, 'auto');
-}, 'Element.animate() accepts a double as an options argument');
+for (const invalid of gBadIterationStartValues) {
+ test(t => {
+ assert_throws(new TypeError, () => {
+ createDiv(t).animate(null, { iterationStart: invalid });
+ });
+ }, 'Element.animate() does not accept invalid iterationStart value: ' +
+ invalid);
+}
+
+for (const invalid of gBadIterationsValues) {
+ test(t => {
+ assert_throws(new TypeError, () => {
+ createDiv(t).animate(null, { iterations: invalid });
+ });
+ }, 'Element.animate() does not accept invalid iterations value: ' +
+ invalid);
+}
test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] },
- { duration: Infinity, fill: 'forwards' });
- assert_equals(anim.effect.timing.duration, Infinity);
- assert_equals(anim.effect.timing.fill, 'forwards');
- // Also check that unspecified parameters receive their default values
- assert_equals(anim.effect.timing.direction, 'normal');
-}, 'Element.animate() accepts a KeyframeAnimationOptions argument');
-
-test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] });
- assert_equals(anim.effect.timing.duration, 'auto');
-}, 'Element.animate() accepts an absent options argument');
-
-test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
+ const anim = createDiv(t).animate(null, 2000);
assert_equals(anim.id, '');
}, 'Element.animate() correctly sets the id attribute when no id is specified');
test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] }, { id: 'test' });
+ const anim = createDiv(t).animate(null, { id: 'test' });
assert_equals(anim.id, 'test');
}, 'Element.animate() correctly sets the id attribute');
test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
+ const anim = createDiv(t).animate(null, 2000);
assert_equals(anim.timeline, document.timeline);
}, 'Element.animate() correctly sets the Animation\'s timeline');
@@ -157,7 +187,7 @@
iframe.addEventListener('load', t.step_func(() => {
const div = createDiv(t, iframe.contentDocument);
- const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
+ const anim = div.animate(null, 2000);
assert_equals(anim.timeline, iframe.contentDocument.timeline);
iframe.remove();
t.done();
@@ -168,8 +198,7 @@
'triggered on an element in a different document');
test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
+ const anim = createDiv(t).animate(null, 2000);
assert_equals(anim.playState, 'running');
}, 'Element.animate() calls play on the Animation');
diff --git a/web-animations/interfaces/Animatable/getAnimations.html b/web-animations/interfaces/Animatable/getAnimations.html
index d05e2aa..182b5cb 100644
--- a/web-animations/interfaces/Animatable/getAnimations.html
+++ b/web-animations/interfaces/Animatable/getAnimations.html
@@ -75,12 +75,14 @@
assert_array_equals(div.getAnimations(), [],
'Animation should not be returned when it is finished');
- animation.effect.timing.duration += 100 * MS_PER_SEC;
+ animation.effect.updateTiming({
+ duration: animation.effect.getTiming().duration + 100 * MS_PER_SEC,
+ });
assert_array_equals(div.getAnimations(), [animation],
'Animation should be returned after extending the'
+ ' duration');
- animation.effect.timing.duration = 0;
+ animation.effect.updateTiming({ duration: 0 });
assert_array_equals(div.getAnimations(), [],
'Animation should not be returned after setting the'
+ ' duration to zero');
@@ -91,13 +93,13 @@
const div = createDiv(t);
const animation = div.animate(null, 100 * MS_PER_SEC);
- animation.effect.timing.endDelay = -200 * MS_PER_SEC;
+ animation.effect.updateTiming({ endDelay: -200 * MS_PER_SEC });
assert_array_equals(div.getAnimations(), [],
'Animation should not be returned after setting a'
+ ' negative end delay such that the end time is less'
+ ' than the current time');
- animation.effect.timing.endDelay = 100 * MS_PER_SEC;
+ animation.effect.updateTiming({ endDelay: 100 * MS_PER_SEC });
assert_array_equals(div.getAnimations(), [animation],
'Animation should be returned after setting a positive'
+ ' end delay such that the end time is more than the'
@@ -113,17 +115,17 @@
assert_array_equals(div.getAnimations(), [],
'Animation should not be returned when it is finished');
- animation.effect.timing.iterations = 10;
+ animation.effect.updateTiming({ iterations: 10 });
assert_array_equals(div.getAnimations(), [animation],
'Animation should be returned after inreasing the'
+ ' number of iterations');
- animation.effect.timing.iterations = 0;
+ animation.effect.updateTiming({ iterations: 0 });
assert_array_equals(div.getAnimations(), [],
'Animations should not be returned after setting the'
+ ' iteration count to zero');
- animation.effect.timing.iterations = Infinity;
+ animation.effect.updateTiming({ iterations: Infinity });
assert_array_equals(div.getAnimations(), [animation],
'Animation should be returned after inreasing the'
+ ' number of iterations to infinity');
diff --git a/web-animations/interfaces/Animation/cancel.html b/web-animations/interfaces/Animation/cancel.html
index be1bb5d..711a339 100644
--- a/web-animations/interfaces/Animation/cancel.html
+++ b/web-animations/interfaces/Animation/cancel.html
@@ -29,7 +29,7 @@
const div = createDiv(t);
const animation = div.animate({ marginLeft: ['100px', '200px'] },
100 * MS_PER_SEC);
- animation.effect.timing.easing = 'linear';
+ animation.effect.updateTiming({ easing: 'linear' });
animation.cancel();
assert_equals(getComputedStyle(div).marginLeft, '0px',
'margin-left style is not animated after cancelling');
diff --git a/web-animations/interfaces/Animation/constructor.html b/web-animations/interfaces/Animation/constructor.html
index c00c66e..fcbaab1 100644
--- a/web-animations/interfaces/Animation/constructor.html
+++ b/web-animations/interfaces/Animation/constructor.html
@@ -14,7 +14,7 @@
const gTarget = document.getElementById('target');
function createEffect() {
- return new KeyframeEffectReadOnly(gTarget, { opacity: [0, 1] });
+ return new KeyframeEffect(gTarget, { opacity: [0, 1] });
}
function createNull() {
@@ -82,10 +82,9 @@
}
test(t => {
- const effect = new KeyframeEffectReadOnly(null,
- { left: ['10px', '20px'] },
- { duration: 10000,
- fill: 'forwards' });
+ const effect = new KeyframeEffect(null,
+ { left: ['10px', '20px'] },
+ { duration: 10000, fill: 'forwards' });
const anim = new Animation(effect, document.timeline);
anim.pause();
assert_equals(effect.getComputedTiming().progress, 0.0);
@@ -100,7 +99,7 @@
iframe.addEventListener('load', t.step_func(() => {
const div = createDiv(t, iframe.contentDocument);
- const effect = new KeyframeEffectReadOnly(div, null, 10000);
+ const effect = new KeyframeEffect(div, null, 10000);
const anim = new Animation(effect);
assert_equals(anim.timeline, document.timeline);
iframe.remove();
diff --git a/web-animations/interfaces/Animation/effect.html b/web-animations/interfaces/Animation/effect.html
index 175fc31..cb8bc09 100644
--- a/web-animations/interfaces/Animation/effect.html
+++ b/web-animations/interfaces/Animation/effect.html
@@ -14,7 +14,7 @@
const anim = new Animation();
assert_equals(anim.effect, null, 'initial effect is null');
- const newEffect = new KeyframeEffectReadOnly(createDiv(t), null);
+ const newEffect = new KeyframeEffect(createDiv(t), null);
anim.effect = newEffect;
assert_equals(anim.effect, newEffect, 'new effect is set');
}, 'effect is set correctly.');
diff --git a/web-animations/interfaces/Animation/finished.html b/web-animations/interfaces/Animation/finished.html
index 79700f3..563d4ba 100644
--- a/web-animations/interfaces/Animation/finished.html
+++ b/web-animations/interfaces/Animation/finished.html
@@ -189,7 +189,7 @@
animation.currentTime = HALF_DUR;
return animation.ready.then(() => {
currentTimeBeforeShortening = animation.currentTime;
- animation.effect.timing.duration = QUARTER_DUR;
+ animation.effect.updateTiming({ duration: QUARTER_DUR });
// Below we use gotNextFrame to check that shortening of the animation
// duration causes the finished promise to resolve, rather than it just
// getting resolved on the next animation frame. This relies on the fact
@@ -206,7 +206,7 @@
assert_equals(animation.currentTime, currentTimeBeforeShortening,
'currentTime should be unchanged when duration shortened');
const previousFinishedPromise = animation.finished;
- animation.effect.timing.duration = 100 * MS_PER_SEC;
+ animation.effect.updateTiming({ duration: 100 * MS_PER_SEC });
assert_not_equals(animation.finished, previousFinishedPromise,
'Finished promise should change after lengthening the ' +
'duration causes the animation to become active');
diff --git a/web-animations/interfaces/Animation/idlharness.html b/web-animations/interfaces/Animation/idlharness.html
index bf7c9f3..20fca13 100644
--- a/web-animations/interfaces/Animation/idlharness.html
+++ b/web-animations/interfaces/Animation/idlharness.html
@@ -10,11 +10,11 @@
<script type="text/plain" id="Animation-IDL">
enum AnimationPlayState { "idle", "pending", "running", "paused", "finished" };
-[Constructor (optional AnimationEffectReadOnly? effect = null,
+[Constructor (optional AnimationEffect? effect = null,
optional AnimationTimeline? timeline)]
interface Animation : EventTarget {
attribute DOMString id;
- attribute AnimationEffectReadOnly? effect;
+ attribute AnimationEffect? effect;
attribute AnimationTimeline? timeline;
attribute double? startTime;
attribute double? currentTime;
diff --git a/web-animations/interfaces/AnimationEffectTiming/getComputedTiming.html b/web-animations/interfaces/AnimationEffect/getComputedTiming.html
similarity index 99%
rename from web-animations/interfaces/AnimationEffectTiming/getComputedTiming.html
rename to web-animations/interfaces/AnimationEffect/getComputedTiming.html
index 9a92880..e0e4fc2 100644
--- a/web-animations/interfaces/AnimationEffectTiming/getComputedTiming.html
+++ b/web-animations/interfaces/AnimationEffect/getComputedTiming.html
@@ -195,7 +195,5 @@
}, `getComputedTiming().endTime for ${stest.desc}`);
}
-
-done();
</script>
</body>
diff --git a/web-animations/interfaces/AnimationEffect/updateTiming.html b/web-animations/interfaces/AnimationEffect/updateTiming.html
new file mode 100644
index 0000000..746f0d7
--- /dev/null
+++ b/web-animations/interfaces/AnimationEffect/updateTiming.html
@@ -0,0 +1,475 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>AnimationEffect.updateTiming</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations-1/#dom-animationeffect-updatetiming">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<script src="../../resources/easing-tests.js"></script>
+<script src="../../resources/timing-tests.js"></script>
+<body>
+<div id="log"></div>
+<script>
+'use strict';
+
+// ------------------------------
+// delay
+// ------------------------------
+
+test(t => {
+ const anim = createDiv(t).animate(null, 100);
+ anim.effect.updateTiming({ delay: 100 });
+ assert_equals(anim.effect.getTiming().delay, 100, 'set delay 100');
+ assert_equals(anim.effect.getComputedTiming().delay, 100,
+ 'getComputedTiming() after set delay 100');
+}, 'Allows setting the delay to a positive number');
+
+test(t => {
+ const anim = createDiv(t).animate(null, 100);
+ anim.effect.updateTiming({ delay: -100 });
+ assert_equals(anim.effect.getTiming().delay, -100, 'set delay -100');
+ assert_equals(anim.effect.getComputedTiming().delay, -100,
+ 'getComputedTiming() after set delay -100');
+}, 'Allows setting the delay to a negative number');
+
+test(t => {
+ const anim = createDiv(t).animate(null, 100);
+ anim.effect.updateTiming({ delay: 100 });
+ assert_equals(anim.effect.getComputedTiming().progress, null);
+ assert_equals(anim.effect.getComputedTiming().currentIteration, null);
+}, 'Allows setting the delay of an animation in progress: positive delay that'
+ + ' causes the animation to be no longer in-effect');
+
+test(t => {
+ const anim = createDiv(t).animate(null, { fill: 'both', duration: 100 });
+ anim.effect.updateTiming({ delay: -50 });
+ assert_equals(anim.effect.getComputedTiming().progress, 0.5);
+}, 'Allows setting the delay of an animation in progress: negative delay that'
+ + ' seeks into the active interval');
+
+test(t => {
+ const anim = createDiv(t).animate(null, { fill: 'both', duration: 100 });
+ anim.effect.updateTiming({ delay: -100 });
+ assert_equals(anim.effect.getComputedTiming().progress, 1);
+ assert_equals(anim.effect.getComputedTiming().currentIteration, 0);
+}, 'Allows setting the delay of an animation in progress: large negative delay'
+ + ' that causes the animation to be finished');
+
+for (const invalid of gBadDelayValues) {
+ test(t => {
+ const anim = createDiv(t).animate(null);
+ assert_throws({ name: 'TypeError' }, () => {
+ anim.effect.updateTiming({ delay: invalid });
+ });
+ }, `Throws when setting invalid delay value: ${invalid}`);
+}
+
+
+// ------------------------------
+// endDelay
+// ------------------------------
+
+test(t => {
+ const anim = createDiv(t).animate(null, 2000);
+ anim.effect.updateTiming({ endDelay: 123.45 });
+ assert_time_equals_literal(anim.effect.getTiming().endDelay, 123.45,
+ 'set endDelay 123.45');
+ assert_time_equals_literal(anim.effect.getComputedTiming().endDelay, 123.45,
+ 'getComputedTiming() after set endDelay 123.45');
+}, 'Allows setting the endDelay to a positive number');
+
+test(t => {
+ const anim = createDiv(t).animate(null, 2000);
+ anim.effect.updateTiming({ endDelay: -1000 });
+ assert_equals(anim.effect.getTiming().endDelay, -1000, 'set endDelay -1000');
+ assert_equals(anim.effect.getComputedTiming().endDelay, -1000,
+ 'getComputedTiming() after set endDelay -1000');
+}, 'Allows setting the endDelay to a negative number');
+
+test(t => {
+ const anim = createDiv(t).animate(null, 2000);
+ assert_throws({ name: 'TypeError' }, () => {
+ anim.effect.updateTiming({ endDelay: Infinity });
+ });
+}, 'Throws when setting the endDelay to infinity');
+
+test(t => {
+ const anim = createDiv(t).animate(null, 2000);
+ assert_throws({ name: 'TypeError' }, () => {
+ anim.effect.updateTiming({ endDelay: -Infinity });
+ });
+}, 'Throws when setting the endDelay to negative infinity');
+
+
+// ------------------------------
+// fill
+// ------------------------------
+
+for (const fill of ['none', 'forwards', 'backwards', 'both']) {
+ test(t => {
+ const anim = createDiv(t).animate(null, 100);
+ anim.effect.updateTiming({ fill });
+ assert_equals(anim.effect.getTiming().fill, fill, 'set fill ' + fill);
+ assert_equals(anim.effect.getComputedTiming().fill, fill,
+ 'getComputedTiming() after set fill ' + fill);
+ }, `Allows setting the fill to '${fill}'`);
+}
+
+
+// ------------------------------
+// iterationStart
+// ------------------------------
+
+test(t => {
+ const anim = createDiv(t).animate(null,
+ { iterationStart: 0.2,
+ iterations: 1,
+ fill: 'both',
+ duration: 100,
+ delay: 1 });
+ anim.effect.updateTiming({ iterationStart: 2.5 });
+ assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.5);
+ assert_equals(anim.effect.getComputedTiming().currentIteration, 2);
+}, 'Allows setting the iterationStart of an animation in progress:'
+ + ' backwards-filling');
+
+test(t => {
+ const anim = createDiv(t).animate(null,
+ { iterationStart: 0.2,
+ iterations: 1,
+ fill: 'both',
+ duration: 100,
+ delay: 0 });
+ anim.effect.updateTiming({ iterationStart: 2.5 });
+ assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.5);
+ assert_equals(anim.effect.getComputedTiming().currentIteration, 2);
+}, 'Allows setting the iterationStart of an animation in progress:'
+ + ' active phase');
+
+test(t => {
+ const anim = createDiv(t).animate(null,
+ { iterationStart: 0.2,
+ iterations: 1,
+ fill: 'both',
+ duration: 100,
+ delay: 0 });
+ anim.finish();
+ anim.effect.updateTiming({ iterationStart: 2.5 });
+ assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.5);
+ assert_equals(anim.effect.getComputedTiming().currentIteration, 3);
+}, 'Allows setting the iterationStart of an animation in progress:'
+ + ' forwards-filling');
+
+for (const invalid of gBadIterationStartValues) {
+ test(t => {
+ const anim = createDiv(t).animate(null);
+ assert_throws({ name: 'TypeError' }, () => {
+ anim.effect.updateTiming({ iterationStart: invalid });
+ }, `setting ${invalid}`);
+ }, `Throws when setting invalid iterationStart value: ${invalid}`);
+}
+
+// ------------------------------
+// iterations
+// ------------------------------
+
+test(t => {
+ const anim = createDiv(t).animate(null, 2000);
+ anim.effect.updateTiming({ iterations: 2 });
+ assert_equals(anim.effect.getTiming().iterations, 2, 'set duration 2');
+ assert_equals(anim.effect.getComputedTiming().iterations, 2,
+ 'getComputedTiming() after set iterations 2');
+}, 'Allows setting iterations to a double value');
+
+test(t => {
+ const anim = createDiv(t).animate(null, 2000);
+ anim.effect.updateTiming({ iterations: Infinity });
+ assert_equals(anim.effect.getTiming().iterations, Infinity,
+ 'set duration Infinity');
+ assert_equals(anim.effect.getComputedTiming().iterations, Infinity,
+ 'getComputedTiming() after set iterations Infinity');
+}, 'Allows setting iterations to infinity');
+
+for (const invalid of gBadIterationsValues) {
+ test(t => {
+ const anim = createDiv(t).animate(null);
+ assert_throws({ name: 'TypeError' }, () => {
+ anim.effect.updateTiming({ iterations: invalid });
+ });
+ }, `Throws when setting invalid iterations value: ${invalid}`);
+}
+
+test(t => {
+ const anim = createDiv(t).animate(null, { duration: 100000, fill: 'both' });
+
+ anim.finish();
+
+ assert_equals(anim.effect.getComputedTiming().progress, 1,
+ 'progress when animation is finished');
+ assert_equals(anim.effect.getComputedTiming().currentIteration, 0,
+ 'current iteration when animation is finished');
+
+ anim.effect.updateTiming({ iterations: 2 });
+
+ assert_time_equals_literal(anim.effect.getComputedTiming().progress,
+ 0,
+ 'progress after adding an iteration');
+ assert_time_equals_literal(anim.effect.getComputedTiming().currentIteration,
+ 1,
+ 'current iteration after adding an iteration');
+
+ anim.effect.updateTiming({ iterations: 0 });
+
+ assert_equals(anim.effect.getComputedTiming().progress, 0,
+ 'progress after setting iterations to zero');
+ assert_equals(anim.effect.getComputedTiming().currentIteration, 0,
+ 'current iteration after setting iterations to zero');
+
+ anim.effect.updateTiming({ iterations: Infinity });
+
+ assert_equals(anim.effect.getComputedTiming().progress, 0,
+ 'progress after setting iterations to Infinity');
+ assert_equals(anim.effect.getComputedTiming().currentIteration, 1,
+ 'current iteration after setting iterations to Infinity');
+}, 'Allows setting the iterations of an animation in progress');
+
+
+// ------------------------------
+// duration
+// ------------------------------
+
+for (const duration of gGoodDurationValues) {
+ test(t => {
+ const anim = createDiv(t).animate(null, 2000);
+ anim.effect.updateTiming({ duration: duration.specified });
+ if (typeof duration.specified === 'number') {
+ assert_time_equals_literal(anim.effect.getTiming().duration,
+ duration.specified,
+ 'Updates specified duration');
+ } else {
+ assert_equals(anim.effect.getTiming().duration, duration.specified,
+ 'Updates specified duration');
+ }
+ assert_time_equals_literal(anim.effect.getComputedTiming().duration,
+ duration.computed,
+ 'Updates computed duration');
+ }, `Allows setting the duration to ${duration.specified}`);
+}
+
+for (const invalid of gBadDurationValues) {
+ test(t => {
+ assert_throws(new TypeError, () => {
+ createDiv(t).animate(null, { duration: invalid });
+ });
+ }, 'Throws when setting invalid duration: '
+ + (typeof invalid === 'string' ? `"${invalid}"` : invalid));
+}
+
+test(t => {
+ const anim = createDiv(t).animate(null, { duration: 100000, fill: 'both' });
+ anim.finish();
+ assert_equals(anim.effect.getComputedTiming().progress, 1,
+ 'progress when animation is finished');
+ anim.effect.updateTiming({ duration: anim.effect.getTiming().duration * 2 });
+ assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.5,
+ 'progress after doubling the duration');
+ anim.effect.updateTiming({ duration: 0 });
+ assert_equals(anim.effect.getComputedTiming().progress, 1,
+ 'progress after setting duration to zero');
+ anim.effect.updateTiming({ duration: 'auto' });
+ assert_equals(anim.effect.getComputedTiming().progress, 1,
+ 'progress after setting duration to \'auto\'');
+}, 'Allows setting the duration of an animation in progress');
+
+promise_test(t => {
+ const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
+ return anim.ready.then(() => {
+ const originalStartTime = anim.startTime;
+ const originalCurrentTime = anim.currentTime;
+ assert_time_equals_literal(
+ anim.effect.getComputedTiming().duration,
+ 100 * MS_PER_SEC,
+ 'Initial duration should be as set on KeyframeEffect'
+ );
+
+ anim.effect.updateTiming({ duration: 200 * MS_PER_SEC });
+ assert_time_equals_literal(
+ anim.effect.getComputedTiming().duration,
+ 200 * MS_PER_SEC,
+ 'Effect duration should have been updated'
+ );
+ assert_times_equal(anim.startTime, originalStartTime,
+ 'startTime should be unaffected by changing effect ' +
+ 'duration');
+ assert_times_equal(anim.currentTime, originalCurrentTime,
+ 'currentTime should be unaffected by changing effect ' +
+ 'duration');
+ });
+}, 'Allows setting the duration of an animation in progress such that the' +
+ ' the start and current time do not change');
+
+
+// ------------------------------
+// direction
+// ------------------------------
+
+test(t => {
+ const anim = createDiv(t).animate(null, 2000);
+
+ const directions = ['normal', 'reverse', 'alternate', 'alternate-reverse'];
+ for (const direction of directions) {
+ anim.effect.updateTiming({ direction: direction });
+ assert_equals(anim.effect.getTiming().direction, direction,
+ `set direction to ${direction}`);
+ }
+}, 'Allows setting the direction to each of the possible keywords');
+
+test(t => {
+ const anim = createDiv(t).animate(null, {
+ duration: 10000,
+ direction: 'normal',
+ });
+ anim.currentTime = 7000;
+ assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.7,
+ 'progress before updating direction');
+
+ anim.effect.updateTiming({ direction: 'reverse' });
+
+ assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.3,
+ 'progress after updating direction');
+}, 'Allows setting the direction of an animation in progress from \'normal\' to'
+ + ' \'reverse\'');
+
+test(t => {
+ const anim = createDiv(t).animate(null,
+ { duration: 10000, direction: 'normal' });
+ assert_equals(anim.effect.getComputedTiming().progress, 0,
+ 'progress before updating direction');
+
+ anim.effect.updateTiming({ direction: 'reverse' });
+
+ assert_equals(anim.effect.getComputedTiming().progress, 1,
+ 'progress after updating direction');
+}, 'Allows setting the direction of an animation in progress from \'normal\' to'
+ + ' \'reverse\' while at start of active interval');
+
+test(t => {
+ const anim = createDiv(t).animate(null,
+ { fill: 'backwards',
+ duration: 10000,
+ delay: 10000,
+ direction: 'normal' });
+ assert_equals(anim.effect.getComputedTiming().progress, 0,
+ 'progress before updating direction');
+
+ anim.effect.updateTiming({ direction: 'reverse' });
+
+ assert_equals(anim.effect.getComputedTiming().progress, 1,
+ 'progress after updating direction');
+}, 'Allows setting the direction of an animation in progress from \'normal\' to'
+ + ' \'reverse\' while filling backwards');
+
+test(t => {
+ const anim = createDiv(t).animate(null,
+ { iterations: 2,
+ duration: 10000,
+ direction: 'normal' });
+ anim.currentTime = 17000;
+ assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.7,
+ 'progress before updating direction');
+
+ anim.effect.updateTiming({ direction: 'alternate' });
+
+ assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.3,
+ 'progress after updating direction');
+}, 'Allows setting the direction of an animation in progress from \'normal\' to'
+ + ' \'alternate\'');
+
+test(t => {
+ const anim = createDiv(t).animate(null,
+ { iterations: 2,
+ duration: 10000,
+ direction: 'alternate' });
+ anim.currentTime = 17000;
+ assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.3,
+ 'progress before updating direction');
+
+ anim.effect.updateTiming({ direction: 'alternate-reverse' });
+
+ assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.7,
+ 'progress after updating direction');
+}, 'Allows setting the direction of an animation in progress from \'alternate\''
+ + ' to \'alternate-reverse\'');
+
+
+// ------------------------------
+// easing
+// ------------------------------
+
+function assert_progress(animation, currentTime, easingFunction) {
+ animation.currentTime = currentTime;
+ const portion = currentTime / animation.effect.getTiming().duration;
+ assert_approx_equals(animation.effect.getComputedTiming().progress,
+ easingFunction(portion),
+ 0.01,
+ 'The progress of the animation should be approximately'
+ + ` ${easingFunction(portion)} at ${currentTime}ms`);
+}
+
+for (const options of gEasingTests) {
+ test(t => {
+ const target = createDiv(t);
+ const anim = target.animate(null,
+ { duration: 1000 * MS_PER_SEC,
+ fill: 'forwards' });
+ anim.effect.updateTiming({ easing: options.easing });
+ assert_equals(anim.effect.getTiming().easing,
+ options.serialization || options.easing);
+
+ const easing = options.easingFunction;
+ assert_progress(anim, 0, easing);
+ assert_progress(anim, 250 * MS_PER_SEC, easing);
+ assert_progress(anim, 500 * MS_PER_SEC, easing);
+ assert_progress(anim, 750 * MS_PER_SEC, easing);
+ assert_progress(anim, 1000 * MS_PER_SEC, easing);
+ }, `Allows setting the easing to a ${options.desc}`);
+}
+
+for (const easing of gRoundtripEasings) {
+ test(t => {
+ const anim = createDiv(t).animate(null);
+ anim.effect.updateTiming({ easing: easing });
+ assert_equals(anim.effect.getTiming().easing, easing);
+ }, `Updates the specified value when setting the easing to '${easing}'`);
+}
+
+test(t => {
+ const delay = 1000 * MS_PER_SEC;
+
+ const target = createDiv(t);
+ const anim = target.animate(null,
+ { duration: 1000 * MS_PER_SEC,
+ fill: 'both',
+ delay: delay,
+ easing: 'steps(2, start)' });
+
+ anim.effect.updateTiming({ easing: 'steps(2, end)' });
+ assert_equals(anim.effect.getComputedTiming().progress, 0,
+ 'easing replace to steps(2, end) at before phase');
+
+ anim.currentTime = delay + 750 * MS_PER_SEC;
+ assert_equals(anim.effect.getComputedTiming().progress, 0.5,
+ 'change currentTime to active phase');
+
+ anim.effect.updateTiming({ easing: 'steps(2, start)' });
+ assert_equals(anim.effect.getComputedTiming().progress, 1,
+ 'easing replace to steps(2, start) at active phase');
+
+ anim.currentTime = delay + 1500 * MS_PER_SEC;
+ anim.effect.updateTiming({ easing: 'steps(2, end)' });
+ assert_equals(anim.effect.getComputedTiming().progress, 1,
+ 'easing replace to steps(2, end) again at after phase');
+}, 'Allows setting the easing of an animation in progress');
+
+</script>
+</body>
diff --git a/web-animations/interfaces/AnimationEffectTiming/delay.html b/web-animations/interfaces/AnimationEffectTiming/delay.html
deleted file mode 100644
index 41f099b..0000000
--- a/web-animations/interfaces/AnimationEffectTiming/delay.html
+++ /dev/null
@@ -1,78 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>AnimationEffectTiming.delay</title>
-<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animationeffecttiming-delay">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-<body>
-<div id="log"></div>
-<script>
-'use strict';
-
-test(t => {
- const anim = createDiv(t).animate(null);
- assert_equals(anim.effect.timing.delay, 0);
-}, 'Has the default value 0');
-
-test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] }, 100);
- anim.effect.timing.delay = 100;
- assert_equals(anim.effect.timing.delay, 100, 'set delay 100');
- assert_equals(anim.effect.getComputedTiming().delay, 100,
- 'getComputedTiming() after set delay 100');
-}, 'Can be set to a positive number');
-
-test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] }, 100);
- anim.effect.timing.delay = -100;
- assert_equals(anim.effect.timing.delay, -100, 'set delay -100');
- assert_equals(anim.effect.getComputedTiming().delay, -100,
- 'getComputedTiming() after set delay -100');
-}, 'Can be set to a negative number');
-
-test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] }, 100);
- anim.effect.timing.delay = 100;
- assert_equals(anim.effect.getComputedTiming().progress, null);
- assert_equals(anim.effect.getComputedTiming().currentIteration, null);
-}, 'Can set a positive delay on an animation without a backwards fill to'
- + ' make it no longer active');
-
-test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] },
- { fill: 'both',
- duration: 100 });
- anim.effect.timing.delay = -50;
- assert_equals(anim.effect.getComputedTiming().progress, 0.5);
-}, 'Can set a negative delay to seek into the active interval');
-
-test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] },
- { fill: 'both',
- duration: 100 });
- anim.effect.timing.delay = -100;
- assert_equals(anim.effect.getComputedTiming().progress, 1);
- assert_equals(anim.effect.getComputedTiming().currentIteration, 0);
-}, 'Can set a large negative delay to finishing an animation');
-
-test(t => {
- const div = createDiv(t);
- const anim = div.animate(null);
- for (let invalid of [NaN, Infinity]) {
- assert_throws({ name: 'TypeError' }, () => {
- anim.effect.timing.delay = invalid;
- }, `setting ${invalid}`);
- assert_throws({ name: 'TypeError' }, () => {
- div.animate({}, { delay: invalid });
- }, `animate() with ${invalid}`);
- }
-}, 'Throws when setting invalid values');
-
-</script>
-</body>
diff --git a/web-animations/interfaces/AnimationEffectTiming/direction.html b/web-animations/interfaces/AnimationEffectTiming/direction.html
deleted file mode 100644
index 3238f5d..0000000
--- a/web-animations/interfaces/AnimationEffectTiming/direction.html
+++ /dev/null
@@ -1,108 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>AnimationEffectTiming.direction</title>
-<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animationeffecttiming-direction">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-<body>
-<div id="log"></div>
-<script>
-'use strict';
-
-test(t => {
- const anim = createDiv(t).animate(null);
- assert_equals(anim.effect.timing.direction, 'normal');
-}, 'Has the default value \'normal\'');
-
-test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
-
- const directions = ['normal', 'reverse', 'alternate', 'alternate-reverse'];
- for (const direction of directions) {
- anim.effect.timing.direction = direction;
- assert_equals(anim.effect.timing.direction, direction,
- `set direction to ${direction}`);
- }
-}, 'Can be set to each of the possible keywords');
-
-test(t => {
- const div = createDiv(t);
- const anim = div.animate(null, { duration: 10000, direction: 'normal' });
- anim.currentTime = 7000;
- assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.7,
- 'progress before updating direction');
-
- anim.effect.timing.direction = 'reverse';
-
- assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.3,
- 'progress after updating direction');
-}, 'Can be changed from \'normal\' to \'reverse\' while in progress');
-
-test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] },
- { duration: 10000,
- direction: 'normal' });
- assert_equals(anim.effect.getComputedTiming().progress, 0,
- 'progress before updating direction');
-
- anim.effect.timing.direction = 'reverse';
-
- assert_equals(anim.effect.getComputedTiming().progress, 1,
- 'progress after updating direction');
-}, 'Can be changed from \'normal\' to \'reverse\' while at start of active'
- + ' interval');
-
-test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] },
- { fill: 'backwards',
- duration: 10000,
- delay: 10000,
- direction: 'normal' });
- assert_equals(anim.effect.getComputedTiming().progress, 0,
- 'progress before updating direction');
-
- anim.effect.timing.direction = 'reverse';
-
- assert_equals(anim.effect.getComputedTiming().progress, 1,
- 'progress after updating direction');
-}, 'Can be changed from \'normal\' to \'reverse\' while filling backwards');
-
-test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] },
- { iterations: 2,
- duration: 10000,
- direction: 'normal' });
- anim.currentTime = 17000;
- assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.7,
- 'progress before updating direction');
-
- anim.effect.timing.direction = 'alternate';
-
- assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.3,
- 'progress after updating direction');
-}, 'Can be changed from \'normal\' to \'alternate\' while in progress');
-
-test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] },
- { iterations: 2,
- duration: 10000,
- direction: 'alternate' });
- anim.currentTime = 17000;
- assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.3,
- 'progress before updating direction');
-
- anim.effect.timing.direction = 'alternate-reverse';
-
- assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.7,
- 'progress after updating direction');
-}, 'Can be changed from \'alternate\' to \'alternate-reverse\' while in'
- + ' progress');
-
-</script>
-</body>
diff --git a/web-animations/interfaces/AnimationEffectTiming/duration.html b/web-animations/interfaces/AnimationEffectTiming/duration.html
deleted file mode 100644
index 42913f5..0000000
--- a/web-animations/interfaces/AnimationEffectTiming/duration.html
+++ /dev/null
@@ -1,190 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>AnimationEffectTiming.duration</title>
-<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animationeffecttiming-duration">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-<body>
-<div id="log"></div>
-<script>
-'use strict';
-
-test(t => {
- const anim = createDiv(t).animate(null);
- assert_equals(anim.effect.timing.duration, 'auto');
-}, 'Has the default value \'auto\'');
-
-test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
- anim.effect.timing.duration = 123.45;
- assert_time_equals_literal(anim.effect.timing.duration, 123.45,
- 'set duration 123.45');
- assert_time_equals_literal(anim.effect.getComputedTiming().duration, 123.45,
- 'getComputedTiming() after set duration 123.45');
-}, 'Can be set to a double value');
-
-test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
- anim.effect.timing.duration = 'auto';
- assert_equals(anim.effect.timing.duration, 'auto', 'set duration \'auto\'');
- assert_equals(anim.effect.getComputedTiming().duration, 0,
- 'getComputedTiming() after set duration \'auto\'');
-}, 'Can be set to the string \'auto\'');
-
-test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] }, { duration: 'auto' });
- assert_equals(anim.effect.timing.duration, 'auto', 'set duration \'auto\'');
- assert_equals(anim.effect.getComputedTiming().duration, 0,
- 'getComputedTiming() after set duration \'auto\'');
-}, 'Can be set to \'auto\' using a dictionary object');
-
-test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
- anim.effect.timing.duration = Infinity;
- assert_equals(anim.effect.timing.duration, Infinity, 'set duration Infinity');
- assert_equals(anim.effect.getComputedTiming().duration, Infinity,
- 'getComputedTiming() after set duration Infinity');
-}, 'Can be set to Infinity');
-
-test(t => {
- const div = createDiv(t);
- assert_throws({ name: 'TypeError' }, () => {
- div.animate({ opacity: [ 0, 1 ] }, -1);
- });
-}, 'animate() throws when passed a negative number');
-
-test(t => {
- const div = createDiv(t);
- assert_throws({ name: 'TypeError' }, () => {
- div.animate({ opacity: [ 0, 1 ] }, -Infinity);
- });
-}, 'animate() throws when passed negative Infinity');
-
-test(t => {
- const div = createDiv(t);
- assert_throws({ name: 'TypeError' }, () => {
- div.animate({ opacity: [ 0, 1 ] }, NaN);
- });
-}, 'animate() throws when passed a NaN value');
-
-test(t => {
- const div = createDiv(t);
- assert_throws({ name: 'TypeError' }, () => {
- div.animate({ opacity: [ 0, 1 ] }, { duration: -1 });
- });
-}, 'animate() throws when passed a negative number using a dictionary object');
-
-test(t => {
- const div = createDiv(t);
- assert_throws({ name: 'TypeError' }, () => {
- div.animate({ opacity: [ 0, 1 ] }, { duration: -Infinity });
- });
-}, 'animate() throws when passed negative Infinity using a dictionary object');
-
-test(t => {
- const div = createDiv(t);
- assert_throws({ name: 'TypeError' }, () => {
- div.animate({ opacity: [ 0, 1 ] }, { duration: NaN });
- });
-}, 'animate() throws when passed a NaN value using a dictionary object');
-
-test(t => {
- const div = createDiv(t);
- assert_throws({ name: 'TypeError' }, () => {
- div.animate({ opacity: [ 0, 1 ] }, { duration: 'abc' });
- });
-}, 'animate() throws when passed a string other than \'auto\' using a'
- + ' dictionary object');
-
-test(t => {
- const div = createDiv(t);
- assert_throws({ name: 'TypeError' }, () => {
- div.animate({ opacity: [ 0, 1 ] }, { duration: '100' });
- });
-}, 'animate() throws when passed a string containing a number using a'
- + ' dictionary object');
-
-test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
- assert_throws({ name: 'TypeError' }, () => {
- anim.effect.timing.duration = -1;
- });
-}, 'Throws when setting a negative number');
-
-test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
- assert_throws({ name: 'TypeError' }, () => {
- anim.effect.timing.duration = -Infinity;
- });
-}, 'Throws when setting negative infinity');
-
-test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
- assert_throws({ name: 'TypeError' }, () => {
- anim.effect.timing.duration = NaN;
- });
-}, 'Throws when setting a NaN value');
-
-test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
- assert_throws({ name: 'TypeError' }, () => {
- anim.effect.timing.duration = 'abc';
- });
-}, 'Throws when setting a string other than \'auto\'');
-
-test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
- assert_throws({ name: 'TypeError' }, () => {
- anim.effect.timing.duration = '100';
- });
-}, 'Throws when setting a string containing a number');
-
-promise_test(t => {
- const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
- return anim.ready.then(() => {
- const originalStartTime = anim.startTime;
- const originalCurrentTime = anim.currentTime;
- assert_equals(anim.effect.getComputedTiming().duration, 100 * MS_PER_SEC,
- 'Initial duration should be as set on KeyframeEffect');
-
- anim.effect.timing.duration = 200 * MS_PER_SEC;
- assert_equals(anim.effect.getComputedTiming().duration, 200 * MS_PER_SEC,
- 'Effect duration should have been updated');
- assert_times_equal(anim.startTime, originalStartTime,
- 'startTime should be unaffected by changing effect ' +
- 'duration');
- assert_times_equal(anim.currentTime, originalCurrentTime,
- 'currentTime should be unaffected by changing effect ' +
- 'duration');
- });
-}, 'Extending an effect\'s duration does not change the start or current time');
-
-test(t => {
- const div = createDiv(t);
- const anim = div.animate(null, { duration: 100000, fill: 'both' });
- anim.finish();
- assert_equals(anim.effect.getComputedTiming().progress, 1,
- 'progress when animation is finished');
- anim.effect.timing.duration *= 2;
- assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.5,
- 'progress after doubling the duration');
- anim.effect.timing.duration = 0;
- assert_equals(anim.effect.getComputedTiming().progress, 1,
- 'progress after setting duration to zero');
- anim.effect.timing.duration = 'auto';
- assert_equals(anim.effect.getComputedTiming().progress, 1,
- 'progress after setting duration to \'auto\'');
-}, 'Can be updated while the animation is in progress');
-
-</script>
-</body>
diff --git a/web-animations/interfaces/AnimationEffectTiming/easing.html b/web-animations/interfaces/AnimationEffectTiming/easing.html
deleted file mode 100644
index ec2b239..0000000
--- a/web-animations/interfaces/AnimationEffectTiming/easing.html
+++ /dev/null
@@ -1,96 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>AnimationEffectTiming.easing</title>
-<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animationeffecttiming-easing">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-<script src="../../resources/easing-tests.js"></script>
-<body>
-<div id="log"></div>
-<script>
-'use strict';
-
-test(t => {
- const anim = createDiv(t).animate(null);
- assert_equals(anim.effect.timing.easing, 'linear');
-}, 'Has the default value \'linear\'');
-
-function assert_progress(animation, currentTime, easingFunction) {
- animation.currentTime = currentTime;
- const portion = currentTime / animation.effect.timing.duration;
- assert_approx_equals(animation.effect.getComputedTiming().progress,
- easingFunction(portion),
- 0.01,
- 'The progress of the animation should be approximately'
- + ` ${easingFunction(portion)} at ${currentTime}ms`);
-}
-
-for (const options of gEasingTests) {
- test(t => {
- const target = createDiv(t);
- const anim = target.animate([ { opacity: 0 }, { opacity: 1 } ],
- { duration: 1000 * MS_PER_SEC,
- fill: 'forwards' });
- anim.effect.timing.easing = options.easing;
- assert_equals(anim.effect.timing.easing,
- options.serialization || options.easing);
-
- const easing = options.easingFunction;
- assert_progress(anim, 0, easing);
- assert_progress(anim, 250 * MS_PER_SEC, easing);
- assert_progress(anim, 500 * MS_PER_SEC, easing);
- assert_progress(anim, 750 * MS_PER_SEC, easing);
- assert_progress(anim, 1000 * MS_PER_SEC, easing);
- }, options.desc);
-}
-
-for (const invalidEasing of gInvalidEasings) {
- test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] }, 100 * MS_PER_SEC);
- assert_throws({ name: 'TypeError' },
- () => {
- anim.effect.timing.easing = invalidEasing;
- });
- }, `Throws on invalid easing: '${invalidEasing}'`);
-}
-
-for (const easing of gRoundtripEasings) {
- test(t => {
- const anim = createDiv(t).animate(null);
- anim.effect.timing.easing = easing;
- assert_equals(anim.effect.timing.easing, easing);
- }, `Canonical easing '${easing}' is returned as set`);
-}
-
-test(t => {
- const delay = 1000 * MS_PER_SEC;
-
- const target = createDiv(t);
- const anim = target.animate([ { opacity: 0 }, { opacity: 1 } ],
- { duration: 1000 * MS_PER_SEC,
- fill: 'both',
- delay: delay,
- easing: 'steps(2, start)' });
-
- anim.effect.timing.easing = 'steps(2, end)';
- assert_equals(anim.effect.getComputedTiming().progress, 0,
- 'easing replace to steps(2, end) at before phase');
-
- anim.currentTime = delay + 750 * MS_PER_SEC;
- assert_equals(anim.effect.getComputedTiming().progress, 0.5,
- 'change currentTime to active phase');
-
- anim.effect.timing.easing = 'steps(2, start)';
- assert_equals(anim.effect.getComputedTiming().progress, 1,
- 'easing replace to steps(2, start) at active phase');
-
- anim.currentTime = delay + 1500 * MS_PER_SEC;
- anim.effect.timing.easing = 'steps(2, end)';
- assert_equals(anim.effect.getComputedTiming().progress, 1,
- 'easing replace to steps(2, end) again at after phase');
-}, 'Allows the easing to be changed while the animation is in progress');
-
-</script>
-</body>
diff --git a/web-animations/interfaces/AnimationEffectTiming/endDelay.html b/web-animations/interfaces/AnimationEffectTiming/endDelay.html
deleted file mode 100644
index 3062c8c..0000000
--- a/web-animations/interfaces/AnimationEffectTiming/endDelay.html
+++ /dev/null
@@ -1,89 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>AnimationEffectTiming.endDelay</title>
-<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animationeffecttiming-enddelay">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-<body>
-<div id="log"></div>
-<script>
-'use strict';
-
-test(t => {
- const anim = createDiv(t).animate(null);
- assert_equals(anim.effect.timing.endDelay, 0);
-}, 'Has the default value 0');
-
-test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
- anim.effect.timing.endDelay = 123.45;
- assert_time_equals_literal(anim.effect.timing.endDelay, 123.45,
- 'set endDelay 123.45');
- assert_time_equals_literal(anim.effect.getComputedTiming().endDelay, 123.45,
- 'getComputedTiming() after set endDelay 123.45');
-}, 'Can be set to a positive number');
-
-test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
- anim.effect.timing.endDelay = -1000;
- assert_equals(anim.effect.timing.endDelay, -1000, 'set endDelay -1000');
- assert_equals(anim.effect.getComputedTiming().endDelay, -1000,
- 'getComputedTiming() after set endDelay -1000');
-}, 'Can be set to a negative number');
-
-test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
- assert_throws({ name: 'TypeError' }, () => {
- anim.effect.timing.endDelay = Infinity;
- }, 'we can not assign Infinity to timing.endDelay');
-}, 'Throws when setting infinity');
-
-test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
- assert_throws({ name: 'TypeError' }, () => {
- anim.effect.timing.endDelay = -Infinity;
- }, 'we can not assign negative Infinity to timing.endDelay');
-}, 'Throws when setting negative infinity');
-
-async_test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] },
- { duration: 100000, endDelay: 50000 });
- anim.onfinish = t.step_func(event => {
- assert_unreached('finish event should not be fired');
- });
-
- anim.ready.then(() => {
- anim.currentTime = 100000;
- return waitForAnimationFrames(2);
- }).then(t.step_func(() => {
- t.done();
- }));
-}, 'finish event is not fired at the end of the active interval when the'
- + ' endDelay has not expired');
-
-async_test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] },
- { duration: 100000, endDelay: 30000 });
- anim.ready.then(() => {
- anim.currentTime = 110000; // during endDelay
- anim.onfinish = t.step_func(event => {
- assert_unreached('onfinish event should not be fired during endDelay');
- });
- return waitForAnimationFrames(2);
- }).then(t.step_func(() => {
- anim.onfinish = t.step_func(event => {
- t.done();
- });
- anim.currentTime = 130000; // after endTime
- }));
-}, 'finish event is fired after the endDelay has expired');
-
-</script>
-</body>
diff --git a/web-animations/interfaces/AnimationEffectTiming/fill.html b/web-animations/interfaces/AnimationEffectTiming/fill.html
deleted file mode 100644
index 0173947..0000000
--- a/web-animations/interfaces/AnimationEffectTiming/fill.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>AnimationEffectTiming.fill</title>
-<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animationeffecttiming-fill">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-<body>
-<div id="log"></div>
-<script>
-'use strict';
-
-test(t => {
- const anim = createDiv(t).animate(null);
- assert_equals(anim.effect.timing.fill, 'auto');
-}, 'Has the default value \'auto\'');
-
-for (const fill of ['none', 'forwards', 'backwards', 'both']) {
- test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] }, 100);
- anim.effect.timing.fill = fill;
- assert_equals(anim.effect.timing.fill, fill, 'set fill ' + fill);
- assert_equals(anim.effect.getComputedTiming().fill, fill,
- 'getComputedTiming() after set fill ' + fill);
- }, `Can set fill to ${fill}`);
-}
-
-</script>
-</body>
diff --git a/web-animations/interfaces/AnimationEffectTiming/idlharness.html b/web-animations/interfaces/AnimationEffectTiming/idlharness.html
deleted file mode 100644
index 7e537d1..0000000
--- a/web-animations/interfaces/AnimationEffectTiming/idlharness.html
+++ /dev/null
@@ -1,80 +0,0 @@
-<!doctype html>
-<meta charset=utf-8>
-<title>AnimationEffectTiming and AnimationEffectTimingReadOnly IDL</title>
-<link rel="help"
- href="https://drafts.csswg.org/web-animations/#animationeffecttiming">
-<link rel="help"
- href="https://drafts.csswg.org/web-animations/#animationeffecttimingreadonly">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="/resources/WebIDLParser.js"></script>
-<script src="/resources/idlharness.js"></script>
-<div id="log"></div>
-<script type="text/plain" id="AnimationEffectTimingReadOnly-IDL">
-enum FillMode { "none", "forwards", "backwards", "both", "auto" };
-enum PlaybackDirection {
- "normal",
- "reverse",
- "alternate",
- "alternate-reverse"
-};
-
-dictionary AnimationEffectTimingProperties {
- double delay = 0.0;
- double endDelay = 0.0;
- FillMode fill = "auto";
- double iterationStart = 0.0;
- unrestricted double iterations = 1.0;
- (unrestricted double or DOMString) duration = "auto";
- PlaybackDirection direction = "normal";
- DOMString easing = "linear";
-};
-
-[Exposed=Window]
-interface AnimationEffectTimingReadOnly {
- readonly attribute double delay;
- readonly attribute double endDelay;
- readonly attribute FillMode fill;
- readonly attribute double iterationStart;
- readonly attribute unrestricted double iterations;
- readonly attribute (unrestricted double or DOMString) duration;
- readonly attribute PlaybackDirection direction;
- readonly attribute DOMString easing;
-};
-</script>
-<script type="text/plain" id="AnimationEffectTiming-IDL">
-[Exposed=Window]
-interface AnimationEffectTiming : AnimationEffectTimingReadOnly {
- inherit attribute double delay;
- inherit attribute double endDelay;
- inherit attribute FillMode fill;
- inherit attribute double iterationStart;
- inherit attribute unrestricted double iterations;
- inherit attribute (unrestricted double or DOMString) duration;
- inherit attribute PlaybackDirection direction;
- inherit attribute DOMString easing;
-};
-</script>
-<script>
-'use strict';
-
-const idlArray = new IdlArray();
-
-idlArray.add_idls(
- document.getElementById('AnimationEffectTimingReadOnly-IDL').textContent
-);
-idlArray.add_idls(
- document.getElementById('AnimationEffectTiming-IDL').textContent
-);
-
-idlArray.add_objects({
- AnimationEffectTiming: [
- '(new KeyframeEffect(null, null)).timing'
- ],
- AnimationEffectTimingReadOnly: [
- '(new KeyframeEffectReadOnly(null, null)).timing'
- ],
-});
-idlArray.test();
-
-</script>
diff --git a/web-animations/interfaces/AnimationEffectTiming/iterationStart.html b/web-animations/interfaces/AnimationEffectTiming/iterationStart.html
deleted file mode 100644
index 73bc481..0000000
--- a/web-animations/interfaces/AnimationEffectTiming/iterationStart.html
+++ /dev/null
@@ -1,72 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>AnimationEffectTiming.iterationStart</title>
-<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animationeffecttiming-iterationstart">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-<body>
-<div id="log"></div>
-<script>
-'use strict';
-
-test(t => {
- const anim = createDiv(t).animate(null);
- assert_equals(anim.effect.timing.iterationStart, 0);
-}, 'Has the default value 0');
-
-test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] },
- { iterationStart: 0.2,
- iterations: 1,
- fill: 'both',
- duration: 100,
- delay: 1 });
- anim.effect.timing.iterationStart = 2.5;
- assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.5);
- assert_equals(anim.effect.getComputedTiming().currentIteration, 2);
-}, 'Changing the value updates computed timing when backwards-filling');
-
-test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] },
- { iterationStart: 0.2,
- iterations: 1,
- fill: 'both',
- duration: 100,
- delay: 0 });
- anim.effect.timing.iterationStart = 2.5;
- assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.5);
- assert_equals(anim.effect.getComputedTiming().currentIteration, 2);
-}, 'Changing the value updates computed timing during the active phase');
-
-test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] },
- { iterationStart: 0.2,
- iterations: 1,
- fill: 'both',
- duration: 100,
- delay: 0 });
- anim.finish();
- anim.effect.timing.iterationStart = 2.5;
- assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.5);
- assert_equals(anim.effect.getComputedTiming().currentIteration, 3);
-}, 'Changing the value updates computed timing when forwards-filling');
-
-test(t => {
- const div = createDiv(t);
- const anim = div.animate(null);
- for (let invalid of [-1, NaN, Infinity]) {
- assert_throws({ name: 'TypeError' }, () => {
- anim.effect.timing.iterationStart = invalid;
- }, `setting ${invalid}`);
- assert_throws({ name: 'TypeError' }, () => {
- div.animate({}, { iterationStart: invalid });
- }, `animate() with ${invalid}`);
- }
-}, 'Throws when setting invalid values');
-
-</script>
-</body>
diff --git a/web-animations/interfaces/AnimationEffectTiming/iterations.html b/web-animations/interfaces/AnimationEffectTiming/iterations.html
deleted file mode 100644
index 3bfaf8e..0000000
--- a/web-animations/interfaces/AnimationEffectTiming/iterations.html
+++ /dev/null
@@ -1,96 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>AnimationEffectTiming.iterations</title>
-<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animationeffecttiming-iterations">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-<body>
-<div id="log"></div>
-<script>
-'use strict';
-
-test(t => {
- const anim = createDiv(t).animate(null);
- assert_equals(anim.effect.timing.iterations, 1);
-}, 'Has the default value 1');
-
-test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
- anim.effect.timing.iterations = 2;
- assert_equals(anim.effect.timing.iterations, 2, 'set duration 2');
- assert_equals(anim.effect.getComputedTiming().iterations, 2,
- 'getComputedTiming() after set iterations 2');
-}, 'Can be set to a double value');
-
-test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
- anim.effect.timing.iterations = Infinity;
- assert_equals(anim.effect.timing.iterations, Infinity, 'set duration Infinity');
- assert_equals(anim.effect.getComputedTiming().iterations, Infinity,
- 'getComputedTiming() after set iterations Infinity');
-}, 'Can be set to infinity');
-
-test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
- assert_throws({ name: 'TypeError' }, () => {
- anim.effect.timing.iterations = -1;
- });
-}, 'Throws when setting a negative number');
-
-test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
- assert_throws({ name: 'TypeError' }, () => {
- anim.effect.timing.iterations = -Infinity;
- });
-}, 'Throws when setting negative infinity');
-
-test(t => {
- const div = createDiv(t);
- const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
- assert_throws({ name: 'TypeError' }, () => {
- anim.effect.timing.iterations = NaN;
- });
-}, 'Throws when setting a NaN value');
-
-test(t => {
- const div = createDiv(t);
- const anim = div.animate(null, { duration: 100000, fill: 'both' });
-
- anim.finish();
-
- assert_equals(anim.effect.getComputedTiming().progress, 1,
- 'progress when animation is finished');
- assert_equals(anim.effect.getComputedTiming().currentIteration, 0,
- 'current iteration when animation is finished');
-
- anim.effect.timing.iterations = 2;
-
- assert_time_equals_literal(anim.effect.getComputedTiming().progress,
- 0,
- 'progress after adding an iteration');
- assert_time_equals_literal(anim.effect.getComputedTiming().currentIteration,
- 1,
- 'current iteration after adding an iteration');
-
- anim.effect.timing.iterations = 0;
-
- assert_equals(anim.effect.getComputedTiming().progress, 0,
- 'progress after setting iterations to zero');
- assert_equals(anim.effect.getComputedTiming().currentIteration, 0,
- 'current iteration after setting iterations to zero');
-
- anim.effect.timing.iterations = Infinity;
-
- assert_equals(anim.effect.getComputedTiming().progress, 0,
- 'progress after setting iterations to Infinity');
- assert_equals(anim.effect.getComputedTiming().currentIteration, 1,
- 'current iteration after setting iterations to Infinity');
-}, 'Can be updated while the animation is in progress');
-
-</script>
-</body>
diff --git a/web-animations/interfaces/Document/getAnimations.html b/web-animations/interfaces/Document/getAnimations.html
index 165626d..3a1d7be 100644
--- a/web-animations/interfaces/Document/getAnimations.html
+++ b/web-animations/interfaces/Document/getAnimations.html
@@ -42,7 +42,7 @@
}, 'Test the order of document.getAnimations with script generated animations')
test(t => {
- const effect = new KeyframeEffectReadOnly(null, gKeyFrames, 100 * MS_PER_SEC);
+ const effect = new KeyframeEffect(null, gKeyFrames, 100 * MS_PER_SEC);
const anim = new Animation(effect, document.timeline);
anim.play();
diff --git a/web-animations/interfaces/KeyframeEffect/constructor.html b/web-animations/interfaces/KeyframeEffect/constructor.html
index dfdebde..250a8c7 100644
--- a/web-animations/interfaces/KeyframeEffect/constructor.html
+++ b/web-animations/interfaces/KeyframeEffect/constructor.html
@@ -1,6 +1,6 @@
<!DOCTYPE html>
<meta charset=utf-8>
-<title>KeyframeEffect and KeyframeEffectReadOnly constructor</title>
+<title>KeyframeEffect constructor</title>
<link rel="help"
href="https://drafts.csswg.org/web-animations/#dom-keyframeeffect-keyframeeffect">
<link rel="help"
@@ -21,49 +21,48 @@
test(t => {
for (const frames of gEmptyKeyframeListTests) {
- assert_equals(new KeyframeEffectReadOnly(target, frames)
- .getKeyframes().length,
+ assert_equals(new KeyframeEffect(target, frames).getKeyframes().length,
0, `number of frames for ${JSON.stringify(frames)}`);
}
-}, 'A KeyframeEffectReadOnly can be constructed with no frames');
+}, 'A KeyframeEffect can be constructed with no frames');
test(t => {
for (const subtest of gEasingParsingTests) {
const easing = subtest[0];
const expected = subtest[1];
- const effect = new KeyframeEffectReadOnly(target, {
+ const effect = new KeyframeEffect(target, {
left: ['10px', '20px']
}, { easing: easing });
- assert_equals(effect.timing.easing, expected,
+ assert_equals(effect.getTiming().easing, expected,
`resulting easing for '${easing}'`);
}
}, 'easing values are parsed correctly when passed to the ' +
- 'KeyframeEffectReadOnly constructor in KeyframeEffectOptions');
+ 'KeyframeEffect constructor in KeyframeEffectOptions');
test(t => {
for (const invalidEasing of gInvalidEasings) {
assert_throws(new TypeError, () => {
- new KeyframeEffectReadOnly(target, null, { easing: invalidEasing });
+ new KeyframeEffect(target, null, { easing: invalidEasing });
}, `TypeError is thrown for easing '${invalidEasing}'`);
}
}, 'Invalid easing values are correctly rejected when passed to the ' +
- 'KeyframeEffectReadOnly constructor in KeyframeEffectOptions');
+ 'KeyframeEffect constructor in KeyframeEffectOptions');
test(t => {
const getKeyframe =
composite => ({ left: [ '10px', '20px' ], composite: composite });
for (const composite of gGoodKeyframeCompositeValueTests) {
- const effect = new KeyframeEffectReadOnly(target, getKeyframe(composite));
+ const effect = new KeyframeEffect(target, getKeyframe(composite));
assert_equals(effect.getKeyframes()[0].composite, composite,
`resulting composite for '${composite}'`);
}
for (const composite of gBadKeyframeCompositeValueTests) {
assert_throws(new TypeError, () => {
- new KeyframeEffectReadOnly(target, getKeyframe(composite));
+ new KeyframeEffect(target, getKeyframe(composite));
});
}
}, 'composite values are parsed correctly when passed to the ' +
- 'KeyframeEffectReadOnly constructor in property-indexed keyframes');
+ 'KeyframeEffect constructor in property-indexed keyframes');
test(t => {
const getKeyframes = composite =>
@@ -72,29 +71,29 @@
{ offset: 1, left: '20px' }
];
for (const composite of gGoodKeyframeCompositeValueTests) {
- const effect = new KeyframeEffectReadOnly(target, getKeyframes(composite));
+ const effect = new KeyframeEffect(target, getKeyframes(composite));
assert_equals(effect.getKeyframes()[0].composite, composite,
`resulting composite for '${composite}'`);
}
for (const composite of gBadKeyframeCompositeValueTests) {
assert_throws(new TypeError, () => {
- new KeyframeEffectReadOnly(target, getKeyframes(composite));
+ new KeyframeEffect(target, getKeyframes(composite));
});
}
}, 'composite values are parsed correctly when passed to the ' +
- 'KeyframeEffectReadOnly constructor in regular keyframes');
+ 'KeyframeEffect constructor in regular keyframes');
test(t => {
for (const composite of gGoodOptionsCompositeValueTests) {
- const effect = new KeyframeEffectReadOnly(target, {
+ const effect = new KeyframeEffect(target, {
left: ['10px', '20px']
- }, { composite: composite });
+ }, { composite });
assert_equals(effect.getKeyframes()[0].composite, null,
`resulting composite for '${composite}'`);
}
for (const composite of gBadOptionsCompositeValueTests) {
assert_throws(new TypeError, () => {
- new KeyframeEffectReadOnly(target, {
+ new KeyframeEffect(target, {
left: ['10px', '20px']
}, { composite: composite });
});
@@ -104,32 +103,30 @@
for (const subtest of gKeyframesTests) {
test(t => {
- const effect = new KeyframeEffectReadOnly(target, subtest.input);
+ const effect = new KeyframeEffect(target, subtest.input);
assert_frame_lists_equal(effect.getKeyframes(), subtest.output);
- }, `A KeyframeEffectReadOnly can be constructed with ${subtest.desc}`);
+ }, `A KeyframeEffect can be constructed with ${subtest.desc}`);
test(t => {
- const effect = new KeyframeEffectReadOnly(target, subtest.input);
- const secondEffect =
- new KeyframeEffectReadOnly(target, effect.getKeyframes());
+ const effect = new KeyframeEffect(target, subtest.input);
+ const secondEffect = new KeyframeEffect(target, effect.getKeyframes());
assert_frame_lists_equal(secondEffect.getKeyframes(),
effect.getKeyframes());
- }, `A KeyframeEffectReadOnly constructed with ${subtest.desc} roundtrips`);
+ }, `A KeyframeEffect constructed with ${subtest.desc} roundtrips`);
}
for (const subtest of gInvalidKeyframesTests) {
test(t => {
assert_throws(new TypeError, () => {
- new KeyframeEffectReadOnly(target, subtest.input);
+ new KeyframeEffect(target, subtest.input);
});
- }, `KeyframeEffectReadOnly constructor throws with ${subtest.desc}`);
+ }, `KeyframeEffect constructor throws with ${subtest.desc}`);
}
test(t => {
- const effect = new KeyframeEffectReadOnly(target,
- { left: ['10px', '20px'] });
+ const effect = new KeyframeEffect(target, { left: ['10px', '20px'] });
- const timing = effect.timing;
+ const timing = effect.getTiming();
assert_equals(timing.delay, 0, 'default delay');
assert_equals(timing.endDelay, 0, 'default endDelay');
assert_equals(timing.fill, 'auto', 'default fill');
@@ -142,14 +139,12 @@
assert_equals(effect.composite, 'replace', 'default composite');
assert_equals(effect.iterationComposite, 'replace',
'default iterationComposite');
-}, 'A KeyframeEffectReadOnly constructed without any ' +
- 'KeyframeEffectOptions object');
+}, 'A KeyframeEffect constructed without any KeyframeEffectOptions object');
for (const subtest of gKeyframeEffectOptionTests) {
test(t => {
- const effect = new KeyframeEffectReadOnly(target,
- { left: ['10px', '20px'] },
- subtest.input);
+ const effect = new KeyframeEffect(target, { left: ['10px', '20px'] },
+ subtest.input);
// Helper function to provide default expected values when the test does
// not supply them.
@@ -157,7 +152,7 @@
return field in subtest.expected ? subtest.expected[field] : defaultValue;
};
- const timing = effect.timing;
+ const timing = effect.getTiming();
assert_equals(timing.delay, expected('delay', 0),
'timing delay');
assert_equals(timing.fill, expected('fill', 'auto'),
@@ -169,27 +164,24 @@
assert_equals(timing.direction, expected('direction', 'normal'),
'timing direction');
- }, `A KeyframeEffectReadOnly constructed by ${subtest.desc}`);
+ }, `A KeyframeEffect constructed by ${subtest.desc}`);
}
for (const subtest of gInvalidKeyframeEffectOptionTests) {
test(t => {
assert_throws(new TypeError, () => {
- new KeyframeEffectReadOnly(target,
- { left: ['10px', '20px'] },
- subtest.input);
+ new KeyframeEffect(target, { left: ['10px', '20px'] }, subtest.input);
});
- }, `Invalid KeyframeEffectReadOnly option by ${subtest.desc}`);
+ }, `Invalid KeyframeEffect option by ${subtest.desc}`);
}
test(t => {
- const effect = new KeyframeEffectReadOnly(null,
- { left: ['10px', '20px'] },
- { duration: 100 * MS_PER_SEC,
- fill: 'forwards' });
+ const effect = new KeyframeEffect(null, { left: ['10px', '20px'] },
+ { duration: 100 * MS_PER_SEC,
+ fill: 'forwards' });
assert_equals(effect.target, null,
'Effect created with null target has correct target');
-}, 'A KeyframeEffectReadOnly constructed with null target');
+}, 'A KeyframeEffect constructed with null target');
test(t => {
const test_error = { name: 'test' };
diff --git a/web-animations/interfaces/KeyframeEffect/copy-constructor.html b/web-animations/interfaces/KeyframeEffect/copy-constructor.html
index c4e8a8e..e3bc0db 100644
--- a/web-animations/interfaces/KeyframeEffect/copy-constructor.html
+++ b/web-animations/interfaces/KeyframeEffect/copy-constructor.html
@@ -1,6 +1,6 @@
<!DOCTYPE html>
<meta charset=utf-8>
-<title>KeyframeEffect and KeyframeEffectReadOnly copy constructor</title>
+<title>KeyframeEffect copy constructor</title>
<link rel="help"
href="https://drafts.csswg.org/web-animations/#dom-keyframeeffect-keyframeeffect-source">
<link rel="help"
@@ -14,21 +14,21 @@
'use strict';
test(t => {
- const effect = new KeyframeEffectReadOnly(createDiv(t), null);
- const copiedEffect = new KeyframeEffectReadOnly(effect);
+ const effect = new KeyframeEffect(createDiv(t), null);
+ const copiedEffect = new KeyframeEffect(effect);
assert_equals(copiedEffect.target, effect.target, 'same target');
-}, 'Copied KeyframeEffectReadOnly has the same target');
+}, 'Copied KeyframeEffect has the same target');
test(t => {
const effect =
- new KeyframeEffectReadOnly(null,
- [ { marginLeft: '0px' },
- { marginLeft: '-20px', easing: 'ease-in',
- offset: 0.1 },
- { marginLeft: '100px', easing: 'ease-out' },
- { marginLeft: '50px' } ]);
+ new KeyframeEffect(null,
+ [ { marginLeft: '0px' },
+ { marginLeft: '-20px', easing: 'ease-in',
+ offset: 0.1 },
+ { marginLeft: '100px', easing: 'ease-out' },
+ { marginLeft: '50px' } ]);
- const copiedEffect = new KeyframeEffectReadOnly(effect);
+ const copiedEffect = new KeyframeEffect(effect);
const keyframesA = effect.getKeyframes();
const keyframesB = copiedEffect.getKeyframes();
assert_equals(keyframesA.length, keyframesB.length, 'same keyframes length');
@@ -50,34 +50,33 @@
assert_equals(keyframesA[i].marginLeft, keyframesB[i].marginLeft,
`Keyframe ${i} has the same property value pair`);
}
-}, 'Copied KeyframeEffectReadOnly has the same keyframes');
+}, 'Copied KeyframeEffect has the same keyframes');
test(t => {
const effect =
- new KeyframeEffectReadOnly(null, null,
- { iterationComposite: 'accumulate' });
+ new KeyframeEffect(null, null, { iterationComposite: 'accumulate' });
- const copiedEffect = new KeyframeEffectReadOnly(effect);
+ const copiedEffect = new KeyframeEffect(effect);
assert_equals(copiedEffect.iterationComposite, effect.iterationComposite,
'same iterationCompositeOperation');
assert_equals(copiedEffect.composite, effect.composite,
'same compositeOperation');
-}, 'Copied KeyframeEffectReadOnly has the same KeyframeEffectOptions');
+}, 'Copied KeyframeEffect has the same KeyframeEffectOptions');
test(t => {
- const effect = new KeyframeEffectReadOnly(null, null,
- { duration: 100 * MS_PER_SEC,
- delay: -1 * MS_PER_SEC,
- endDelay: 2 * MS_PER_SEC,
- fill: 'forwards',
- iterationStart: 2,
- iterations: 20,
- easing: 'ease-out',
- direction: 'alternate' } );
+ const effect = new KeyframeEffect(null, null,
+ { duration: 100 * MS_PER_SEC,
+ delay: -1 * MS_PER_SEC,
+ endDelay: 2 * MS_PER_SEC,
+ fill: 'forwards',
+ iterationStart: 2,
+ iterations: 20,
+ easing: 'ease-out',
+ direction: 'alternate' } );
- const copiedEffect = new KeyframeEffectReadOnly(effect);
- const timingA = effect.timing;
- const timingB = copiedEffect.timing;
+ const copiedEffect = new KeyframeEffect(effect);
+ const timingA = effect.getTiming();
+ const timingB = copiedEffect.getTiming();
assert_not_equals(timingA, timingB, 'different timing objects');
assert_equals(timingA.delay, timingB.delay, 'same delay');
assert_equals(timingA.endDelay, timingB.endDelay, 'same endDelay');
@@ -88,19 +87,7 @@
assert_equals(timingA.duration, timingB.duration, 'same duration');
assert_equals(timingA.direction, timingB.direction, 'same direction');
assert_equals(timingA.easing, timingB.easing, 'same easing');
-}, 'Copied KeyframeEffectReadOnly has the same timing content');
-
-test(t => {
- const effect = new KeyframeEffectReadOnly(createDiv(t), null);
- assert_equals(effect.constructor.name, 'KeyframeEffectReadOnly');
- assert_equals(effect.timing.constructor.name,
- 'AnimationEffectTimingReadOnly');
-
- // Make a mutable copy
- const copiedEffect = new KeyframeEffect(effect);
- assert_equals(copiedEffect.constructor.name, 'KeyframeEffect');
- assert_equals(copiedEffect.timing.constructor.name, 'AnimationEffectTiming');
-}, 'KeyframeEffect constructed from a KeyframeEffectReadOnly is mutable');
+}, 'Copied KeyframeEffect has the same timing content');
</script>
</body>
diff --git a/web-animations/interfaces/KeyframeEffect/idlharness.html b/web-animations/interfaces/KeyframeEffect/idlharness.html
index 5056a87..0340a19 100644
--- a/web-animations/interfaces/KeyframeEffect/idlharness.html
+++ b/web-animations/interfaces/KeyframeEffect/idlharness.html
@@ -9,7 +9,7 @@
<script src="/resources/WebIDLParser.js"></script>
<script src="/resources/idlharness.js"></script>
<div id="log"></div>
-<script type="text/plain" id="AnimationEffectTimingReadOnly-IDL">
+<script type="text/plain" id="AnimationEffect-IDL">
enum FillMode { "none", "forwards", "backwards", "both", "auto" };
enum PlaybackDirection {
"normal",
@@ -18,7 +18,7 @@
"alternate-reverse"
};
-dictionary AnimationEffectTimingProperties {
+dictionary EffectTiming {
double delay = 0.0;
double endDelay = 0.0;
FillMode fill = "auto";
@@ -29,38 +29,37 @@
DOMString easing = "linear";
};
-[Exposed=Window]
-interface AnimationEffectTimingReadOnly {
- readonly attribute double delay;
- readonly attribute double endDelay;
- readonly attribute FillMode fill;
- readonly attribute double iterationStart;
- readonly attribute unrestricted double iterations;
- readonly attribute (unrestricted double or DOMString) duration;
- readonly attribute PlaybackDirection direction;
- readonly attribute DOMString easing;
+dictionary OptionalEffectTiming {
+ double delay;
+ double endDelay;
+ FillMode fill;
+ double iterationStart;
+ unrestricted double iterations;
+ (unrestricted double or DOMString) duration;
+ PlaybackDirection direction;
+ DOMString easing;
};
-</script>
-<script type="text/plain" id="AnimationEffectReadOnly-IDL">
-dictionary ComputedTimingProperties : AnimationEffectTimingProperties {
- unrestricted double endTime;
- unrestricted double activeDuration;
- double? localTime;
- double? progress;
- unrestricted double? currentIteration;
+
+dictionary ComputedEffectTiming : EffectTiming {
+ unrestricted double endTime = 0.0;
+ unrestricted double activeDuration = 0.0;
+ double? localTime = null;
+ double? progress = null;
+ unrestricted double? currentIteration = null;
};
[Exposed=Window]
-interface AnimationEffectReadOnly {
- readonly attribute AnimationEffectTimingReadOnly timing;
- ComputedTimingProperties getComputedTiming();
+interface AnimationEffect {
+ EffectTiming getTiming();
+ ComputedEffectTiming getComputedTiming();
+ void updateTiming(optional OptionalEffectTiming timing);
};
</script>
-<script type="text/plain" id="KeyframeEffectReadOnly-IDL">
+<script type="text/plain" id="KeyframeEffect-IDL">
enum IterationCompositeOperation { "replace", "accumulate" };
enum CompositeOperation { "replace", "add", "accumulate" };
-dictionary KeyframeEffectOptions : AnimationEffectTimingProperties {
+dictionary KeyframeEffectOptions : EffectTiming {
IterationCompositeOperation iterationComposite = "replace";
CompositeOperation composite = "replace";
};
@@ -69,24 +68,13 @@
Constructor ((Element or CSSPseudoElement)? target,
object? keyframes,
optional (unrestricted double or KeyframeEffectOptions) options),
- Constructor (KeyframeEffectReadOnly source)]
-interface KeyframeEffectReadOnly : AnimationEffectReadOnly {
- readonly attribute (Element or CSSPseudoElement)? target;
- readonly attribute IterationCompositeOperation iterationComposite;
- readonly attribute CompositeOperation composite;
+ Constructor (KeyframeEffect source)]
+interface KeyframeEffect : AnimationEffect {
+ attribute (Element or CSSPseudoElement)? target;
+ attribute IterationCompositeOperation iterationComposite;
+ attribute CompositeOperation composite;
+
sequence<object> getKeyframes ();
-};
-</script>
-<script type="text/plain" id="KeyframeEffect-IDL">
-[Exposed=Window,
- Constructor ((Element or CSSPseudoElement)? target,
- object? keyframes,
- optional (unrestricted double or KeyframeEffectOptions) options),
- Constructor (KeyframeEffectReadOnly source)]
-interface KeyframeEffect : KeyframeEffectReadOnly {
- inherit attribute (Element or CSSPseudoElement)? target;
- inherit attribute IterationCompositeOperation iterationComposite;
- inherit attribute CompositeOperation composite;
void setKeyframes (object? keyframes);
};
</script>
@@ -98,20 +86,13 @@
idlArray.add_untested_idls('interface CSSPseudoElement {};');
idlArray.add_untested_idls('interface Element {};');
idlArray.add_untested_idls(
- document.getElementById('AnimationEffectTimingReadOnly-IDL').textContent
-);
-idlArray.add_idls(
- document.getElementById('AnimationEffectReadOnly-IDL').textContent
-);
-idlArray.add_idls(
- document.getElementById('KeyframeEffectReadOnly-IDL').textContent
+ document.getElementById('AnimationEffect-IDL').textContent
);
idlArray.add_idls(
document.getElementById('KeyframeEffect-IDL').textContent
);
idlArray.add_objects({
KeyframeEffect: ['new KeyframeEffect(null, null)'],
- KeyframeEffectReadOnly: ['new KeyframeEffectReadOnly(null, null)'],
});
idlArray.test();
diff --git a/web-animations/interfaces/KeyframeEffect/iterationComposite.html b/web-animations/interfaces/KeyframeEffect/iterationComposite.html
index de2afa7..bbb8ee2 100644
--- a/web-animations/interfaces/KeyframeEffect/iterationComposite.html
+++ b/web-animations/interfaces/KeyframeEffect/iterationComposite.html
@@ -19,7 +19,8 @@
anim.pause();
anim.currentTime =
- anim.effect.timing.duration * 2 + anim.effect.timing.duration / 2;
+ anim.effect.getComputedTiming().duration * 2 +
+ anim.effect.getComputedTiming().duration / 2;
assert_equals(getComputedStyle(div).marginLeft, '25px',
'Animated style at 50s of the third iteration');
diff --git a/web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-001.html b/web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-001.html
index 523019d..133fd57 100644
--- a/web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-001.html
+++ b/web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-001.html
@@ -13,7 +13,7 @@
'use strict';
// This file only tests the KeyframeEffect constructor since it is
-// assumed that the implementation of the KeyframeEffectReadOnly constructor,
+// assumed that the implementation of the KeyframeEffect constructor,
// Animatable.animate() method, and KeyframeEffect.setKeyframes() method will
// all share common machinery and it is not necessary to test each method.
diff --git a/web-animations/resources/timing-tests.js b/web-animations/resources/timing-tests.js
new file mode 100644
index 0000000..4b0f021
--- /dev/null
+++ b/web-animations/resources/timing-tests.js
@@ -0,0 +1,46 @@
+'use strict';
+
+// =================================
+//
+// Common timing parameter test data
+//
+// =================================
+
+
+// ------------------------------
+// Delay values
+// ------------------------------
+
+const gBadDelayValues = [
+ NaN, Infinity, -Infinity
+];
+
+// ------------------------------
+// Duration values
+// ------------------------------
+
+const gGoodDurationValues = [
+ { specified: 123.45, computed: 123.45 },
+ { specified: 'auto', computed: 0 },
+ { specified: Infinity, computed: Infinity },
+];
+
+const gBadDurationValues = [
+ -1, NaN, -Infinity, 'abc', '100'
+];
+
+// ------------------------------
+// iterationStart values
+// ------------------------------
+
+const gBadIterationStartValues = [
+ -1, NaN, Infinity, -Infinity
+];
+
+// ------------------------------
+// iterations values
+// ------------------------------
+
+const gBadIterationsValues = [
+ -1, -Infinity, NaN
+];
diff --git a/web-animations/resources/timing-utils.js b/web-animations/resources/timing-utils.js
new file mode 100644
index 0000000..d7267f9
--- /dev/null
+++ b/web-animations/resources/timing-utils.js
@@ -0,0 +1,39 @@
+'use strict';
+
+// =======================================
+//
+// Utility functions for testing timing
+//
+// =======================================
+
+
+// ------------------------------
+// Helper functions
+// ------------------------------
+
+// Utility function to check that a subset of timing properties have their
+// default values.
+function assert_default_timing_except(effect, propertiesToSkip) {
+ const defaults = {
+ delay: 0,
+ endDelay: 0,
+ fill: 'auto',
+ iterationStart: 0,
+ iterations: 1,
+ duration: 'auto',
+ direction: 'normal',
+ easing: 'linear',
+ };
+
+ for (const prop of Object.keys(defaults)) {
+ if (propertiesToSkip.includes(prop)) {
+ continue;
+ }
+
+ assert_equals(
+ effect.getTiming()[prop],
+ defaults[prop],
+ `${prop} parameter has default value:`
+ );
+ }
+}
diff --git a/web-animations/testcommon.js b/web-animations/testcommon.js
index bb5acc2..46f2356 100644
--- a/web-animations/testcommon.js
+++ b/web-animations/testcommon.js
@@ -29,7 +29,11 @@
// a time value based on its precision requirements with a fixed value.
if (!window.assert_time_equals_literal) {
window.assert_time_equals_literal = (actual, expected, description) => {
- assert_approx_equals(actual, expected, TIME_PRECISION, description);
+ if (Math.abs(expected) === Infinity) {
+ assert_equals(actual, expected, description);
+ } else {
+ assert_approx_equals(actual, expected, TIME_PRECISION, description);
+ }
}
}
@@ -283,4 +287,4 @@
assert_approx_equals(actualRotationVector[i], expectedRotationVector[i], 0.0001,
`expected ${expected} but got ${actual}: ${description}`);
}
-}
\ No newline at end of file
+}
diff --git a/web-animations/timing-model/animation-effects/phases-and-states.html b/web-animations/timing-model/animation-effects/phases-and-states.html
index ac3732f..b62726c 100644
--- a/web-animations/timing-model/animation-effects/phases-and-states.html
+++ b/web-animations/timing-model/animation-effects/phases-and-states.html
@@ -22,7 +22,7 @@
if (phase === 'active') {
// If the fill mode is 'none', then progress will only be non-null if we
// are in the active phase.
- animation.effect.timing.fill = 'none';
+ animation.effect.updateTiming({ fill: 'none' });
assert_not_equals(animation.effect.getComputedTiming().progress, null,
'Animation effect is in active phase when current time'
+ ` is ${currentTime}ms`);
@@ -31,15 +31,15 @@
// phase is to toggle the fill mode. For example, if the progress is null
// will the fill node is 'none' but non-null when the fill mode is
// 'backwards' then we are in the before phase.
- animation.effect.timing.fill = 'none';
+ animation.effect.updateTiming({ fill: 'none' });
assert_equals(animation.effect.getComputedTiming().progress, null,
`Animation effect is in ${phase} phase when current time`
+ ` is ${currentTime}ms`
+ ' (progress is null with \'none\' fill mode)');
- animation.effect.timing.fill = phase === 'before'
- ? 'backwards'
- : 'forwards';
+ animation.effect.updateTiming({
+ fill: phase === 'before' ? 'backwards' : 'forwards',
+ });
assert_not_equals(animation.effect.getComputedTiming().progress, null,
`Animation effect is in ${phase} phase when current time`
+ ` is ${currentTime}ms`
diff --git a/web-animations/timing-model/animations/finishing-an-animation.html b/web-animations/timing-model/animations/finishing-an-animation.html
index b479db9..833f074 100644
--- a/web-animations/timing-model/animations/finishing-an-animation.html
+++ b/web-animations/timing-model/animations/finishing-an-animation.html
@@ -196,7 +196,7 @@
}, 'Finishing an animation resolves the finished promise synchronously');
promise_test(async t => {
- const effect = new KeyframeEffectReadOnly(null, null, 100 * MS_PER_SEC);
+ const effect = new KeyframeEffect(null, null, 100 * MS_PER_SEC);
const animation = new Animation(effect, document.timeline);
let resolvedFinished = false;
animation.finished.then(() => {
diff --git a/web-animations/timing-model/animations/setting-the-target-effect-of-an-animation.html b/web-animations/timing-model/animations/setting-the-target-effect-of-an-animation.html
index 184804d..daa73f5 100644
--- a/web-animations/timing-model/animations/setting-the-target-effect-of-an-animation.html
+++ b/web-animations/timing-model/animations/setting-the-target-effect-of-an-animation.html
@@ -36,9 +36,9 @@
anim.pause();
assert_true(anim.pending);
- anim.effect = new KeyframeEffectReadOnly(createDiv(t),
- { marginLeft: [ '0px', '100px' ] },
- 100 * MS_PER_SEC);
+ anim.effect = new KeyframeEffect(createDiv(t),
+ { marginLeft: [ '0px', '100px' ] },
+ 100 * MS_PER_SEC);
assert_true(anim.pending);
await anim.ready;
@@ -52,9 +52,9 @@
anim.play();
assert_true(anim.pending);
- anim.effect = new KeyframeEffectReadOnly(createDiv(t),
- { marginLeft: [ '0px', '100px' ] },
- 100 * MS_PER_SEC);
+ anim.effect = new KeyframeEffect(createDiv(t),
+ { marginLeft: [ '0px', '100px' ] },
+ 100 * MS_PER_SEC);
assert_true(anim.pending);
await anim.ready;
diff --git a/web-animations/timing-model/animations/updating-the-finished-state.html b/web-animations/timing-model/animations/updating-the-finished-state.html
index 7059423..8e02fed 100644
--- a/web-animations/timing-model/animations/updating-the-finished-state.html
+++ b/web-animations/timing-model/animations/updating-the-finished-state.html
@@ -141,7 +141,9 @@
'Hold time is initially set');
// Then extend the duration so that the hold time is cleared and on
// the next tick the current time will increase.
- anim.effect.timing.duration *= 2;
+ anim.effect.updateTiming({
+ duration: anim.effect.getComputedTiming().duration * 2,
+ });
await waitForNextFrame();
assert_greater_than(anim.currentTime, 100 * MS_PER_SEC,
@@ -247,7 +249,7 @@
anim.cancel();
// Trigger a change that will cause the "update the finished state"
// procedure to run.
- anim.effect.timing.duration = 200 * MS_PER_SEC;
+ anim.effect.updateTiming({ duration: 200 * MS_PER_SEC });
assert_equals(anim.currentTime, null,
'The animation hold time / start time should not be updated');
// The "update the finished state" procedure is supposed to run after any
@@ -273,7 +275,7 @@
// is greater than the target end. At this point the "update the finished
// state" procedure should run and if we fail to check for a pending task
// we will set the hold time to the target end, i.e. 50ms.
- anim.effect.timing.duration = 50 * MS_PER_SEC;
+ anim.effect.updateTiming({ duration: 50 * MS_PER_SEC });
assert_equals(anim.currentTime, 75 * MS_PER_SEC,
'Hold time should not be updated');
}, 'Updating the finished state when there is a pending task');
@@ -289,7 +291,7 @@
anim.currentTime = 150 * MS_PER_SEC;
// Trigger a change that will cause the "update the finished state"
// procedure to run (did seek = false).
- anim.effect.timing.duration = 200 * MS_PER_SEC;
+ anim.effect.updateTiming({ duration: 200 * MS_PER_SEC });
await waitForAnimationFrames(1);
assert_equals(anim.currentTime, 150 * MS_PER_SEC,
@@ -348,7 +350,7 @@
}, 'Finish notification steps run when the animation completes normally');
promise_test(async t => {
- const effect = new KeyframeEffectReadOnly(null, null, 1);
+ const effect = new KeyframeEffect(null, null, 1);
const animation = new Animation(effect, document.timeline);
animation.play();
await animation.ready;
@@ -417,5 +419,38 @@
};
}, 'Animation finish event is fired again after replaying from start');
+async_test(t => {
+ const anim = createDiv(t).animate(null,
+ { duration: 100000, endDelay: 50000 });
+ anim.onfinish = t.step_func(event => {
+ assert_unreached('finish event should not be fired');
+ });
+
+ anim.ready.then(() => {
+ anim.currentTime = 100000;
+ return waitForAnimationFrames(2);
+ }).then(t.step_func(() => {
+ t.done();
+ }));
+}, 'finish event is not fired at the end of the active interval when the'
+ + ' endDelay has not expired');
+
+async_test(t => {
+ const anim = createDiv(t).animate(null,
+ { duration: 100000, endDelay: 30000 });
+ anim.ready.then(() => {
+ anim.currentTime = 110000; // during endDelay
+ anim.onfinish = t.step_func(event => {
+ assert_unreached('onfinish event should not be fired during endDelay');
+ });
+ return waitForAnimationFrames(2);
+ }).then(t.step_func(() => {
+ anim.onfinish = t.step_func(event => {
+ t.done();
+ });
+ anim.currentTime = 130000; // after endTime
+ }));
+}, 'finish event is fired after the endDelay has expired');
+
</script>
</body>