summaryrefslogtreecommitdiffstats
path: root/gfx/layers/apz/test/mochitest/helper_bug1695598.html
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/layers/apz/test/mochitest/helper_bug1695598.html')
-rw-r--r--gfx/layers/apz/test/mochitest/helper_bug1695598.html123
1 files changed, 123 insertions, 0 deletions
diff --git a/gfx/layers/apz/test/mochitest/helper_bug1695598.html b/gfx/layers/apz/test/mochitest/helper_bug1695598.html
new file mode 100644
index 0000000000..fb6102e33d
--- /dev/null
+++ b/gfx/layers/apz/test/mochitest/helper_bug1695598.html
@@ -0,0 +1,123 @@
+<html>
+<head>
+ <title>Test for bug 1695598</title>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <script src="/tests/SimpleTest/paint_listener.js"></script>
+ <script type="application/javascript" src="apz_test_utils.js"></script>
+ <script type="application/javascript" src="apz_test_native_event_utils.js"></script>
+ <script type="text/javascript">
+ let scrollEvents = 100;
+ let i = 0;
+
+ // Scroll points
+ let numscrolls = 0;
+ let last_numscrolls = 0;
+ let start_scrolly = 0;
+ let missed_events = 0;
+ let missed_scroll_updates = 0;
+
+ let utils = SpecialPowers.getDOMWindowUtils(window);
+
+ let timeStamp = document.timeline.currentTime;
+ async function sendScrollEvent(aRafTimestamp) {
+ if (i < scrollEvents) {
+ if (timeStamp == document.timeline.currentTime) {
+ // If we are in a rAF callback at the same time stamp we've already
+ // sent a key event, skip it, otherwise we will not get the
+ // corresponding scroll event for the key event since it will be
+ // coalesced into a single scroll event.
+ window.requestAnimationFrame(sendScrollEvent);
+ return;
+ }
+ timeStamp = document.timeline.currentTime;
+ // Sent a key event in a setTimeout callback so that it will be
+ // processed in between nsRefreshDriver::Tick calls, thus the async
+ // scroll triggered by the key event is going to be processed on the
+ // main-thread before RepaintRequests are processed inside
+ // nsRefreshDriver::Tick, which results there's an async scroll when
+ // RepaintRequests are processed.
+ setTimeout(async () => {
+ window.synthesizeKey("KEY_ArrowDown");
+ i++;
+ // "apz-repaints-flush" is notified in an early runner of
+ // nsRefreshDriver, which means it will be delivered inside
+ // a nsRefreshDriver::Tick call before rAF callbacks.
+ await promiseOnlyApzControllerFlushedWithoutSetTimeout();
+
+ // Wait an animationiteration event since animation events are fired
+ // before rAF callbacks and after scroll events so that it's a good
+ // place to tell whether the expected scroll event got fired or not.
+ await promiseOneEvent(document.getElementById("animation"),
+ "animationiteration", null);
+ if (numscrolls == last_numscrolls) {
+ missed_events++;
+ }
+ if (window.scrollY <= start_scrolly) {
+ missed_scroll_updates++;
+ }
+ last_numscrolls = numscrolls;
+ start_scrolly = window.scrollY;
+ window.requestAnimationFrame(sendScrollEvent);
+ }, 0);
+ } else {
+ // There's a race condition even if we got an "apz-repaints-flush"
+ // notification but any scroll event isn't fired and scroll position
+ // isn't updated since the notification was corresponding to a layers
+ // update triggered by the key event above, which means there was no
+ // repaint request corresponding to APZ animation sample in the time
+ // frame. We allow the case here in the half of key events.
+ ok(missed_events < scrollEvents / 2, `missed event firing ${missed_events} times`);
+ ok(missed_scroll_updates < scrollEvents / 2, `missed scroll update ${missed_scroll_updates} times`);
+ endTest();
+ }
+ }
+
+ async function endTest() {
+ document.removeEventListener("scroll", gotScroll);
+ subtestDone();
+ }
+
+ function gotScroll() {
+ numscrolls++;
+ }
+
+ function startTest() {
+ document.addEventListener("scroll", gotScroll);
+ window.requestAnimationFrame(sendScrollEvent);
+ }
+
+ if (!isApzEnabled()) {
+ ok(true, "APZ not enabled, skipping test");
+ subtestDone();
+ }
+
+ waitUntilApzStable()
+ .then(forceLayerTreeToCompositor)
+ .then(startTest);
+ </script>
+ <style>
+ #content {
+ height: 10000vh;
+ background: repeating-linear-gradient(#EEE, #EEE 100px, #DDD 100px, #DDD 200px);
+ }
+ @keyframes anim {
+ from { opacity: 0; }; /* To avoid churning this scroll test */
+ to { opacity: 0; };
+ }
+ #animation {
+ position: absolute;
+ width: 100px;
+ height: 100px;
+ visibility: hidden; /* for skipping restyles on the main-thread */
+ animation-name: anim;
+ animation-iteration-count: infinite;
+ animation-duration: 1ms; /* to get an animationiteration event in each tick */
+ }
+ </style>
+</head>
+<body>
+ <div id="animation"></div>
+ <div id="content">
+ </div>
+</body>
+</html>