chromium/third_party/blink/web_tests/webaudio/internals/scriptprocessornode-premature-death.html

<!DOCTYPE html>
<html>
  <head>
    <title>
      scriptprocessornode-premature-death.html
    </title>
    <script src="../../resources/gc.js"></script>
    <script src="../../resources/js-test.js"></script>
  </head>
  <body>
    <script id="layout-test-code">
      description('Tests that a script processor node is not prematurely GCed');
      window.jsTestIsAsync = true;

      if (!window.internals) {
        testFailed('This test requires window.internals.');
        finishJSTest();
      }

      let wasCalled, wasCollectedPrematurely, savedNode, savedCallback;

      async function test(saveReference, nextStep) {
        debug(
            'Testing ' + (saveReference ? 'with' : 'without') + ' explicitly ' +
            'keeping a reference to the script processor node alive.');

        // Create an audio context
        let context = new OfflineAudioContext(
            2,         // channels
            4096,      // length (frames)
            44100.0);  // sample rate

        // Set up a source, reading from an empty buffer
        let source = context.createBufferSource();
        source.buffer = context.createBuffer(
            2,         // source channels
            4096,      // length (frames)
            44100.0);  // sample rate

        // Set up a script processor node to generate something
        let node = context.createScriptProcessor(
            512,  // buffer size
            0,    // input channels
            2);   // output channels

        // source -> script processor node -> destination
        source.connect(node);
        node.connect(context.destination);

        // Set up something which indicates whether we're called to
        // generate anything

        wasCalled = false;
        let callback = () => {
          wasCalled = true;
        };
        node.onaudioprocess = callback;

        if (saveReference) {
          savedNode = node;
          savedCallback = callback;
        }

        // Watch the callback; if it dies, we're obviously not generating
        // anything

        let observation = internals.observeGC(callback);
        node = callback = null;
        await asyncGC();
        wasCollectedPrematurely = observation.wasCollected;
        source.start(0);
        context.oncomplete = check(nextStep);
        context.startRendering();
      }

      function check(nextStep) {
        return () => {
          shouldBeFalse('wasCollectedPrematurely');
          shouldBeTrue('wasCalled');
          nextStep();
        };
      }

      function step1() {
        test(true, step2);
      }

      function step2() {
        test(false, finishJSTest);
      }

      step1();

      window.successfullyParsed = true;
    </script>
  </body>
</html>