tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

suspend-after-construct.html (2811B)


      1 <!doctype html>
      2 <title>Test AudioContext state updates with suspend() shortly after
      3  construction</title>
      4 <script src=/resources/testharness.js></script>
      5 <script src=/resources/testharnessreport.js></script>
      6 <script>
      7 // A separate async_test is used for tracking state change counts so that it
      8 // can report excess changes after the promise_test for the iteration has
      9 // completed.
     10 const changeCountingTest = async_test('State change counting');
     11 
     12 const doTest = async (testCount) => {
     13  const ctx = new AudioContext();
     14  // Explicitly resume to get a promise to indicate whether the context
     15  // successfully started running.
     16  const resume = ctx.resume();
     17  const suspend = ctx.suspend();
     18  let stateChangesDone = new Promise((resolve) => {
     19    ctx.onstatechange = () => {
     20      ++ctx.stateChangeCount;
     21      changeCountingTest.step(() => {
     22        assert_less_than_equal(ctx.stateChangeCount,
     23                               ctx.expectedStateChangeCount,
     24                               `ctx ${testCount} state change count.`);
     25        assert_equals(ctx.state, ctx.expectedState, `ctx ${testCount} state`);
     26      });
     27      if (ctx.stateChangeCount == ctx.totalStateChangeCount) {
     28        resolve();
     29      }
     30    };
     31  });
     32  ctx.stateChangeCount = 0;
     33  ctx.expectedStateChangeCount = 1;
     34  ctx.expectedState = 'running';
     35  ctx.totalStateChangeCount = 2;
     36  let resumeState = 'pending';
     37  resume.then(() => {
     38    resumeState = 'fulfilled';
     39    assert_equals(ctx.state, 'running', 'state on resume fulfilled.');
     40  }).catch(() => {
     41    // The resume() promise may be rejected if "Attempt to acquire system
     42    // resources" fails.  The spec does not discuss the possibility of a
     43    // subsequent suspend causing such a failure, but accept this as a
     44    // reasonable behavior.
     45    resumeState = 'rejected';
     46    assert_equals(ctx.state, 'suspended', 'state on resume rejected.');
     47    assert_equals(ctx.stateChangeCount, 0);
     48    ctx.expectedStateChangeCount = 0;
     49    stateChangesDone = Promise.resolve();
     50  });
     51  suspend.then(() => {
     52    assert_not_equals(resumeState, 'pending',
     53                      'resume promise should settle before suspend promise.')
     54    if (resumeState == 'fulfilled') {
     55      ++ctx.expectedStateChangeCount;
     56    }
     57    ctx.expectedState = 'suspended';
     58    assert_equals(ctx.state, 'suspended', 'state on suspend fulfilled.');
     59  });
     60  await resume;
     61  await suspend;
     62  await stateChangesDone;
     63 };
     64 
     65 // Repeat the test because Gecko uses different code when there is more than
     66 // one AudioContext.  The third run provides time to check that no further
     67 // state changes from the second run are pending.
     68 for (const testCount of [1, 2, 3]) {
     69  promise_test(() => { return doTest(testCount); }, `Iteration ${testCount}`);
     70 }
     71 promise_test(async () => changeCountingTest.done(), 'Stop waiting');
     72 </script>