<!DOCTYPE HTML> <html> <head> <title>Test ScriptProcessorNode in cycle with no listener is collected</title> <script src="/tests/SimpleTest/SimpleTest.js"></script> <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> </head> <body> <script class="testbody" type="text/javascript"> SimpleTest.waitForExplicitFinish(); var observer = function(subject, topic, data) { var id = parseInt(data); var index = ids.indexOf(id); if (index != -1) { ok(true, "Collected AudioNode id " + id + " at index " + index); ids.splice(index, 1); } } SpecialPowers.addObserver(observer, "webaudio-node-demise"); SimpleTest.registerCleanupFunction(function() { if (observer) { SpecialPowers.removeObserver(observer, "webaudio-node-demise"); } }); var ac = new AudioContext(); var testProcessor = ac.createScriptProcessor(256, 1, 0); var delay = ac.createDelay(); testProcessor.connect(delay); delay.connect(testProcessor); var referenceProcessor = ac.createScriptProcessor(256, 1, 0); var gain = ac.createGain(); gain.connect(referenceProcessor); var processCount = 0; testProcessor.onaudioprocess = function(event) { ++processCount; switch (processCount) { case 1: // Switch to listening to referenceProcessor; referenceProcessor.onaudioprocess = event.target.onaudioprocess; referenceProcessor = null; event.target.onaudioprocess = null; break; case 2: // There are no references to testProcessor and so GC can begin. SpecialPowers.exactGC(function() { SpecialPowers.removeObserver(observer, "webaudio-node-demise"); observer = null; event.target.onaudioprocess = null; ok(!ids.length, "All expected nodes should be collected"); SimpleTest.finish(); }); break; } }; function id(node) { return SpecialPowers.getPrivilegedProps(node, "id"); } // Nodes with these ids should be collected. var ids = [ id(testProcessor), id(delay), id(gain) ]; testProcessor = null; delay = null; gain = null; </script> </pre> </body> </html>