Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

<!DOCTYPE HTML>
<html>
<head>
<title>Test inactive AudioContext is garbage 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();
let ids;
const observer = (subject, topic, data) => {
const id = parseInt(data);
if (ids) {
ok(ids.delete(id), "Collected AudioNode id " + id);
}
}
SpecialPowers.addObserver(observer, "webaudio-node-demise");
SimpleTest.registerCleanupFunction(function() {
if (observer) {
SpecialPowers.removeObserver(observer, "webaudio-node-demise");
}
});
function id(node) {
return SpecialPowers.getPrivilegedProps(node, "id");
}
let tests = [{
name: "Bare running AudioContext", setup: () => {
const ac = new AudioContext();
ids.add(id(ac.destination));
// Await state change notification before collection.
return new Promise((resolve) => {
ac.onstatechange = () => {
is(ac.state, "running", "ac.state");
resolve();
};
});
}
}, {
name: "Stopped source", setup: () => {
const ac = new AudioContext();
ids.add(id(ac.destination));
const source = new ConstantSourceNode(ac);
ids.add(id(source));
source.start();
source.stop();
// Await ended notification before collection.
return new Promise((resolve) => {
source.onended = () => {
is(ac.state, "running", "ac.state");
resolve();
};
});
}
}, {
name: "OfflineAudioContext not started", setup: () => {
const ac = new OfflineAudioContext({
numberOfChannels: 1, length: 1, sampleRate: 48000
});
ids.add(id(ac.destination));
const source = new ConstantSourceNode(ac);
ids.add(id(source));
source.start();
}
}, {
name: "Completed OfflineAudioContext", setup: async () => {
const ac = new OfflineAudioContext({
numberOfChannels: 1, length: 1, sampleRate: 48000
});
ids.add(id(ac.destination));
const sourceBeforeStart = new ConstantSourceNode(ac);
ids.add(id(sourceBeforeStart));
sourceBeforeStart.start();
ac.startRendering();
await new Promise((resolve) => {
ac.oncomplete = () => {
resolve();
};
});
const sourceAfterComplete = new ConstantSourceNode(ac);
ids.add(id(sourceAfterComplete));
sourceAfterComplete.start();
}
}, {
name: "suspended AudioContext", setup: async () => {
const ac = new AudioContext();
ids.add(id(ac.destination));
const sourceBeforeSuspend = new ConstantSourceNode(ac);
ids.add(id(sourceBeforeSuspend));
sourceBeforeSuspend.start();
ac.suspend();
const sourceAfterSuspend = new ConstantSourceNode(ac);
ids.add(id(sourceAfterSuspend));
sourceAfterSuspend.start();
await new Promise((resolve) => {
ac.onstatechange = () => {
if (ac.state == "suspended") {
resolve();
}
};
});
const sourceAfterSuspended = new ConstantSourceNode(ac);
ids.add(id(sourceAfterSuspended));
sourceAfterSuspended.start();
}
}, {
name: "closed AudioContext", setup: async () => {
const ac = new AudioContext();
ids.add(id(ac.destination));
const sourceBeforeClose = new ConstantSourceNode(ac);
ids.add(id(sourceBeforeClose));
sourceBeforeClose.start();
ac.close();
const sourceAfterClose = new ConstantSourceNode(ac);
ids.add(id(sourceAfterClose));
sourceAfterClose.start();
await new Promise((resolve) => {
ac.onstatechange = () => {
if (ac.state == "closed") {
resolve();
}
};
});
const sourceAfterClosed = new ConstantSourceNode(ac);
ids.add(id(sourceAfterClosed));
sourceAfterClosed.start();
}
}];
const start_next_test = async () => {
const test = tests.shift();
if (!test) {
SimpleTest.finish();
return;
}
// Collect all audio nodes from previous tests.
if (!ids) {
await new Promise(resolve => {
SpecialPowers.exactGC(resolve);
});
}
ids = new Set();
await test.setup();
SpecialPowers.exactGC(() => {
is(ids.size, 0,
`All expected nodes for "${test.name}" should be collected`);
start_next_test();
});
}
start_next_test();
</script>
</pre>
</body>
</html>