LibWeb: Validate AudioNode::connect() input and output arguments

This commit is contained in:
Tim Ledbetter 2025-01-04 02:21:16 +00:00 committed by Tim Ledbetter
parent e6334d217b
commit 2edd0812ca
Notes: github-actions[bot] 2025-01-09 11:35:56 +00:00
4 changed files with 138 additions and 5 deletions

View file

@ -59,18 +59,35 @@ WebIDL::ExceptionOr<GC::Ref<AudioNode>> AudioNode::connect(GC::Ref<AudioNode> de
return WebIDL::InvalidAccessError::create(realm(), "Cannot connect to an AudioNode in a different AudioContext"_string);
}
(void)output;
(void)input;
// The output parameter is an index describing which output of the AudioNode from which to connect.
// If this parameter is out-of-bounds, an IndexSizeError exception MUST be thrown.
if (output >= number_of_outputs()) {
return WebIDL::IndexSizeError::create(realm(), MUST(String::formatted("Output index {} exceeds number of outputs", output)));
}
// The input parameter is an index describing which input of the destination AudioNode to connect to.
// If this parameter is out-of-bounds, an IndexSizeError exception MUST be thrown.
if (input >= destination_node->number_of_inputs()) {
return WebIDL::IndexSizeError::create(realm(), MUST(String::formatted("Input index '{}' exceeds number of inputs", input)));
}
dbgln("FIXME: Implement Audio::connect(AudioNode)");
return destination_node;
}
// https://webaudio.github.io/web-audio-api/#dom-audionode-connect-destinationparam-output
void AudioNode::connect(GC::Ref<AudioParam> destination_param, WebIDL::UnsignedLong output)
WebIDL::ExceptionOr<void> AudioNode::connect(GC::Ref<AudioParam> destination_param, WebIDL::UnsignedLong output)
{
(void)destination_param;
(void)output;
// The output parameter is an index describing which output of the AudioNode from which to connect.
// If the parameter is out-of-bounds, an IndexSizeError exception MUST be thrown.
if (output >= number_of_outputs()) {
return WebIDL::IndexSizeError::create(realm(), MUST(String::formatted("Output index {} exceeds number of outputs", output)));
}
dbgln("FIXME: Implement AudioNode::connect(AudioParam)");
return {};
}
// https://webaudio.github.io/web-audio-api/#dom-audionode-disconnect

View file

@ -37,7 +37,7 @@ public:
virtual ~AudioNode() override;
WebIDL::ExceptionOr<GC::Ref<AudioNode>> connect(GC::Ref<AudioNode> destination_node, WebIDL::UnsignedLong output = 0, WebIDL::UnsignedLong input = 0);
void connect(GC::Ref<AudioParam> destination_param, WebIDL::UnsignedLong output = 0);
WebIDL::ExceptionOr<void> connect(GC::Ref<AudioParam> destination_param, WebIDL::UnsignedLong output = 0);
void disconnect();
void disconnect(WebIDL::UnsignedLong output);

View file

@ -0,0 +1,23 @@
Harness status: OK
Found 18 tests
18 Pass
Pass # AUDIT TASK RUNNER STARTED.
Pass Executing "test"
Pass Audit report
Pass > [test] Basic tests for AudioNode API.
Pass AudioBufferSource.numberOfInputs is equal to 0.
Pass AudioBufferSource.numberOfOutputs is equal to 1.
Pass AudioContext.destination.numberOfInputs is equal to 1.
Pass AudioContext.destination.numberOfOutputs is equal to 1.
Pass audioNode.connect(0, 0, 0) threw TypeError: "Not an object of type AudioNode".
Pass audioNode.connect(null, 0, 0) threw TypeError: "Not an object of type AudioNode".
Pass audioNode.connect(context.destination, 5, 0) threw IndexSizeError: "Output index 5 exceeds number of outputs".
Pass audioNode.connect(context.destination, 0, 5) threw IndexSizeError: "Input index '5' exceeds number of inputs".
Pass audioNode.connect(context.destination, 0, 0) did not throw an exception.
Pass Connecting a node to a different context threw InvalidAccessError: "Cannot connect to an AudioNode in a different AudioContext".
Pass context3 = new AudioContext(1, 44100, 44100) threw TypeError: "Not an object of type AudioContextOptions".
Pass AudioNode is an EventTarget is true.
Pass < [test] All assertions passed. (total 12 assertions)
Pass # AUDIT TASK RUNNER FINISHED: 1 tasks ran successfully.

View file

@ -0,0 +1,93 @@
<!DOCTYPE html>
<html>
<head>
<title>
audionode.html
</title>
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<script src="../../../webaudio/resources/audit-util.js"></script>
<script src="../../../webaudio/resources/audit.js"></script>
</head>
<body>
<div id="description"></div>
<div id="console"></div>
<script id="layout-test-code">
let audit = Audit.createTaskRunner();
let context = 0;
let context2 = 0;
let context3 = 0;
audit.define(
{label: 'test', description: 'Basic tests for AudioNode API.'},
function(task, should) {
context = new AudioContext();
window.audioNode = context.createBufferSource();
// Check input and output numbers of AudioSourceNode.
should(audioNode.numberOfInputs, 'AudioBufferSource.numberOfInputs')
.beEqualTo(0);
should(
audioNode.numberOfOutputs, 'AudioBufferSource.numberOfOutputs')
.beEqualTo(1);
// Check input and output numbers of AudioDestinationNode
should(
context.destination.numberOfInputs,
'AudioContext.destination.numberOfInputs')
.beEqualTo(1);
should(
context.destination.numberOfOutputs,
'AudioContext.destination.numberOfOutputs')
.beEqualTo(1);
// Try calling connect() method with illegal values.
should(
() => audioNode.connect(0, 0, 0), 'audioNode.connect(0, 0, 0)')
.throw(TypeError);
should(
() => audioNode.connect(null, 0, 0),
'audioNode.connect(null, 0, 0)')
.throw(TypeError);
should(
() => audioNode.connect(context.destination, 5, 0),
'audioNode.connect(context.destination, 5, 0)')
.throw(DOMException, 'IndexSizeError');
should(
() => audioNode.connect(context.destination, 0, 5),
'audioNode.connect(context.destination, 0, 5)')
.throw(DOMException, 'IndexSizeError');
should(
() => audioNode.connect(context.destination, 0, 0),
'audioNode.connect(context.destination, 0, 0)')
.notThrow();
// Create a new context and try to connect the other context's node
// to this one.
context2 = new AudioContext();
should(
() => window.audioNode.connect(context2.destination),
'Connecting a node to a different context')
.throw(DOMException, 'InvalidAccessError');
// 3-arg AudioContext doesn't create an offline context anymore.
should(
() => context3 = new AudioContext(1, 44100, 44100),
'context3 = new AudioContext(1, 44100, 44100)')
.throw(TypeError);
// Ensure it is an EventTarget
should(
audioNode instanceof EventTarget, 'AudioNode is an EventTarget')
.beTrue();
task.done();
});
audit.run();
</script>
</body>
</html>