test_audioContextGC.html (4340B)
1 <!DOCTYPE HTML> 2 <html> 3 <head> 4 <title>Test inactive AudioContext is garbage collected</title> 5 <script src="/tests/SimpleTest/SimpleTest.js"></script> 6 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> 7 </head> 8 <body> 9 <script class="testbody" type="text/javascript"> 10 11 SimpleTest.waitForExplicitFinish(); 12 13 let ids; 14 15 const observer = (subject, topic, data) => { 16 const id = parseInt(data); 17 if (ids) { 18 ok(ids.delete(id), "Collected AudioNode id " + id); 19 } 20 } 21 SpecialPowers.addObserver(observer, "webaudio-node-demise"); 22 23 SimpleTest.registerCleanupFunction(function() { 24 if (observer) { 25 SpecialPowers.removeObserver(observer, "webaudio-node-demise"); 26 } 27 }); 28 29 function id(node) { 30 return SpecialPowers.getPrivilegedProps(node, "id"); 31 } 32 33 let tests = [{ 34 name: "Bare running AudioContext", setup: () => { 35 const ac = new AudioContext(); 36 ids.add(id(ac.destination)); 37 // Await state change notification before collection. 38 return new Promise((resolve) => { 39 ac.onstatechange = () => { 40 is(ac.state, "running", "ac.state"); 41 resolve(); 42 }; 43 }); 44 } 45 }, { 46 name: "Stopped source", setup: () => { 47 const ac = new AudioContext(); 48 ids.add(id(ac.destination)); 49 const source = new ConstantSourceNode(ac); 50 ids.add(id(source)); 51 source.start(); 52 source.stop(); 53 // Await ended notification before collection. 54 return new Promise((resolve) => { 55 source.onended = () => { 56 is(ac.state, "running", "ac.state"); 57 resolve(); 58 }; 59 }); 60 } 61 }, { 62 name: "OfflineAudioContext not started", setup: () => { 63 const ac = new OfflineAudioContext({ 64 numberOfChannels: 1, length: 1, sampleRate: 48000 65 }); 66 ids.add(id(ac.destination)); 67 const source = new ConstantSourceNode(ac); 68 ids.add(id(source)); 69 source.start(); 70 } 71 }, { 72 name: "Completed OfflineAudioContext", setup: async () => { 73 const ac = new OfflineAudioContext({ 74 numberOfChannels: 1, length: 1, sampleRate: 48000 75 }); 76 ids.add(id(ac.destination)); 77 const sourceBeforeStart = new ConstantSourceNode(ac); 78 ids.add(id(sourceBeforeStart)); 79 sourceBeforeStart.start(); 80 ac.startRendering(); 81 await new Promise((resolve) => { 82 ac.oncomplete = () => { 83 resolve(); 84 }; 85 }); 86 const sourceAfterComplete = new ConstantSourceNode(ac); 87 ids.add(id(sourceAfterComplete)); 88 sourceAfterComplete.start(); 89 } 90 }, { 91 name: "suspended AudioContext", setup: async () => { 92 const ac = new AudioContext(); 93 ids.add(id(ac.destination)); 94 const sourceBeforeSuspend = new ConstantSourceNode(ac); 95 ids.add(id(sourceBeforeSuspend)); 96 sourceBeforeSuspend.start(); 97 ac.suspend(); 98 const sourceAfterSuspend = new ConstantSourceNode(ac); 99 ids.add(id(sourceAfterSuspend)); 100 sourceAfterSuspend.start(); 101 await new Promise((resolve) => { 102 ac.onstatechange = () => { 103 if (ac.state == "suspended") { 104 resolve(); 105 } 106 }; 107 }); 108 const sourceAfterSuspended = new ConstantSourceNode(ac); 109 ids.add(id(sourceAfterSuspended)); 110 sourceAfterSuspended.start(); 111 } 112 }, { 113 name: "closed AudioContext", setup: async () => { 114 const ac = new AudioContext(); 115 ids.add(id(ac.destination)); 116 const sourceBeforeClose = new ConstantSourceNode(ac); 117 ids.add(id(sourceBeforeClose)); 118 sourceBeforeClose.start(); 119 ac.close(); 120 const sourceAfterClose = new ConstantSourceNode(ac); 121 ids.add(id(sourceAfterClose)); 122 sourceAfterClose.start(); 123 await new Promise((resolve) => { 124 ac.onstatechange = () => { 125 if (ac.state == "closed") { 126 resolve(); 127 } 128 }; 129 }); 130 const sourceAfterClosed = new ConstantSourceNode(ac); 131 ids.add(id(sourceAfterClosed)); 132 sourceAfterClosed.start(); 133 } 134 }]; 135 136 const start_next_test = async () => { 137 const test = tests.shift(); 138 if (!test) { 139 SimpleTest.finish(); 140 return; 141 } 142 // Collect all audio nodes from previous tests. 143 if (!ids) { 144 await new Promise(resolve => { 145 SpecialPowers.exactGC(resolve); 146 }); 147 } 148 ids = new Set(); 149 await test.setup(); 150 SpecialPowers.exactGC(() => { 151 is(ids.size, 0, 152 `All expected nodes for "${test.name}" should be collected`); 153 start_next_test(); 154 }); 155 } 156 157 start_next_test(); 158 159 </script> 160 </pre> 161 </body> 162 </html>