<html>
<head>
<script src="../../resources/js-test.js"></script>
<script src="../../resources/visibility.js"></script>
<script>
description('<a href="https://bugs.webkit.org/show_bug.cgi?id=98474">Bug 98474</a>: Throttle DOM timers on hidden pages.');
jsTestIsAsync = true;
let testStartTime = 0;
let timerCount = 0;
let requestedInterval = 100;
let timerAlignmentInterval = 1000;
function testTimer() {
++timerCount;
let promise;
// Timer 1 runs when the page is visible.
// Timer 2, 3, 4 run when the page is hidden.
// Timer 5 runs when the page is visible. It finishes the test.
if (timerCount == 1) {
promise = setMainWindowHidden(true);
} else if (timerCount == 4) {
promise = setMainWindowHidden(false);
} else if (timerCount == 5) {
// Timer 1 and 5 add at least `requestedInterval` of delay.
// No throttling, may run as soon as the timeout expires.
// Timer 2 adds at least `requestedInterval` of delay.
// Runs on the first 1-second aligned tick after the
// timeout's expiration. Depending on when the timer is
// scheduled, this may have no effect.
// Timer 3 and 4 add at least `timerAlignmentInterval` of delay.
// Runs on the first 1-second aligned tick after the
// timeout's expiration (which means that it can't be the
// same tick as the previous timer invocation).
//
// Arbitrary delays introduced by the test environment prevent
// setting an upper bound on total execution time. Also, since
// each individual timer could be delayed to run exactly
// `requestedInterval` before the next 1-second aligned tick,
// it is not possible to expect that an individual timer runs at
// least `timerAlignmentInterval` after the previous timer under
// throttling.
totalTime = Date.now() - testStartTime;
shouldBeGreaterThanOrEqual("totalTime", "3 * requestedInterval + 2 * timerAlignmentInterval");
// The test should run in less than a day. Without this check, the
// test could pass simply because `testStartTime` was not initialized.
shouldBeGreaterThanOrEqual("1000 * 60 * 60 * 24", "totalTime");
finishJSTest();
return;
} else {
promise = Promise.resolve();
}
promise.then(() => {
setTimeout(testTimer, requestedInterval);
});
}
function runTest()
{
if (!window.testRunner) {
debug('This test requires testRunner');
return;
}
var requestedIntervalSpans = document.getElementsByClassName('requestedInterval');
for (var i = 0; i < requestedIntervalSpans.length; i++)
requestedIntervalSpans[i].innerText = requestedInterval;
document.getElementById('alignmentInterval').innerText = timerAlignmentInterval / 1000;
testRunner.dumpAsText();
testStartTime = Date.now();
previousTime = testStartTime;
setTimeout(testTimer, requestedInterval);
}
</script>
</head>
<body onload="runTest()">
<p>
This test measures the time taken to fire a <span class="requestedInterval"></span>ms DOM Timer when the page visibility is set to "visible", "hidden", and then back to "visible". Due to page timer throttling, the timer should fire close to <span id="alignmentInterval"></span>s when page is hidden. And it should fire close to <span class="requestedInterval"></span>ms, when the page is visible.
</p>
</body>
</html>