mirror of
https://github.com/servo/servo.git
synced 2025-09-13 16:38:20 +01:00
Update web-platform-tests to revision 2d42384cf21efd71843295d319c1bab85b3acf4a
This commit is contained in:
parent
f2b224d610
commit
e851ef0cd2
1014 changed files with 5653 additions and 1590 deletions
|
@ -0,0 +1,56 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Test that AnimationWorklet inside frames with different origin causes new global scopes</title>
|
||||
<link rel="help" href="https://drafts.css-houdini.org/css-animationworklet/">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="common.js"></script>
|
||||
|
||||
<style>
|
||||
.redbox {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background-color: #ff0000;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="target" class="redbox"></div>
|
||||
|
||||
<script id="main_worklet" type="text/worklet">
|
||||
registerAnimator("duplicate_animator", class {
|
||||
animate(currentTime, effect) {
|
||||
effect.localTime = 500;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
async_test(t => {
|
||||
// Wait for iframe to load and start its animations.
|
||||
window.onmessage = function(msg) {
|
||||
window.requestAnimationFrame( _ => {
|
||||
run_test(msg.data);
|
||||
});
|
||||
};
|
||||
|
||||
// Create and load the iframe to avoid racy cases.
|
||||
var iframe = document.createElement('iframe');
|
||||
iframe.src = 'resources/animator-iframe.html';
|
||||
document.body.appendChild(iframe);
|
||||
|
||||
function run_test(data) {
|
||||
runInAnimationWorklet(
|
||||
document.getElementById('main_worklet').textContent
|
||||
).then(_ => {
|
||||
// Create an animation for duplicate animator.
|
||||
const target = document.getElementById('target');
|
||||
const animation = new WorkletAnimation('duplicate_animator', new KeyframeEffect(target, [{ opacity: 0 }], { duration: 1000 }));
|
||||
animation.play();
|
||||
|
||||
assert_equals(data, '0.4');
|
||||
waitTwoAnimationFrames(t.step_func_done(() => {
|
||||
assert_equals(getComputedStyle(target).opacity, '0.5');
|
||||
}));
|
||||
});
|
||||
}
|
||||
}, 'Both main frame and iframe should update the opacity of their target');
|
||||
</script>
|
33
tests/wpt/web-platform-tests/animation-worklet/common.js
Normal file
33
tests/wpt/web-platform-tests/animation-worklet/common.js
Normal file
|
@ -0,0 +1,33 @@
|
|||
'use strict';
|
||||
|
||||
function registerPassthroughAnimator() {
|
||||
return runInAnimationWorklet(`
|
||||
registerAnimator('passthrough', class {
|
||||
animate(currentTime, effect) { effect.localTime = currentTime; }
|
||||
});
|
||||
`);
|
||||
}
|
||||
|
||||
function runInAnimationWorklet(code) {
|
||||
return CSS.animationWorklet.addModule(
|
||||
URL.createObjectURL(new Blob([code], {type: 'text/javascript'}))
|
||||
);
|
||||
}
|
||||
|
||||
function waitForAnimationFrames(count, callback) {
|
||||
function rafCallback() {
|
||||
if (count <= 0) {
|
||||
callback();
|
||||
} else {
|
||||
count -= 1;
|
||||
window.requestAnimationFrame(rafCallback);
|
||||
}
|
||||
}
|
||||
rafCallback();
|
||||
};
|
||||
|
||||
// Wait for two main thread frames to guarantee that compositor has produced
|
||||
// at least one frame. Note that this is a Chrome-only concept.
|
||||
function waitTwoAnimationFrames(callback) {
|
||||
waitForAnimationFrames(2, callback);
|
||||
};
|
|
@ -0,0 +1,39 @@
|
|||
<!DOCTYPE html>
|
||||
<style>
|
||||
.greenbox {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background-color: #00ff00;
|
||||
}
|
||||
</style>
|
||||
<script src="../common.js"></script>
|
||||
|
||||
<script id="iframe_worklet" type="text/worklet">
|
||||
registerAnimator("iframe_animator", class {
|
||||
animate(currentTime, effect) {
|
||||
effect.localTime = 600;
|
||||
}
|
||||
});
|
||||
registerAnimator("duplicate_animator", class {
|
||||
animate(currentTime, effect) {
|
||||
effect.localTime = 800;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<div id="iframe_target" class="greenbox"></div>
|
||||
|
||||
<script>
|
||||
runInAnimationWorklet(
|
||||
document.getElementById('iframe_worklet').textContent
|
||||
).then(_ => {
|
||||
const target = document.getElementById('iframe_target');
|
||||
// Only create an animation for iframe_animator.
|
||||
const effect = new KeyframeEffect(target, [{ opacity: 0 }], { duration: 1000 });
|
||||
const animation = new WorkletAnimation('iframe_animator', effect);
|
||||
animation.play();
|
||||
waitTwoAnimationFrames( _ => {
|
||||
window.parent.postMessage(getComputedStyle(target).opacity, '*');
|
||||
});
|
||||
});
|
||||
</script>
|
|
@ -0,0 +1,175 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Tests that ScrollTimeline works properly with writing mode and directionality</title>
|
||||
<link rel="help" href="https://drafts.css-houdini.org/css-animationworklet/">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="common.js"></script>
|
||||
|
||||
<script id="worklet_code" type="text/worklet">
|
||||
registerAnimator("test_animator", class {
|
||||
animate(currentTime, effect) {
|
||||
effect.localTime = currentTime;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
// Creates a DOM structure like:
|
||||
// - container
|
||||
// - box {100x100}
|
||||
// - scroller {100x100, writing-mode, direction}
|
||||
// - contents
|
||||
function createTestDOM(x_scroll_axis, writing_mode, direction) {
|
||||
const elements = {};
|
||||
|
||||
elements.container = document.createElement('div');
|
||||
|
||||
elements.box = document.createElement('div');
|
||||
elements.box.style.height = '100px';
|
||||
elements.box.style.width = '100px';
|
||||
|
||||
elements.scroller = document.createElement('div');
|
||||
elements.scroller.style.height = '100px';
|
||||
elements.scroller.style.width = '100px';
|
||||
if (x_scroll_axis)
|
||||
elements.scroller.style.overflowX = 'scroll';
|
||||
else
|
||||
elements.scroller.style.overflowY = 'scroll';
|
||||
elements.scroller.style.direction = direction;
|
||||
elements.scroller.style.writingMode = writing_mode;
|
||||
|
||||
// Callers don't need access to this.
|
||||
const contents = document.createElement('div');
|
||||
contents.style.height = x_scroll_axis ? '100%' : '1000px';
|
||||
contents.style.width = x_scroll_axis ? '1000px' : '100%';
|
||||
|
||||
elements.scroller.appendChild(contents);
|
||||
elements.container.appendChild(elements.box);
|
||||
elements.container.appendChild(elements.scroller);
|
||||
document.body.appendChild(elements.container);
|
||||
|
||||
return elements;
|
||||
}
|
||||
|
||||
function createAndPlayTestAnimation(elements, timeline_orientation) {
|
||||
const effect = new KeyframeEffect(
|
||||
elements.box,
|
||||
[{transform: 'translateY(0)'}, {transform: 'translateY(200px)'}], {
|
||||
duration: 1000,
|
||||
});
|
||||
|
||||
const timeline = new ScrollTimeline({
|
||||
scrollSource: elements.scroller,
|
||||
timeRange: 1000,
|
||||
orientation: timeline_orientation
|
||||
});
|
||||
const animation = new WorkletAnimation('test_animator', effect, timeline);
|
||||
animation.play();
|
||||
}
|
||||
|
||||
setup(setupAndRegisterTests, {explicit_done: true});
|
||||
|
||||
function setupAndRegisterTests() {
|
||||
const worklet_code = document.getElementById('worklet_code').textContent;
|
||||
runInAnimationWorklet(worklet_code).then(() => {
|
||||
// Note that block horizontal-tb is tested implicitly in the basic
|
||||
// ScrollTimeline tests (as it is the default).
|
||||
async_test(
|
||||
block_vertical_lr,
|
||||
'A block ScrollTimeline should produce the correct current time for vertical-lr');
|
||||
async_test(
|
||||
block_vertical_rl,
|
||||
'A block ScrollTimeline should produce the correct current time for vertical-rl');
|
||||
// Again, inline for horizontal-tb and direction: ltr is the default
|
||||
// inline mode and so is tested elsewhere.
|
||||
async_test(
|
||||
inline_horizontal_tb_rtl,
|
||||
'An inline ScrollTimeline should produce the correct current time for horizontal-tb and direction: rtl');
|
||||
async_test(
|
||||
inline_vertical_writing_mode_ltr,
|
||||
'An inline ScrollTimeline should produce the correct current time for vertical writing mode');
|
||||
async_test(
|
||||
inline_vertical_writing_mode_rtl,
|
||||
'An inline ScrollTimeline should produce the correct current time for vertical writing mode and direction: rtl');
|
||||
done();
|
||||
});
|
||||
}
|
||||
|
||||
function block_vertical_lr(t) {
|
||||
const elements = createTestDOM(true, 'vertical-lr', 'ltr');
|
||||
createAndPlayTestAnimation(elements, 'block');
|
||||
|
||||
// Move the scroller to the 25% point.
|
||||
const maxScroll =
|
||||
elements.scroller.scrollWidth - elements.scroller.clientWidth;
|
||||
elements.scroller.scrollLeft = 0.25 * maxScroll;
|
||||
|
||||
waitForAnimationFrames(3, t.step_func_done(() => {
|
||||
assert_equals(
|
||||
getComputedStyle(elements.box).transform, 'matrix(1, 0, 0, 1, 0, 50)');
|
||||
}));
|
||||
}
|
||||
|
||||
function block_vertical_rl(t) {
|
||||
const elements = createTestDOM(true, 'vertical-rl', 'ltr');
|
||||
createAndPlayTestAnimation(elements, 'block');
|
||||
|
||||
// Move the scroller to the 75% point. Since it is vertical-rl, this is
|
||||
// equivalent to the 25% point for the ScrollTimeline.
|
||||
const maxScroll =
|
||||
elements.scroller.scrollWidth - elements.scroller.clientWidth;
|
||||
elements.scroller.scrollLeft = 0.75 * maxScroll;
|
||||
|
||||
waitForAnimationFrames(3, t.step_func_done(() => {
|
||||
assert_equals(
|
||||
getComputedStyle(elements.box).transform, 'matrix(1, 0, 0, 1, 0, 50)');
|
||||
}));
|
||||
}
|
||||
|
||||
function inline_horizontal_tb_rtl(t) {
|
||||
const elements = createTestDOM(true, 'horizontal-tb', 'rtl');
|
||||
createAndPlayTestAnimation(elements, 'inline');
|
||||
|
||||
// Move the scroller to the 75% point. Since it is direction: rtl, this is
|
||||
// equivalent to the 25% point for the ScrollTimeline.
|
||||
const maxScroll =
|
||||
elements.scroller.scrollWidth - elements.scroller.clientWidth;
|
||||
elements.scroller.scrollLeft = 0.75 * maxScroll;
|
||||
|
||||
waitForAnimationFrames(3, t.step_func_done(() => {
|
||||
assert_equals(
|
||||
getComputedStyle(elements.box).transform, 'matrix(1, 0, 0, 1, 0, 50)');
|
||||
}));
|
||||
}
|
||||
|
||||
function inline_vertical_writing_mode_ltr(t) {
|
||||
const elements = createTestDOM(false, 'vertical-lr', 'ltr');
|
||||
createAndPlayTestAnimation(elements, 'inline');
|
||||
|
||||
// Move the scroller to the 25% point.
|
||||
const maxScroll =
|
||||
elements.scroller.scrollHeight - elements.scroller.clientHeight;
|
||||
elements.scroller.scrollTop = 0.25 * maxScroll;
|
||||
|
||||
waitForAnimationFrames(3, t.step_func_done(() => {
|
||||
assert_equals(
|
||||
getComputedStyle(elements.box).transform, 'matrix(1, 0, 0, 1, 0, 50)');
|
||||
}));
|
||||
}
|
||||
|
||||
function inline_vertical_writing_mode_rtl(t) {
|
||||
const elements = createTestDOM(false, 'vertical-lr', 'rtl');
|
||||
createAndPlayTestAnimation(elements, 'inline');
|
||||
|
||||
// Move the scroller to the 75% point. Since this is a vertical writing mode
|
||||
// and direction: rtl, this is 25% of the ScrollTimeline currentTime.
|
||||
const maxScroll =
|
||||
elements.scroller.scrollHeight - elements.scroller.clientHeight;
|
||||
elements.scroller.scrollTop = 0.75 * maxScroll;
|
||||
|
||||
waitForAnimationFrames(3, t.step_func_done(() => {
|
||||
assert_equals(
|
||||
getComputedStyle(elements.box).transform, 'matrix(1, 0, 0, 1, 0, 50)');
|
||||
}));
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,107 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Test that worklet animation works with different fill modes</title>
|
||||
<link rel="help" href="https://drafts.css-houdini.org/css-animationworklet/">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="common.js"></script>
|
||||
|
||||
<style>
|
||||
.target {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background-color: green;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
function CreateTest(target, effect, verify, test_name) {
|
||||
async_test(t => {
|
||||
runInAnimationWorklet(
|
||||
document.getElementById('simple_animate').textContent
|
||||
).then(_ => {
|
||||
const animation = new WorkletAnimation('test_animator', effect);
|
||||
animation.play();
|
||||
|
||||
waitTwoAnimationFrames(() => {
|
||||
// waitTwoAnimationFrames guarantees a compositor frame that could update
|
||||
// the opacity value in the worklet. Meanwhile, getComputedStyle needs an
|
||||
// extra frame to fetch the updated value.
|
||||
window.requestAnimationFrame(t.step_func_done(() => {
|
||||
verify();
|
||||
animation.cancel();
|
||||
}));
|
||||
});
|
||||
});
|
||||
}, test_name);
|
||||
}
|
||||
</script>
|
||||
<script id="simple_animate" type="text/worklet">
|
||||
registerAnimator("test_animator", class {
|
||||
animate(currentTime, effect) {
|
||||
effect.localTime = 2000;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<div id="target1" class='target'></div>
|
||||
<div id="target2" class='target'></div>
|
||||
<div id="target3" class='target'></div>
|
||||
<div id="target4" class='target'></div>
|
||||
<div id="target5" class='target'></div>
|
||||
<div id="target6" class='target'></div>
|
||||
|
||||
<script>
|
||||
const effect_with_fill_forwards = new KeyframeEffect(
|
||||
target1,
|
||||
{ opacity: [0.5, 0] },
|
||||
{ duration: 1000, fill: 'forwards' });
|
||||
CreateTest(target1,
|
||||
effect_with_fill_forwards,
|
||||
function() { assert_equals(getComputedStyle(target1).opacity, '0'); },
|
||||
"Effect with fill mode forwards in after phase produces output that is equivalent to effect's end value.");
|
||||
|
||||
const effect_without_fill_forwards = new KeyframeEffect(
|
||||
target2,
|
||||
{ opacity: [0.5, 0] },
|
||||
{ duration: 1000 });
|
||||
CreateTest(target2,
|
||||
effect_without_fill_forwards,
|
||||
function() { assert_equals(getComputedStyle(target2).opacity, '1'); },
|
||||
'Effect without fill mode forwards in after phase (local time beyond end) should deactivate the animation.');
|
||||
|
||||
const effect_without_fill_forwards_at_end = new KeyframeEffect(
|
||||
target3,
|
||||
{ opacity: [0.5, 0] },
|
||||
{ duration: 2000 });
|
||||
CreateTest(target3,
|
||||
effect_without_fill_forwards_at_end,
|
||||
function() { assert_equals(getComputedStyle(target3).opacity, '1'); },
|
||||
'Effect without fill mode in after phase (local time at end) should deactivate the animation.');
|
||||
|
||||
const effect_with_fill_backwards = new KeyframeEffect(
|
||||
target4,
|
||||
{ opacity: [0.5, 0] },
|
||||
{ duration: 1000, delay: 2001, fill: 'backwards' });
|
||||
CreateTest(target4,
|
||||
effect_with_fill_backwards,
|
||||
function() { assert_equals(getComputedStyle(target4).opacity, '0.5'); },
|
||||
"Effect with fill mode backwards in before phase produces output that is equivalent to effect's start value.");
|
||||
|
||||
const effect_without_fill_backwards = new KeyframeEffect(
|
||||
target5,
|
||||
{ opacity: [0.5, 0] },
|
||||
{ duration: 1000, delay: 2001 });
|
||||
CreateTest(target5,
|
||||
effect_without_fill_backwards,
|
||||
function() { assert_equals(getComputedStyle(target5).opacity, '1'); },
|
||||
'Effect without fill mode backwards in before phase (local time before start) should deactivate the animation.');
|
||||
|
||||
const effect_without_fill_backwards_at_start = new KeyframeEffect(
|
||||
target6,
|
||||
{ opacity: [0.5, 0] },
|
||||
{ duration: 1000, delay: 2000 });
|
||||
CreateTest(target6,
|
||||
effect_without_fill_backwards_at_start,
|
||||
function() { assert_equals(getComputedStyle(target6).opacity, '0.5'); },
|
||||
'Effect with local time at start point is in active phase.');
|
||||
</script>
|
|
@ -0,0 +1,35 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Test that worklet animation with invalid effect cannot be played</title>
|
||||
<link rel="help" href="https://drafts.css-houdini.org/css-animationworklet/">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="common.js"></script>
|
||||
|
||||
<style>
|
||||
#target {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="target"></div>
|
||||
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
test(function() {
|
||||
registerPassthroughAnimator();
|
||||
let playFunc = function() {
|
||||
let effect = new KeyframeEffect(
|
||||
document.getElementById('target'),
|
||||
[
|
||||
// No keyframe.
|
||||
],
|
||||
{ duration: 1000 }
|
||||
);
|
||||
let animation = new WorkletAnimation('passthrough', effect);
|
||||
animation.play();
|
||||
}
|
||||
assert_throws('InvalidStateError', playFunc);
|
||||
}, 'Trying to play invalid worklet animation should throw an exception.');
|
||||
</script>
|
Loading…
Add table
Add a link
Reference in a new issue