Backed out 9 changesets (bug 1141710)

Backed out changeset 0e360d3f690b (bug 1141710)
Backed out changeset c67f9c7dfd4e (bug 1141710)
Backed out changeset 9496b1468d9c (bug 1141710)
Backed out changeset e1330135150d (bug 1141710)
Backed out changeset 0bf9f153d5bc (bug 1141710)
Backed out changeset ac29161a0f98 (bug 1141710)
Backed out changeset ee29275a1748 (bug 1141710)
Backed out changeset 255c9236bb37 (bug 1141710)
Backed out changeset fcd5ac448c46 (bug 1141710)
This commit is contained in:
Wes Kocher 2015-03-10 18:38:28 -07:00
parent b9f1c057ec
commit 9825e5f35a
2 changed files with 133 additions and 194 deletions

View File

@ -19,11 +19,10 @@
</style>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../testcommon.js"></script>
</head>
<body>
<div id="log"></div>
<script type="text/javascript">
<script type="text/javascript;version=1.8">
'use strict';
@ -42,42 +41,13 @@
const CSS_ANIM_EVENTS = ['animationstart', 'animationiteration', 'animationend'];
const ANIM_DELAY_MS = 1000000; // 1000s
const ANIM_DUR_MS = 1000000; // 1000s
const ANIM_PROPERTY_VAL = 'anim ' + ANIM_DUR_MS + 'ms ' + ANIM_DELAY_MS + 'ms';
/**
* These helpers get the value that the startTime needs to be set to, to put an
* animation that uses the above ANIM_DELAY_MS and ANIM_DUR_MS values into the
* middle of various phases or points through the active duration.
*/
function startTimeForBeforePhase(timeline) {
return timeline.currentTime - ANIM_DELAY_MS / 2;
}
function startTimeForActivePhase(timeline) {
return timeline.currentTime - ANIM_DELAY_MS - ANIM_DUR_MS / 2;
}
function startTimeForAfterPhase(timeline) {
return timeline.currentTime - ANIM_DELAY_MS - ANIM_DUR_MS - ANIM_DELAY_MS / 2;
}
function startTimeForStartOfActiveInterval(timeline) {
return timeline.currentTime - ANIM_DELAY_MS;
}
function startTimeForFiftyPercentThroughActiveInterval(timeline) {
return timeline.currentTime - ANIM_DELAY_MS - ANIM_DUR_MS * 0.5;
}
function startTimeForNinetyPercentThroughActiveInterval(timeline) {
return timeline.currentTime - ANIM_DELAY_MS - ANIM_DUR_MS * 0.9;
}
function startTimeForEndOfActiveInterval(timeline) {
return timeline.currentTime - ANIM_DELAY_MS - ANIM_DUR_MS;
}
// Expected computed 'margin-left' values at points during the active interval:
// When we assert_between_inclusive using these values we could in theory cause
// intermittent failure due to very long delays between paints, but since the
// active duration is 1000s long, a delay would need to be around 100s to cause
// that. If that's happening then there are likely other issues that should be
// fixed, so a failure to make us look into that seems like a good thing.
// intermittent failure due to long refresh driver delays, but since the active
// duration is 1000s long, a delay would need to be around 100s to cause that.
// If that's happening than we have issues that we should solve anyway, so a
// failure to make us look into that seems like a good thing.
const UNANIMATED_POSITION = 10;
const INITIAL_POSITION = 100;
const TEN_PCT_POSITION = 110;
@ -85,6 +55,17 @@ const FIFTY_PCT_POSITION = 150;
const NINETY_PCT_POSITION = 190;
const END_POSITION = 200;
function addDiv(id)
{
var div = document.createElement('div');
div.setAttribute('class', 'animated-div');
if (id) {
div.setAttribute('id', id);
}
document.body.appendChild(div);
return div;
}
/**
* CSS animation events fire asynchronously after we set 'startTime'. This
* helper class allows us to handle such events using Promises.
@ -103,7 +84,7 @@ const END_POSITION = 200;
* eventWatcher.stopWatching(); // all done - stop listening for events
* });
*
* This class will assert_unreached() if an event occurs when there is no
* This class will assert_true(false) if an event occurs when there is no
* Promise created by a waitForEvent() call waiting to be fulfilled, or if the
* event is of a different type to the type passed to waitForEvent. This helps
* provide test coverage to ensure that only events that are expected occur, in
@ -121,13 +102,13 @@ function EventWatcher(watchedNode, eventTypes)
function eventHandler(evt) {
if (!waitingFor) {
assert_unreached('Not expecting event, but got: ' + evt.type +
assert_true(false, 'Not expecting event, but got: ' + evt.type +
' targeting element #' + evt.target.getAttribute('id'));
return;
}
if (evt.type != waitingFor.types[0]) {
assert_unreached('Expected ' + waitingFor.types[0] + ' event but got ' +
evt.type + ' event');
assert_true(false, 'Expected ' + waitingFor.types[0] + ' event but got ' +
evt.type + ' event');
return;
}
if (waitingFor.types.length > 1) {
@ -143,8 +124,8 @@ function EventWatcher(watchedNode, eventTypes)
resolveFunc(evt);
}
for (var i = 0; i < eventTypes.length; i++) {
watchedNode.addEventListener(eventTypes[i], eventHandler);
for (let event of eventTypes) {
watchedNode.addEventListener(event, eventHandler);
}
this.waitForEvent = function(type) {
@ -183,8 +164,8 @@ function EventWatcher(watchedNode, eventTypes)
};
this.stopWatching = function() {
for (var i = 0; i < eventTypes.length; i++) {
watchedNode.removeEventListener(eventTypes[i], eventHandler);
for (let event of eventTypes) {
watchedNode.removeEventListener(event, eventHandler);
}
};
@ -225,7 +206,7 @@ function checkStateOnSettingStartTimeToAnimationCreationTime(player)
// Called when the ready Promise's callbacks should happen
function checkStateOnReadyPromiseResolved(player)
{
assert_less_than_equal(player.startTime, player.timeline.currentTime,
assert_less_than_equal(player.startTime, document.timeline.currentTime,
'AnimationPlayer.startTime should be less than the timeline\'s ' +
'currentTime on the first paint tick after animation creation');
@ -307,11 +288,11 @@ function checkStateAtActiveIntervalEndTime(player)
}
test(function(t)
test(function()
{
var div = addDiv(t, {'class': 'animated-div'});
var div = addDiv();
div.style.animation = ANIM_PROPERTY_VAL;
div.style.animation = 'anim ' + ANIM_DUR_MS + 'ms ' + ANIM_DELAY_MS + 'ms';
var player = div.getAnimationPlayers()[0];
@ -334,45 +315,48 @@ test(function(t)
// will be called (async) regardless of whether the Promise was resolved in
// the past or is resolved in the future.
var currentTime = player.timeline.currentTime;
player.startTime = currentTime;
var currentTime = document.timeline.currentTime;
player.startTime = document.timeline.currentTime;
assert_approx_equals(player.startTime, currentTime, 0.0001, // rounding error
'Check setting of startTime actually works');
checkStateOnSettingStartTimeToAnimationCreationTime(player);
div.parentNode.removeChild(div);
}, 'Examine newly created Animation');
async_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
var div = addDiv();
var eventWatcher = new EventWatcher(div, CSS_ANIM_EVENTS);
div.style.animation = ANIM_PROPERTY_VAL;
div.style.animation = 'anim ' + ANIM_DUR_MS + 'ms ' + ANIM_DELAY_MS + 'ms';
var player = div.getAnimationPlayers()[0];
player.ready.then(t.step_func(function() {
checkStateOnReadyPromiseResolved(player);
player.startTime = startTimeForStartOfActiveInterval(player.timeline);
player.startTime = document.timeline.currentTime - ANIM_DELAY_MS; // jump to start of active interval
return eventWatcher.waitForEvent('animationstart');
})).then(t.step_func(function() {
checkStateAtActiveIntervalStartTime(player);
player.startTime = startTimeForFiftyPercentThroughActiveInterval(player.timeline);
player.startTime = document.timeline.currentTime - ANIM_DELAY_MS - ANIM_DUR_MS * 0.5; // 50% through active interval
checkStateAtFiftyPctOfActiveInterval(player);
player.startTime = startTimeForNinetyPercentThroughActiveInterval(player.timeline);
player.startTime = document.timeline.currentTime - ANIM_DELAY_MS - ANIM_DUR_MS * 0.9; // 90% through active interval
checkStateAtNinetyPctOfActiveInterval(player);
player.startTime = startTimeForEndOfActiveInterval(player.timeline);
player.startTime = document.timeline.currentTime - ANIM_DELAY_MS - ANIM_DUR_MS; // end of active interval
return eventWatcher.waitForEvent('animationend');
})).then(t.step_func(function() {
checkStateAtActiveIntervalEndTime(player);
eventWatcher.stopWatching();
div.parentNode.removeChild(div);
})).catch(t.step_func(function(reason) {
assert_unreached(reason);
assert_true(false, reason);
})).then(function() {
t.done();
});
@ -380,14 +364,14 @@ async_test(function(t) {
async_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
var div = addDiv();
var eventWatcher = new EventWatcher(div, CSS_ANIM_EVENTS);
div.style.animation = ANIM_PROPERTY_VAL;
div.style.animation = 'anim ' + ANIM_DUR_MS + 'ms ' + ANIM_DELAY_MS + 'ms';
var player = div.getAnimationPlayers()[0];
player.startTime = startTimeForEndOfActiveInterval(player.timeline);
player.startTime = document.timeline.currentTime - ANIM_DELAY_MS - ANIM_DUR_MS; // end of active interval
// Skipping over the active interval will dispatch an 'animationstart' then
// an 'animationend' event. We need to wait for these events before we start
@ -398,7 +382,7 @@ async_test(function(t) {
// that after the events we're still in the same end time state:
checkStateAtActiveIntervalEndTime(player);
player.startTime = startTimeForNinetyPercentThroughActiveInterval(player.timeline);
player.startTime = document.timeline.currentTime - ANIM_DELAY_MS - ANIM_DUR_MS * 0.9; // 90% through active interval
// Despite going backwards from after the end of the animation to just
// before the end of the animation, we now expect an animationstart event
@ -407,13 +391,13 @@ async_test(function(t) {
})).then(t.step_func(function() {
checkStateAtNinetyPctOfActiveInterval(player);
player.startTime = startTimeForFiftyPercentThroughActiveInterval(player.timeline);
player.startTime = document.timeline.currentTime - ANIM_DELAY_MS - ANIM_DUR_MS * 0.5; // 50% through active interval
checkStateAtFiftyPctOfActiveInterval(player);
player.startTime = startTimeForStartOfActiveInterval(player.timeline);
player.startTime = document.timeline.currentTime - ANIM_DELAY_MS; // jump to start of active interval
checkStateAtActiveIntervalStartTime(player);
player.startTime = player.timeline.currentTime;
player.startTime = document.timeline.currentTime;
// Despite going backwards from just after the active interval starts to
// the animation start time, we now expect an animationend event
// because we went from inside to outside the active interval.
@ -422,8 +406,9 @@ async_test(function(t) {
checkStateOnReadyPromiseResolved(player);
eventWatcher.stopWatching();
div.parentNode.removeChild(div);
})).catch(t.step_func(function(reason) {
assert_unreached(reason);
assert_true(false, reason);
})).then(function() {
t.done();
});
@ -436,133 +421,102 @@ async_test(function(t) {
}, 'Skipping backwards through animation');
// Next we have multiple tests to check that redundant startTime changes do NOT
// Here we have multiple tests to check that redundant startTime changes do NOT
// dispatch events. It's impossible to distinguish between events not being
// dispatched and events just taking an incredibly long time to dispatch
// without waiting an infinitely long time. Obviously we don't want to do that
// (block this test from finishing forever), so instead we just listen for
// events until two animation frames (i.e. requestAnimationFrame callbacks)
// have happened, then assume that no events will ever be dispatched for the
// redundant changes if no events were detected in that time.
// without some sort of risk of creating intermittent failure. We have a short
// timeout here since we don't want to delay the completion of this test file
// waiting for a long time to make "more sure" events weren't dispatched rather
// than being late.
//
// We test:
//
// * before -> active, then back
// * before -> after, then back
// * active -> before, then back
// * active -> after, then back
// * after -> before, then back
// * after -> active, then back
//
// We do all these tests in a single async_test since that allows us to share
// the timeout that we use to wait so that this test file isn't delayed by the
// timeout time multiplied by number of tests.
async_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
var eventWatcher = new EventWatcher(div, CSS_ANIM_EVENTS);
div.style.animation = ANIM_PROPERTY_VAL;
var player = div.getAnimationPlayers()[0];
var divs = new Array(6);
var eventWatchers = new Array(6);
var players = new Array(6);
for (let i = 0; i < 6; i++) {
divs[i] = addDiv();
eventWatchers[i] = new EventWatcher(divs[i], CSS_ANIM_EVENTS);
divs[i].style.animation = 'anim ' + ANIM_DUR_MS + 'ms ' + ANIM_DELAY_MS + 'ms';
players[i] = divs[i].getAnimationPlayers()[0];
}
player.startTime = startTimeForActivePhase(player.timeline);
player.startTime = startTimeForBeforePhase(player.timeline);
var beforeTime = document.timeline.currentTime - ANIM_DELAY_MS / 2;
var activeTime = document.timeline.currentTime - ANIM_DELAY_MS - ANIM_DUR_MS / 2;
var afterTime = document.timeline.currentTime - ANIM_DELAY_MS - ANIM_DUR_MS - ANIM_DELAY_MS / 2;
waitForTwoAnimationFrames().then(function() {
eventWatcher.stopWatching();
// before -> active, then back:
players[0].startTime = activeTime;
players[0].startTime = beforeTime;
// before -> after, then back:
players[1].startTime = afterTime;
players[1].startTime = beforeTime;
// active -> before, then back:
eventWatchers[2].waitForEvent('animationstart').then(function() {
players[2].startTime = beforeTime;
players[2].startTime = activeTime;
});
players[2].startTime = activeTime; // get us into the initial state
// active -> after, then back:
eventWatchers[3].waitForEvent('animationstart').then(function() {
players[3].startTime = afterTime;
players[3].startTime = activeTime;
});
players[3].startTime = activeTime; // get us into the initial state
// after -> before, then back:
eventWatchers[4].waitForEvents(['animationstart', 'animationend']).then(function() {
players[4].startTime = beforeTime;
players[4].startTime = afterTime;
});
players[4].startTime = afterTime; // get us into the initial state
// after -> active, then back:
eventWatchers[5].waitForEvents(['animationstart', 'animationend']).then(function() {
players[5].startTime = activeTime;
players[5].startTime = afterTime;
});
players[5].startTime = afterTime; // get us into the initial state
// See the long comment documenting this async_test for an explanation of
// why we have this timeout and its relationship to intermittent failure.
setTimeout(function() {
for (let i = 0; i < 6; i++) {
eventWatchers[i].stopWatching();
divs[i].parentNode.removeChild(divs[i]);
}
t.done();
});
}, 'Redundant change, before -> active, then back');
async_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
var eventWatcher = new EventWatcher(div, CSS_ANIM_EVENTS);
div.style.animation = ANIM_PROPERTY_VAL;
var player = div.getAnimationPlayers()[0];
player.startTime = startTimeForAfterPhase(player.timeline);
player.startTime = startTimeForBeforePhase(player.timeline);
waitForTwoAnimationFrames().then(function() {
eventWatcher.stopWatching();
t.done();
});
}, 'Redundant change, before -> after, then back');
async_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
var eventWatcher = new EventWatcher(div, CSS_ANIM_EVENTS);
div.style.animation = ANIM_PROPERTY_VAL;
var player = div.getAnimationPlayers()[0];
eventWatcher.waitForEvent('animationstart').then(function() {
player.startTime = startTimeForBeforePhase(player.timeline);
player.startTime = startTimeForActivePhase(player.timeline);
waitForTwoAnimationFrames().then(function() {
eventWatcher.stopWatching();
t.done();
});
});
// get us into the initial state:
player.startTime = startTimeForActivePhase(player.timeline);
}, 'Redundant change, active -> before, then back');
async_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
var eventWatcher = new EventWatcher(div, CSS_ANIM_EVENTS);
div.style.animation = ANIM_PROPERTY_VAL;
var player = div.getAnimationPlayers()[0];
eventWatcher.waitForEvent('animationstart').then(function() {
player.startTime = startTimeForAfterPhase(player.timeline);
player.startTime = startTimeForActivePhase(player.timeline);
waitForTwoAnimationFrames().then(function() {
eventWatcher.stopWatching();
t.done();
});
});
// get us into the initial state:
player.startTime = startTimeForActivePhase(player.timeline);
}, 'Redundant change, active -> after, then back');
async_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
var eventWatcher = new EventWatcher(div, CSS_ANIM_EVENTS);
div.style.animation = ANIM_PROPERTY_VAL;
var player = div.getAnimationPlayers()[0];
eventWatcher.waitForEvents(['animationstart', 'animationend']).then(function() {
player.startTime = startTimeForBeforePhase(player.timeline);
player.startTime = startTimeForAfterPhase(player.timeline);
waitForTwoAnimationFrames().then(function() {
eventWatcher.stopWatching();
t.done();
});
});
// get us into the initial state:
player.startTime = startTimeForAfterPhase(player.timeline);
}, 'Redundant change, after -> before, then back');
async_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
var eventWatcher = new EventWatcher(div, CSS_ANIM_EVENTS);
div.style.animation = ANIM_PROPERTY_VAL;
var player = div.getAnimationPlayers()[0];
eventWatcher.waitForEvents(['animationstart', 'animationend']).then(function() {
player.startTime = startTimeForActivePhase(player.timeline);
player.startTime = startTimeForAfterPhase(player.timeline);
waitForTwoAnimationFrames().then(function() {
eventWatcher.stopWatching();
t.done();
});
});
// get us into the initial state:
player.startTime = startTimeForAfterPhase(player.timeline);
}, 'Redundant change, after -> active, then back');
}, 1000);
}, 'Redundant changes');
async_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
div.style.animation = ANIM_PROPERTY_VAL;
var div = addDiv();
div.style.animation = 'anim ' + ANIM_DUR_MS + 'ms ' + ANIM_DELAY_MS + 'ms';
var player = div.getAnimationPlayers()[0];
player.ready.then(t.step_func(function() {
player.startTime = null;
return player.ready;
})).then(t.step_func(function() {
div.parentNode.removeChild(div);
})).catch(t.step_func(function(reason) {
assert_unreached(reason);
assert_true(false, reason);
})).then(function() {
t.done();
});
@ -570,7 +524,7 @@ async_test(function(t) {
async_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
var div = addDiv();
div.style.animation = 'anim 100s';
var player = div.getAnimationPlayers()[0];
@ -586,8 +540,10 @@ async_test(function(t) {
'AnimationPlayer.startTime is null after paused');
assert_equals(player.playState, 'paused',
'AnimationPlayer.playState is "paused" after pause() call');
div.parentNode.removeChild(div);
})).catch(t.step_func(function(reason) {
assert_unreached(reason);
assert_true(false, reason);
})).then(function() {
t.done();
});

View File

@ -44,20 +44,3 @@ function waitForFrame() {
function waitForAllPlayers(players) {
return Promise.all(players.map(function(player) { return player.ready; }));
}
/**
* Returns a Promise that is resolved after the next two animation frames have
* occured (that is, after two consecutive requestAnimationFrame callbacks
* have been called).
*/
function waitForTwoAnimationFrames()
{
return new Promise(function(resolve, reject) {
window.requestAnimationFrame(function() {
window.requestAnimationFrame(function() {
resolve();
});
});
});
}