Bug 1688475 - Remove usage of waitForApzFlushedRepaints from test_scroll_behavior.html. r=botond

This involved flattening the entire callback structure of the test
into async/await style.

Differential Revision: https://phabricator.services.mozilla.com/D103125
This commit is contained in:
Kartikaya Gupta 2021-02-01 23:52:31 +00:00
Родитель 8824e4e242
Коммит 46fa04cc0c
1 изменённых файлов: 121 добавлений и 156 удалений

Просмотреть файл

@ -35,59 +35,55 @@
SpecialPowers.pushPrefEnv(
{ 'set': [['layout.css.scroll-behavior.enabled', true]] },
function () {
testScrollBehaviorInterruption(function() {
testScrollBehaviorFramerate(function() {
window.scrollTo(0,0);
SimpleTest.finish();
});
});
async function () {
await testScrollBehaviorInterruption();
await testScrollBehaviorFramerate();
window.scrollTo(0,0);
SimpleTest.finish();
}
);
});
function testScrollBehaviorInterruption(nextTest) {
async function testScrollBehaviorInterruption() {
// Take control of refresh driver
SpecialPowers.DOMWindowUtils.advanceTimeAndRefresh(0);
waitForApzFlushedRepaints(function() {
await promiseApzFlushedRepaints();
window.scrollTo(10, 9);
ok(window.scrollX == 10 && window.scrollY == 9,
"instant scroll-behavior must be synchronous when setting initial position");
window.scrollTo(10, 9);
ok(window.scrollX == 10 && window.scrollY == 9,
"instant scroll-behavior must be synchronous when setting initial position");
window.scrollTo(15, 16);
ok(window.scrollX == 15 && window.scrollY == 16,
"instant scroll-behavior must be synchronous when setting new position");
window.scrollTo(15, 16);
ok(window.scrollX == 15 && window.scrollY == 16,
"instant scroll-behavior must be synchronous when setting new position");
window.scrollTo({left: 100, top: 200, behavior: 'smooth'});
ok(window.scrollX == 15 && window.scrollY == 16,
"smooth scroll-behavior must be asynchronous");
window.scrollTo({left: 100, top: 200, behavior: 'smooth'});
ok(window.scrollX == 15 && window.scrollY == 16,
"smooth scroll-behavior must be asynchronous");
SpecialPowers.DOMWindowUtils.advanceTimeAndRefresh(100);
waitForApzFlushedRepaints(function() {
ok(window.scrollX != 15 && window.scrollY != 16
&& window.scrollX != 100 && window.scrollY != 200,
"smooth scroll-behavior must be triggered by window.scrollTo");
SpecialPowers.DOMWindowUtils.advanceTimeAndRefresh(100);
await promiseApzFlushedRepaints();
window.scrollTo(50, 52);
ok(window.scrollX == 50 && window.scrollY == 52,
"instant scroll-behavior must interrupt smooth scroll-behavior animation");
ok(window.scrollX != 15 && window.scrollY != 16
&& window.scrollX != 100 && window.scrollY != 200,
"smooth scroll-behavior must be triggered by window.scrollTo");
SpecialPowers.DOMWindowUtils.advanceTimeAndRefresh(100);
waitForApzFlushedRepaints(function() {
ok(window.scrollX == 50 && window.scrollY == 52,
"smooth scroll-behavior animation must stop after being interrupted");
window.scrollTo(50, 52);
ok(window.scrollX == 50 && window.scrollY == 52,
"instant scroll-behavior must interrupt smooth scroll-behavior animation");
// Release control of refresh driver
SpecialPowers.DOMWindowUtils.restoreNormalRefresh();
waitForApzFlushedRepaints(nextTest);
});
});
});
SpecialPowers.DOMWindowUtils.advanceTimeAndRefresh(100);
await promiseApzFlushedRepaints();
ok(window.scrollX == 50 && window.scrollY == 52,
"smooth scroll-behavior animation must stop after being interrupted");
// Release control of refresh driver
SpecialPowers.DOMWindowUtils.restoreNormalRefresh();
await promiseApzFlushedRepaints();
}
function testScrollBehaviorFramerate(nextTest) {
async function testScrollBehaviorFramerate() {
/**
* CSSOM-View scroll-behavior smooth scroll animations must produce the
* same results indendently of frame-rate:
@ -116,16 +112,9 @@
{x: 1, y: 100},
{x: -100, y: 50000} ];
var deltaIndex = 0;
function testDeltas() {
if(deltaIndex >= deltas.length) {
nextTest();
return;
}
for (var deltaIndex = 0; deltaIndex < deltas.length; deltaIndex++) {
var deltaX = deltas[deltaIndex].x;
var deltaY = deltas[deltaIndex].y;
deltaIndex++;
// startX and startY must be at least as big as the greatest negative
// number in the deltas array in order to prevent the animation from
@ -136,91 +125,79 @@
var endY = startY + deltaY;
var referenceTimeStep = Math.floor(1000 / referenceFrameRate);
sampleAnimation(startX, startY, endX, endY,
referenceTimeStep, function(refSamples) {
let refSamples = await sampleAnimation(startX, startY, endX, endY,
referenceTimeStep);
var referenceDuration = refSamples.length * referenceTimeStep; // ms
var referenceDuration = refSamples.length * referenceTimeStep; // ms
var frameRateIndex=0;
for (var frameRateIndex = 0; frameRateIndex < frameRates.length; frameRateIndex++) {
var frameRate = frameRates[frameRateIndex];
function testFrameRate() {
if(frameRateIndex < frameRates.length) {
var frameRate = frameRates[frameRateIndex++];
var testTimeStep = Math.floor(1000 / frameRate);
var testTimeStep = Math.floor(1000 / frameRate);
sampleAnimation(startX, startY, endX, endY,
testTimeStep, function(testSamples) {
var testDuration = testSamples.length * testTimeStep; // ms
let testSamples = await sampleAnimation(startX, startY, endX, endY,
testTimeStep);
var testDuration = testSamples.length * testTimeStep; // ms
// Variance in duration of animation must be accurate to within one
// frame interval
var durationVariance = Math.max(0, Math.abs(testDuration - referenceDuration) - testTimeStep);
is(durationVariance, 0, 'Smooth scroll animation duration must not '
+ 'be framerate dependent at deltaX: ' + deltaX + ', deltaY: '
+ deltaY + ', frameRate: ' + frameRate + 'fps');
// Variance in duration of animation must be accurate to within one
// frame interval
var durationVariance = Math.max(0, Math.abs(testDuration - referenceDuration) - testTimeStep);
is(durationVariance, 0, 'Smooth scroll animation duration must not '
+ 'be framerate dependent at deltaX: ' + deltaX + ', deltaY: '
+ deltaY + ', frameRate: ' + frameRate + 'fps');
var maxVariance = 0;
testSamples.forEach(function(sample, sampleIndex) {
var maxVariance = 0;
testSamples.forEach(function(sample, sampleIndex) {
var testToRef = refSamples.length / testSamples.length;
var refIndexThisFrame = clamp(Math.floor(sampleIndex * testToRef),
0, refSamples.length - 1);
var refIndexPrevFrame = clamp(Math.floor((sampleIndex - 1) * testToRef),
0, refSamples.length - 1);
var refIndexNextFrame = clamp(Math.floor((sampleIndex + 1) * testToRef),
0, refSamples.length - 1);
var testToRef = refSamples.length / testSamples.length;
var refIndexThisFrame = clamp(Math.floor(sampleIndex * testToRef),
0, refSamples.length - 1);
var refIndexPrevFrame = clamp(Math.floor((sampleIndex - 1) * testToRef),
0, refSamples.length - 1);
var refIndexNextFrame = clamp(Math.floor((sampleIndex + 1) * testToRef),
0, refSamples.length - 1);
var refSampleThisFrame = refSamples[refIndexThisFrame];
var refSamplePrevFrame = refSamples[refIndexPrevFrame];
var refSampleNextFrame = refSamples[refIndexNextFrame];
var refSampleThisFrame = refSamples[refIndexThisFrame];
var refSamplePrevFrame = refSamples[refIndexPrevFrame];
var refSampleNextFrame = refSamples[refIndexNextFrame];
var refXMin = Math.min(refSamplePrevFrame[0],
refSampleThisFrame[0],
refSampleNextFrame[0]);
var refXMin = Math.min(refSamplePrevFrame[0],
refSampleThisFrame[0],
refSampleNextFrame[0]);
var refYMin = Math.min(refSamplePrevFrame[1],
refSampleThisFrame[1],
refSampleNextFrame[1]);
var refYMin = Math.min(refSamplePrevFrame[1],
refSampleThisFrame[1],
refSampleNextFrame[1]);
var refXMax = Math.max(refSamplePrevFrame[0],
refSampleThisFrame[0],
refSampleNextFrame[0]);
var refXMax = Math.max(refSamplePrevFrame[0],
refSampleThisFrame[0],
refSampleNextFrame[0]);
var refYMax = Math.max(refSamplePrevFrame[1],
refSampleThisFrame[1],
refSampleNextFrame[1]);
var refYMax = Math.max(refSamplePrevFrame[1],
refSampleThisFrame[1],
refSampleNextFrame[1]);
// Varience is expected to be at most 1 pixel beyond the range,
// due to integer rounding of pixel position.
var positionTolerance = 1; // 1 pixel
// Varience is expected to be at most 1 pixel beyond the range,
// due to integer rounding of pixel position.
var positionTolerance = 1; // 1 pixel
maxVariance = Math.max(maxVariance,
refXMin - sample[0] - positionTolerance,
sample[0] - refXMax - positionTolerance,
refYMin - sample[1] - positionTolerance,
sample[1] - refYMax - positionTolerance);
});
maxVariance = Math.max(maxVariance,
refXMin - sample[0] - positionTolerance,
sample[0] - refXMax - positionTolerance,
refYMin - sample[1] - positionTolerance,
sample[1] - refYMax - positionTolerance);
});
is(maxVariance, 0, 'Smooth scroll animated position must not be '
+ 'framerate dependent at deltaX: ' + deltaX + ', deltaY: '
+ deltaY + ', frameRate: ' + frameRate + 'fps');
testFrameRate();
});
} else {
waitForApzFlushedRepaints(testDeltas);
}
}
is(maxVariance, 0, 'Smooth scroll animated position must not be '
+ 'framerate dependent at deltaX: ' + deltaX + ', deltaY: '
+ deltaY + ', frameRate: ' + frameRate + 'fps');
}
testFrameRate();
});
await promiseApzFlushedRepaints();
}
testDeltas();
}
function sampleAnimation(startX, startY, endX, endY, timeStep, callback) {
async function sampleAnimation(startX, startY, endX, endY, timeStep) {
// The animation must be stopped at the destination position for
// minStoppedFrames consecutive frames to detect that the animation has
// completed.
@ -237,57 +214,45 @@
// Take control of refresh driver so we can synthesize
// various frame rates
SpecialPowers.DOMWindowUtils.advanceTimeAndRefresh(0);
waitForApzFlushedRepaints(function() {
await promiseApzFlushedRepaints();
window.scrollTo(startX, startY);
window.scrollTo({left: endX, top: endY, behavior: 'smooth'});
window.scrollTo(startX, startY);
window.scrollTo({left: endX, top: endY, behavior: 'smooth'});
var currentTime = 0; // ms
var currentTime = 0; // ms
function advanceTime() {
if(currentTime < maxTime && frameCountAtDestination < 15) {
while (currentTime < maxTime && frameCountAtDestination < 15) {
positionSamples.push([window.scrollX, window.scrollY]);
positionSamples.push([window.scrollX, window.scrollY]);
currentTime += timeStep;
SpecialPowers.DOMWindowUtils.advanceTimeAndRefresh(timeStep);
waitForApzFlushedRepaints(function() {
if (window.scrollX == endX && window.scrollY == endY) {
frameCountAtDestination++;
} else {
frameCountAtDestination = 0;
}
advanceTime();
});
} else {
isnot(frameCountAtDestination, 0,
'Smooth scrolls must always end at their destination '
+ 'unless they are interrupted, at deltaX: '
+ (endX - startX) + ', deltaY: ' + (endY - startY));
window.scrollTo(0, 0);
// Release control of refresh driver
SpecialPowers.DOMWindowUtils.restoreNormalRefresh();
waitForApzFlushedRepaints(function() {
// We must not include the duplicated frames at the animation
// destination as the tests are dependant on the total duration of
// the animation to be accurate.
positionSamples.splice(1 - minStoppedFrames,
minStoppedFrames - 1);
callback(positionSamples);
});
}
currentTime += timeStep;
SpecialPowers.DOMWindowUtils.advanceTimeAndRefresh(timeStep);
await promiseApzFlushedRepaints();
if (window.scrollX == endX && window.scrollY == endY) {
frameCountAtDestination++;
} else {
frameCountAtDestination = 0;
}
}
advanceTime();
isnot(frameCountAtDestination, 0,
'Smooth scrolls must always end at their destination '
+ 'unless they are interrupted, at deltaX: '
+ (endX - startX) + ', deltaY: ' + (endY - startY));
});
window.scrollTo(0, 0);
// Release control of refresh driver
SpecialPowers.DOMWindowUtils.restoreNormalRefresh();
await promiseApzFlushedRepaints();
// We must not include the duplicated frames at the animation
// destination as the tests are dependant on the total duration of
// the animation to be accurate.
positionSamples.splice(1 - minStoppedFrames,
minStoppedFrames - 1);
return positionSamples;
}
</script>