DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Mercurial (a461fe03fdb0)

VCS Links

Line Code
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 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Test Behavior During Timer Flood</title>
  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
SimpleTest.waitForExplicitFinish();
// This test takes a long time to run and it times out on Android debug as a result.
SimpleTest.requestLongerTimeout(5);

function onLoad() {
  return new Promise(resolve => {
    addEventListener('load', resolve, { once: true });
  });
}

function setPrefs() {
  // Put timeouts randomly in the tracking or normal buffer.  We do this in order to
  // test to ensure that by default, this will not change the scheduling of timeouts.
  return SpecialPowers.pushPrefEnv({"set": [["dom.timeout_bucketing_strategy", 3]]});
}

// Create a frame that executes a timer flood.  The frame signals
// that is ready once the flood has had a chance to warm up.
function withFloodFrame() {
  return new Promise((resolve, reject) => {
    let frame = document.createElement('iframe');
    addEventListener('message', function onMsg(evt) {
      if (evt.data === 'STARTED') {
        removeEventListener('message', onMsg);
        resolve(frame);
      } else if (evt.data == 'OUT_OF_ORDER') {
        ok(false, "Out of order timeout observed");
        reject();
      }
    });
    frame.src = 'file_timer_flood.html';
    document.body.appendChild(frame);
  });
}

// Test that we can load documents during a timer flood.
function testFrameLoad() {
  return new Promise(resolve => {
    let frame = document.createElement('iframe');
    frame.addEventListener('load', _ => {
      frame.remove();
      resolve();
    }, { once: true });
    document.body.appendChild(frame);
  });
}

// Test that we can perform network requests while a timer flood
// is occuring.
function testFetch(url) {
  return fetch(url).then(response => {
    return response.text();
  });
}

// Test that we can run animations for 5 seconds while a timer
// flood is occuring.
function testRequestAnimationFrame() {
  return new Promise(resolve => {
    let remainingFrames = 5 * 60;
    function nextFrame() {
      remainingFrames -= 1;
      if (remainingFrames > 0) {
        requestAnimationFrame(nextFrame);
      } else {
        resolve();
      }
    };
    requestAnimationFrame(nextFrame);
  });
}

let floodFrame;

onLoad()
.then(setPrefs)
.then(_ => {
  // Start a timer flood in a frame.
  return withFloodFrame();
}).then(frame => {
  floodFrame = frame;

  // Next we are going to start a bunch of asynchronous work that we
  // expect to complete in spite of the timer flood.  The type of work
  // is a bit arbitrary, but is chosen to reflect the kinds of things
  // we would like the browser to be able to do even when pages are
  // abusing timers.  Feel free to add more types of work here, but
  // think carefully before removing anything.
  let tests = [];

  // Verify we can perform a variety of work while the timer flood
  // is running.
  for (let i = 0; i < 20; ++i) {
    tests.push(testFrameLoad());
    tests.push(testFetch('file_timer_flood.html'));
  }
  // Verify that animations still work while the timer flood is running.
  // Note that we do one long run of animations instead of parallel runs
  // like the other activities because of the way requestAnimationFrame()
  // is scheduled.  Parallel animations would not result in any additional
  // runnables be placed on the event queue.
  tests.push(testRequestAnimationFrame());

  // Wait for all tests to finish.  If we do not handle the timer flood
  // well then this will likely time out.
  return Promise.all(tests);
}).then(_ => {
  ok(true, 'completed tests without timing out');
  floodFrame.remove();
  SimpleTest.finish();
}).catch(_ => {
  SimpleTest.finish();
});
</script>
</pre>
</body>
</html>