From 099c9e4a7ee37e5fcf3383dc49a9ab6fa907d7cd Mon Sep 17 00:00:00 2001 From: Shannon Booth Date: Wed, 1 May 2024 20:53:39 +1200 Subject: [PATCH] LibWeb: Implement OscillatorNode.type This is a simple getter and setter of the OscillatorType enum, with error checking to not allow 'custom', as that should only be changed through 'setPeriodicWave()'. --- .../Text/expected/WebAudio/OscillatorNode.txt | 4 +++ .../Text/input/WebAudio/OscillatorNode.html | 17 ++++++++++ .../LibWeb/WebAudio/OscillatorNode.cpp | 31 ++++++++++++++++++- .../LibWeb/WebAudio/OscillatorNode.h | 9 ++++++ .../LibWeb/WebAudio/OscillatorNode.idl | 2 +- 5 files changed, 61 insertions(+), 2 deletions(-) diff --git a/Tests/LibWeb/Text/expected/WebAudio/OscillatorNode.txt b/Tests/LibWeb/Text/expected/WebAudio/OscillatorNode.txt index 18da2b5dee5..41a9556b370 100644 --- a/Tests/LibWeb/Text/expected/WebAudio/OscillatorNode.txt +++ b/Tests/LibWeb/Text/expected/WebAudio/OscillatorNode.txt @@ -4,3 +4,7 @@ AudioNode EventTarget Object context: '[object OfflineAudioContext], is same as original: true +Error creating node: 'InvalidStateError: Oscillator node type cannot be set to 'custom'' +oscillator node type: 'sine' +Error: 'InvalidStateError: Oscillator node type cannot be set to 'custom'', type is: sine +oscillator node type: 'triangle' diff --git a/Tests/LibWeb/Text/input/WebAudio/OscillatorNode.html b/Tests/LibWeb/Text/input/WebAudio/OscillatorNode.html index ecb37641215..21cebbae9a9 100644 --- a/Tests/LibWeb/Text/input/WebAudio/OscillatorNode.html +++ b/Tests/LibWeb/Text/input/WebAudio/OscillatorNode.html @@ -15,5 +15,22 @@ // Context getter println(`context: '${oscillator.context}, is same as original: ${audioContext === oscillator.context}`); + + // Invalid type in constructor + try { + new OscillatorNode(audioContext, { type: 'custom' }); + } catch (e) { + println(`Error creating node: '${e}'`); + } + + // Type attribute + println(`oscillator node type: '${oscillator.type}'`); + try { + oscillator.type = 'custom'; + } catch (e) { + println(`Error: '${e}', type is: ${oscillator.type}`); + } + oscillator.type = 'triangle'; + println(`oscillator node type: '${oscillator.type}'`); }); diff --git a/Userland/Libraries/LibWeb/WebAudio/OscillatorNode.cpp b/Userland/Libraries/LibWeb/WebAudio/OscillatorNode.cpp index 49d3e5e0f89..95a72aea9b8 100644 --- a/Userland/Libraries/LibWeb/WebAudio/OscillatorNode.cpp +++ b/Userland/Libraries/LibWeb/WebAudio/OscillatorNode.cpp @@ -23,7 +23,9 @@ WebIDL::ExceptionOr> OscillatorNode::create(JS: WebIDL::ExceptionOr> OscillatorNode::construct_impl(JS::Realm& realm, JS::NonnullGCPtr context, OscillatorOptions const& options) { // FIXME: Invoke "Initialize the AudioNode" steps. - return realm.vm().heap().allocate(realm, realm, context, options); + TRY(verify_valid_type(realm, options.type)); + auto node = realm.vm().heap().allocate(realm, realm, context, options); + return node; } OscillatorNode::OscillatorNode(JS::Realm& realm, JS::NonnullGCPtr context, OscillatorOptions const&) @@ -31,6 +33,33 @@ OscillatorNode::OscillatorNode(JS::Realm& realm, JS::NonnullGCPtr OscillatorNode::verify_valid_type(JS::Realm& realm, Bindings::OscillatorType type) +{ + // The shape of the periodic waveform. It may directly be set to any of the type constant values except + // for "custom". ⌛ Doing so MUST throw an InvalidStateError exception. The setPeriodicWave() method can + // be used to set a custom waveform, which results in this attribute being set to "custom". The default + // value is "sine". When this attribute is set, the phase of the oscillator MUST be conserved. + if (type == Bindings::OscillatorType::Custom) + return WebIDL::InvalidStateError::create(realm, "Oscillator node type cannot be set to 'custom'"_fly_string); + + return {}; +} + +// https://webaudio.github.io/web-audio-api/#dom-oscillatornode-type +WebIDL::ExceptionOr OscillatorNode::set_type(Bindings::OscillatorType type) +{ + TRY(verify_valid_type(realm(), type)); + m_type = type; + return {}; +} + void OscillatorNode::initialize(JS::Realm& realm) { Base::initialize(realm); diff --git a/Userland/Libraries/LibWeb/WebAudio/OscillatorNode.h b/Userland/Libraries/LibWeb/WebAudio/OscillatorNode.h index b254d567bbf..fa04a3c4cd2 100644 --- a/Userland/Libraries/LibWeb/WebAudio/OscillatorNode.h +++ b/Userland/Libraries/LibWeb/WebAudio/OscillatorNode.h @@ -30,11 +30,20 @@ public: static WebIDL::ExceptionOr> create(JS::Realm&, JS::NonnullGCPtr, OscillatorOptions const& = {}); static WebIDL::ExceptionOr> construct_impl(JS::Realm&, JS::NonnullGCPtr, OscillatorOptions const& = {}); + Bindings::OscillatorType type() const; + WebIDL::ExceptionOr set_type(Bindings::OscillatorType); + protected: OscillatorNode(JS::Realm&, JS::NonnullGCPtr, OscillatorOptions const& = {}); virtual void initialize(JS::Realm&) override; virtual void visit_edges(Cell::Visitor&) override; + +private: + static WebIDL::ExceptionOr verify_valid_type(JS::Realm&, Bindings::OscillatorType); + + // https://webaudio.github.io/web-audio-api/#dom-oscillatornode-type + Bindings::OscillatorType m_type { Bindings::OscillatorType::Sine }; }; } diff --git a/Userland/Libraries/LibWeb/WebAudio/OscillatorNode.idl b/Userland/Libraries/LibWeb/WebAudio/OscillatorNode.idl index e17f9bd670e..b77edd61d3f 100644 --- a/Userland/Libraries/LibWeb/WebAudio/OscillatorNode.idl +++ b/Userland/Libraries/LibWeb/WebAudio/OscillatorNode.idl @@ -22,7 +22,7 @@ dictionary OscillatorOptions : AudioNodeOptions { [Exposed=Window] interface OscillatorNode : AudioScheduledSourceNode { constructor(BaseAudioContext context, optional OscillatorOptions options = {}); - // FIXME: attribute OscillatorType type; + attribute OscillatorType type; // FIXME: readonly attribute AudioParam frequency; // FIXME: readonly attribute AudioParam detune; // FIXME: undefined setPeriodicWave(PeriodicWave periodicWave);