blob: 9e93f48ab878c5f9208dae7a6d2278cd98ab4529 [file] [log] [blame]
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>
Test get parameterDescriptor as various iterables
</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/webaudio/js/helpers.js"></script>
</head>
<body>
<script id="params">
// A series of AudioParamDescriptors, copied one by one into various iterable
// data structures. This is used by both the processor side and the main
// thread side, so is in a different script tag.
const PARAMS = [
{
name: "a control-rate parameter",
defaultValue: 0.5,
minValue: 0,
maxValue: 1,
automationRate: "a-rate",
},
{
name: "你好",
defaultValue: 2.5,
minValue: 0,
maxValue: 7,
automationRate: "a-rate",
},
{
name: "🎶",
defaultValue: 8.5,
minValue: 0,
maxValue: 11115,
automationRate: "k-rate",
},
];
</script>
<script id="processors" type="worklet">
registerProcessor("set",
class SetParamProcessor extends AudioWorkletProcessor {
static get parameterDescriptors() {
var s = new Set();
s.add(PARAMS[0]);
s.add(PARAMS[1]);
s.add(PARAMS[2]);
return s;
}
constructor() { super(); }
process() {
}
});
registerProcessor("array",
class ArrayParamProcessor extends AudioWorkletProcessor {
static get parameterDescriptors() {
return PARAMS;
}
constructor() { super(); }
process() { }
});
function* gen() {
yield PARAMS[0];
yield PARAMS[1];
yield PARAMS[2];
}
registerProcessor("generator",
class GeneratorParamProcessor extends AudioWorkletProcessor {
static get parameterDescriptors() {
return gen();
}
constructor() { super(); }
process() { }
});
// Test a processor that has a get parameterDescriptors, but it returns
// something that is not iterable.
try {
registerProcessor("invalid",
class InvalidParamProcessor extends AudioWorkletProcessor {
static get parameterDescriptors() {
return 4;
}
constructor() { super(); }
process() { }
});
throw "This should not have been reached.";
} catch (e) {
// unclear how to signal success here, but we can signal failure in the
// developer console
if (e.name != "TypeError") {
throw "This should be TypeError";
}
}
// Test a processor that has a get parameterDescriptors, with a duplicate
// param name something that is not iterable.
try {
registerProcessor("duplicate-param-name",
class DuplicateParamProcessor extends AudioWorkletProcessor {
static get parameterDescriptors() {
var p = {
name: "a",
defaultValue: 1,
minValue: 0,
maxValue: 1,
automationRate: "k-rate",
};
return [p,p];
}
constructor() { super(); }
process() { }
});
throw "This should not have been reached.";
} catch (e) {
// unclear how to signal success here, but we can signal failure in the
// developer console
if (e.name != "NotSupportedError") {
throw "This should be NotSupportedError";
}
}
// Test a processor that has a no get parameterDescriptors.
try {
registerProcessor("no-params",
class NoParamProcessor extends AudioWorkletProcessor {
constructor() { super(); }
process() { }
});
} catch (e) {
throw "Construction should have worked.";
}
</script>
<script>
setup({ explicit_done: true });
// Mangle the PARAMS object into a map that has the same shape as what an
// AudioWorkletNode.parameter property would
var PARAMS_MAP = new Map();
for (var param of PARAMS) {
var o = param;
var name = o.name;
delete o.name;
PARAMS_MAP.set(name, o);
}
// This compares `lhs` and `rhs`, that are two maplike with the same shape
// as PARAMS_MAP.
function compare(testname, lhs, rhs) {
equals(lhs.size, rhs.size, "Map match in size for " + testname);
var i = 0;
for (var [k, v] of lhs) {
is_true(rhs.has(k), testname + ": " + k + " exists in both maps");
var vrhs = rhs.get(k);
["defaultValue", "minValue", "maxValue", "automationRate"].forEach(
paramKey => {
equals(
v[paramKey],
vrhs[paramKey],
`Values for ${k}.${paramKey} match for ${testname}`
);
}
);
}
}
var ac = new AudioContext();
var url = URLFromScriptsElements(["params", "processors"]);
ac.audioWorklet
.addModule(url)
.then(() => {
["set", "array", "generator"].forEach(iterable => {
test(() => {
var node = new AudioWorkletNode(ac, iterable);
compare(iterable, node.parameters, PARAMS_MAP);
}, `Creating an AudioWorkletNode with a ${iterable} for
parameter descriptor worked`);
});
})
.then(function() {
test(function() {
assert_throws_dom("InvalidStateError", function() {
new AudioWorkletNode(ac, "invalid");
});
}, `Attempting to create an AudioWorkletNode with an non
iterable for parameter descriptor should not work`);
})
.then(function() {
test(() => {
new AudioWorkletNode(ac, "no-params");
}, `Attempting to create an AudioWorkletNode from a processor
that does not have a parameterDescriptors getter should work`);
})
.then(function() {
test(function() {
assert_throws_dom("InvalidStateError", function() {
new AudioWorkletNode(ac, "duplicate-param-name");
});
}, `Attempting to create an AudioWorkletNode with two parameter
descriptor with the same name should not work`);
}).then(function() {
done();
});
</script>
</body>
</html>