summaryrefslogtreecommitdiffstats
path: root/gfx/layers/apz/test/mochitest/helper_hittest_spam.html
blob: cace5491a50516c8b9a79baa5ddd528b3897091b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
<!DOCTYPE HTML>
<html>
<head>
  <title>Test doing lots of hit-testing on a rapidly changing page</title>
  <script type="application/javascript" src="apz_test_utils.js"></script>
  <script type="application/javascript" src="apz_test_native_event_utils.js"></script>
  <script src="/tests/SimpleTest/paint_listener.js"></script>
  <meta name="viewport" content="width=device-width"/>
</head>
<style>
#spamdiv {
    overflow: scroll;
    width: 400px;
    height: 400px;
}
#spamdiv div {
    width: 1000px;
    height: 1000px;
}
</style>
<body>
<script type="application/javascript">

var SPAM_LIMIT = 200; // bigger numbers make the test run longer

// This function adds and removes a scrollable div very rapidly (via
// setTimeout(0) self-scheduling). This causes very frequent layer
// transactions with a new APZ hit-testing tree from the main thread to APZ.
// The div is created afresh every time so that the scroll identifier in
// Gecko is continually increasing, and hit results from a stale tree will
// not be valid on the new tree.
var spamCount = 0;
var spamPoint = null;
function divSpammer() {
  spamCount++;
  if (spamCount >= SPAM_LIMIT) {
    return;
  }
  setTimeout(divSpammer, 0);

  // Remove the div if it exists...
  var spamdiv = document.getElementById('spamdiv');
  if (spamdiv) {
    spamdiv.remove();
    return;
  }
  // ... and add it if it doesn't exist.
  spamdiv = document.createElement('div');
  spamdiv.id = 'spamdiv';
  spamdiv.appendChild(document.createElement('div'));
  document.body.appendChild(spamdiv);
  if (spamPoint == null) {
    spamPoint = centerOf(spamdiv);
  }
}

// This function does continuous hit-testing by scheduling itself over and
// over with setTimeout(0). It hit-tests the same spot and expects to hit
// either the root scrollframe (if the spamdiv is not present in that
// instant) or the spamdiv (if it is present). If the spamdiv is hit, it
// expects the scrollid to be non-decreasing.
var rootScrollId = null;
var lastScrollId = -1;
function hitTestSpammer() {
  if (spamCount >= SPAM_LIMIT) {
    subtestDone();
    return;
  }
  setTimeout(hitTestSpammer, 0);

  if (spamPoint == null) {
    // The very first invocation of this function will have spamPoint as null,
    // and we use that to pick up the rootScrollId.
    ok(rootScrollId == null, "This codepath shouldn't get hit twice");
    rootScrollId = hitTest(centerOf(document.body)).scrollId;
    ok(true, "Root scroll id detected as " + rootScrollId);
    return;
  }

  var scrollId = hitTest(spamPoint).scrollId;
  if (scrollId == rootScrollId) {
    ok(true, "Hit test hit the root scroller, spamdiv is not in compositor");
  } else {
    is(scrollId >= lastScrollId, true, "spamdiv's scroll id is now " + scrollId);
    lastScrollId = scrollId;
  }
}

function startTest() {
  // Make sure to run hitTestSpammer first so the first iteration is while
  // spamPoint is still null.
  setTimeout(hitTestSpammer, 0);
  setTimeout(divSpammer, 0);
}

waitUntilApzStable().then(startTest);

</script>
</body>
</html>